BigW Consortium Gitlab

hipchat_service.rb 7.25 KB
Newer Older
1 2 3 4
# == Schema Information
#
# Table name: services
#
5 6 7 8 9 10 11 12 13 14 15 16 17
#  id                    :integer          not null, primary key
#  type                  :string(255)
#  title                 :string(255)
#  project_id            :integer
#  created_at            :datetime
#  updated_at            :datetime
#  active                :boolean          default(FALSE), not null
#  properties            :text
#  template              :boolean          default(FALSE)
#  push_events           :boolean          default(TRUE)
#  issues_events         :boolean          default(TRUE)
#  merge_requests_events :boolean          default(TRUE)
#  tag_push_events       :boolean          default(TRUE)
Stan Hu committed
18
#  note_events           :boolean          default(TRUE), not null
19 20 21
#

class HipchatService < Service
22 23
  MAX_COMMITS = 3

24
  prop_accessor :token, :room, :server, :notify, :color, :api_version
25 26 27
  validates :token, presence: true, if: :activated?

  def title
28
    'HipChat'
29 30 31
  end

  def description
32
    'Private group chat and IM'
33 34 35 36 37 38 39 40
  end

  def to_param
    'hipchat'
  end

  def fields
    [
41 42
      { type: 'text', name: 'token',     placeholder: 'Room token' },
      { type: 'text', name: 'room',      placeholder: 'Room name or ID' },
43 44
      { type: 'checkbox', name: 'notify' },
      { type: 'select', name: 'color', choices: ['yellow', 'red', 'green', 'purple', 'gray', 'random'] },
45 46
      { type: 'text', name: 'api_version',
        placeholder: 'Leave blank for default (v2)' },
47
      { type: 'text', name: 'server',
Drew Blessing committed
48
        placeholder: 'Leave blank for default. https://hipchat.example.com' }
49 50 51
    ]
  end

52
  def supported_events
53
    %w(push issue merge_request note tag_push)
54 55
  end

56
  def execute(data)
57
    return unless supported_events.include?(data[:object_kind])
58 59
    message = create_message(data)
    return unless message.present?
60
    gate[room].send('GitLab', message, message_options)
61 62 63 64 65
  end

  private

  def gate
66
    options = { api_version: api_version || 'v2' }
Drew Blessing committed
67
    options[:server_url] = server unless server.blank?
68
    @gate ||= HipChat::Client.new(token, options)
69 70
  end

71 72 73 74
  def message_options
    { notify: notify.present? && notify == '1', color: color || 'yellow' }
  end

75 76 77 78 79
  def create_message(data)
    object_kind = data[:object_kind]

    message = \
      case object_kind
80
      when "push", "tag_push"
81 82 83 84 85
        create_push_message(data)
      when "issue"
        create_issue_message(data) unless is_update?(data)
      when "merge_request"
        create_merge_request_message(data) unless is_update?(data)
86 87
      when "note"
        create_note_message(data)
88 89 90 91
      end
  end

  def create_push_message(push)
92 93
    ref_type = Gitlab::Git.tag_ref?(push[:ref]) ? 'tag' : 'branch'
    ref = Gitlab::Git.ref_name(push[:ref])
94

95 96 97 98 99
    before = push[:before]
    after = push[:after]

    message = ""
    message << "#{push[:user_name]} "
100
    if Gitlab::Git.blank_ref?(before)
101
      message << "pushed new #{ref_type} <a href=\""\
102
                 "#{project_url}/commits/#{URI.escape(ref)}\">#{ref}</a>"\
103
                 " to #{project_link}\n"
104
    elsif Gitlab::Git.blank_ref?(after)
105
      message << "removed #{ref_type} <b>#{ref}</b> from <a href=\"#{project.web_url}\">#{project_name}</a> \n"
106
    else
107
      message << "pushed to #{ref_type} <a href=\""\
108
                  "#{project.web_url}/commits/#{URI.escape(ref)}\">#{ref}</a> "
109 110
      message << "of <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/,'')}</a> "
      message << "(<a href=\"#{project.web_url}/compare/#{before}...#{after}\">Compare changes</a>)"
111 112 113 114 115 116 117

      push[:commits].take(MAX_COMMITS).each do |commit|
        message << "<br /> - #{commit[:message].lines.first} (<a href=\"#{commit[:url]}\">#{commit[:id][0..5]}</a>)"
      end

      if push[:commits].count > MAX_COMMITS
        message << "<br />... #{push[:commits].count - MAX_COMMITS} more commits"
118 119 120 121 122
      end
    end

    message
  end
123

124 125 126 127 128 129 130 131
  def format_body(body)
    if body
      body = body.truncate(200, separator: ' ', omission: '...')
    end

    "<pre>#{body}</pre>"
  end

132
  def create_issue_message(data)
133
    user_name = data[:user][:name]
134 135 136 137 138 139 140 141 142

    obj_attr = data[:object_attributes]
    obj_attr = HashWithIndifferentAccess.new(obj_attr)
    title = obj_attr[:title]
    state = obj_attr[:state]
    issue_iid = obj_attr[:iid]
    issue_url = obj_attr[:url]
    description = obj_attr[:description]

143 144
    issue_link = "<a href=\"#{issue_url}\">issue ##{issue_iid}</a>"
    message = "#{user_name} #{state} #{issue_link} in #{project_link}: <b>#{title}</b>"
145 146

    if description
147 148
      description = format_body(description)
      message << description
149 150 151 152 153 154
    end

    message
  end

  def create_merge_request_message(data)
155
    user_name = data[:user][:name]
156 157 158 159 160 161 162 163 164 165 166

    obj_attr = data[:object_attributes]
    obj_attr = HashWithIndifferentAccess.new(obj_attr)
    merge_request_id = obj_attr[:iid]
    source_branch = obj_attr[:source_branch]
    target_branch = obj_attr[:target_branch]
    state = obj_attr[:state]
    description = obj_attr[:description]
    title = obj_attr[:title]

    merge_request_url = "#{project_url}/merge_requests/#{merge_request_id}"
167 168
    merge_request_link = "<a href=\"#{merge_request_url}\">merge request ##{merge_request_id}</a>"
    message = "#{user_name} #{state} #{merge_request_link} in " \
169 170 171
      "#{project_link}: <b>#{title}</b>"

    if description
172 173 174 175 176 177 178 179 180 181 182 183 184
      description = format_body(description)
      message << description
    end

    message
  end

  def format_title(title)
    "<b>" + title.lines.first.chomp + "</b>"
  end

  def create_note_message(data)
    data = HashWithIndifferentAccess.new(data)
185
    user_name = data[:user][:name]
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221

    repo_attr = HashWithIndifferentAccess.new(data[:repository])

    obj_attr = HashWithIndifferentAccess.new(data[:object_attributes])
    note = obj_attr[:note]
    note_url = obj_attr[:url]
    noteable_type = obj_attr[:noteable_type]

    case noteable_type
    when "Commit"
      commit_attr = HashWithIndifferentAccess.new(data[:commit])
      subject_desc = commit_attr[:id]
      subject_desc = Commit.truncate_sha(subject_desc)
      subject_type = "commit"
      title = format_title(commit_attr[:message])
    when "Issue"
      subj_attr = HashWithIndifferentAccess.new(data[:issue])
      subject_id = subj_attr[:iid]
      subject_desc = "##{subject_id}"
      subject_type = "issue"
      title = format_title(subj_attr[:title])
    when "MergeRequest"
      subj_attr = HashWithIndifferentAccess.new(data[:merge_request])
      subject_id = subj_attr[:iid]
      subject_desc = "##{subject_id}"
      subject_type = "merge request"
      title = format_title(subj_attr[:title])
    when "Snippet"
      subj_attr = HashWithIndifferentAccess.new(data[:snippet])
      subject_id = subj_attr[:id]
      subject_desc = "##{subject_id}"
      subject_type = "snippet"
      title = format_title(subj_attr[:title])
    end

    subject_html = "<a href=\"#{note_url}\">#{subject_type} #{subject_desc}</a>"
222
    message = "#{user_name} commented on #{subject_html} in #{project_link}: "
223 224 225 226 227
    message << title

    if note
      note = format_body(note)
      message << note
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
    end

    message
  end

  def project_name
    project.name_with_namespace.gsub(/\s/, '')
  end

  def project_url
    project.web_url
  end

  def project_link
    "<a href=\"#{project_url}\">#{project_name}</a>"
  end

  def is_update?(data)
    data[:object_attributes][:action] == 'update'
  end
Dmitriy Zaporozhets committed
248
end