BigW Consortium Gitlab

irker_worker.rb 4.75 KB
Newer Older
Aorimn committed
1 2 3 4 5
require 'json'
require 'socket'

class IrkerWorker
  include Sidekiq::Worker
6
  include DedicatedSidekiqQueue
Aorimn committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

  def perform(project_id, chans, colors, push_data, settings)
    project = Project.find(project_id)

    # Get config parameters
    return false unless init_perform settings, chans, colors

    repo_name = push_data['repository']['name']
    committer = push_data['user_name']
    branch = push_data['ref'].gsub(%r'refs/[^/]*/', '')

    if @colors
      repo_name = "\x0304#{repo_name}\x0f"
      branch = "\x0305#{branch}\x0f"
    end

23
    # First messages are for branch creation/deletion
Aorimn committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37
    send_branch_updates push_data, project, repo_name, committer, branch

    # Next messages are for commits
    send_commits push_data, project, repo_name, committer, branch

    close_connection
    true
  end

  private

  def init_perform(set, chans, colors)
    @colors = colors
    @channels = chans
38
    start_connection set['server_host'], set['server_port']
Aorimn committed
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
  end

  def start_connection(irker_server, irker_port)
    begin
      @socket = TCPSocket.new irker_server, irker_port
    rescue Errno::ECONNREFUSED => e
      logger.fatal "Can't connect to Irker daemon: #{e}"
      return false
    end
    true
  end

  def sendtoirker(privmsg)
    to_send = { to: @channels, privmsg: privmsg }
    @socket.puts JSON.dump(to_send)
  end

  def close_connection
    @socket.close
  end

  def send_branch_updates(push_data, project, repo_name, committer, branch)
61
    if Gitlab::Git.blank_ref?(push_data['before'])
Aorimn committed
62
      send_new_branch project, repo_name, committer, branch
63
    elsif Gitlab::Git.blank_ref?(push_data['after'])
Aorimn committed
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
      send_del_branch repo_name, committer, branch
    end
  end

  def send_new_branch(project, repo_name, committer, branch)
    repo_path = project.path_with_namespace
    newbranch = "#{Gitlab.config.gitlab.url}/#{repo_path}/branches"
    newbranch = "\x0302\x1f#{newbranch}\x0f" if @colors

    privmsg = "[#{repo_name}] #{committer} has created a new branch "
    privmsg += "#{branch}: #{newbranch}"
    sendtoirker privmsg
  end

  def send_del_branch(repo_name, committer, branch)
    privmsg = "[#{repo_name}] #{committer} has deleted the branch #{branch}"
    sendtoirker privmsg
  end

  def send_commits(push_data, project, repo_name, committer, branch)
    return if push_data['total_commits_count'] == 0

    # Next message is for number of commit pushed, if any
87
    if Gitlab::Git.blank_ref?(push_data['before'])
Aorimn committed
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
      # Tweak on push_data["before"] in order to have a nice compare URL
      push_data['before'] = before_on_new_branch push_data, project
    end

    send_commits_count(push_data, project, repo_name, committer, branch)

    # One message per commit, limited by 3 messages (same limit as the
    # github irc hook)
    commits = push_data['commits'].first(3)
    commits.each do |hook_attrs|
      send_one_commit project, hook_attrs, repo_name, branch
    end
  end

  def before_on_new_branch(push_data, project)
    commit = commit_from_id project, push_data['commits'][0]['id']
    parents = commit.parents
    # Return old value if there's no new one
    return push_data['before'] if parents.empty?
    # Or return the first parent-commit
    parents[0].id
  end

  def send_commits_count(data, project, repo, committer, branch)
    url = compare_url data, project.path_with_namespace
    commits = colorize_commits data['total_commits_count']

    new_commits = 'new commit'
    new_commits += 's' if data['total_commits_count'] > 1

    sendtoirker "[#{repo}] #{committer} pushed #{commits} #{new_commits} " \
                "to #{branch}: #{url}"
  end

  def compare_url(data, repo_path)
123 124
    sha1 = Commit.truncate_sha(data['before'])
    sha2 = Commit.truncate_sha(data['after'])
Aorimn committed
125 126 127 128 129 130 131
    compare_url = "#{Gitlab.config.gitlab.url}/#{repo_path}/compare"
    compare_url += "/#{sha1}...#{sha2}"
    colorize_url compare_url
  end

  def send_one_commit(project, hook_attrs, repo_name, branch)
    commit = commit_from_id project, hook_attrs['id']
132
    sha = colorize_sha Commit.truncate_sha(hook_attrs['id'])
Aorimn committed
133 134 135 136 137 138 139 140
    author = hook_attrs['author']['name']
    files = colorize_nb_files(files_count commit)
    title = commit.title

    sendtoirker "#{repo_name}/#{branch} #{sha} #{author} (#{files}): #{title}"
  end

  def commit_from_id(project, id)
141
    project.commit(id)
Aorimn committed
142 143 144
  end

  def files_count(commit)
145
    diff_size = commit.raw_deltas.size
146

147 148
    files = "#{diff_size} file"
    files += 's' if diff_size > 1
Aorimn committed
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
    files
  end

  def colorize_sha(sha)
    sha = "\x0314#{sha}\x0f" if @colors
    sha
  end

  def colorize_nb_files(nb_files)
    nb_files = "\x0312#{nb_files}\x0f" if @colors
    nb_files
  end

  def colorize_url(url)
    url = "\x0302\x1f#{url}\x0f" if @colors
    url
  end

  def colorize_commits(commits)
    commits = "\x02#{commits}\x0f" if @colors
    commits
  end
end