hipchat_service.rb 7.27 KB
Newer Older
1
2
3
4
# == Schema Information
#
# Table name: services
#
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
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's avatar
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's avatar
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

Douwe Maan's avatar
Douwe Maan committed
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
  end

63
64
65
66
67
68
69
70
71
72
  def test(data)
    begin
      result = execute(data)
    rescue StandardError => error
      return { success: false, result: error }
    end

    { success: true, result: result }
  end

73
74
75
  private

  def gate
76
    options = { api_version: api_version.present? ? api_version : 'v2' }
Drew Blessing's avatar
Drew Blessing committed
77
    options[:server_url] = server unless server.blank?
78
    @gate ||= HipChat::Client.new(token, options)
79
80
  end

81
82
83
84
  def message_options
    { notify: notify.present? && notify == '1', color: color || 'yellow' }
  end

85
86
87
  def create_message(data)
    object_kind = data[:object_kind]

88
89
90
91
92
93
94
95
96
97
    case object_kind
    when "push", "tag_push"
      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)
    when "note"
      create_note_message(data)
    end
98
99
100
  end

  def create_push_message(push)
101
102
    ref_type = Gitlab::Git.tag_ref?(push[:ref]) ? 'tag' : 'branch'
    ref = Gitlab::Git.ref_name(push[:ref])
103

104
105
106
107
108
    before = push[:before]
    after = push[:after]

    message = ""
    message << "#{push[:user_name]} "
109
    if Gitlab::Git.blank_ref?(before)
110
      message << "pushed new #{ref_type} <a href=\""\
111
                 "#{project_url}/commits/#{URI.escape(ref)}\">#{ref}</a>"\
112
                 " to #{project_link}\n"
113
    elsif Gitlab::Git.blank_ref?(after)
114
      message << "removed #{ref_type} <b>#{ref}</b> from <a href=\"#{project.web_url}\">#{project_name}</a> \n"
115
    else
116
      message << "pushed to #{ref_type} <a href=\""\
117
                  "#{project.web_url}/commits/#{URI.escape(ref)}\">#{ref}</a> "
118
119
      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>)"
120
121
122
123
124
125
126

      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"
127
128
129
130
131
      end
    end

    message
  end
132

133
134
135
136
137
138
139
140
  def format_body(body)
    if body
      body = body.truncate(200, separator: ' ', omission: '...')
    end

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

141
  def create_issue_message(data)
142
    user_name = data[:user][:name]
143
144
145
146
147
148
149
150
151

    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]

152
153
    issue_link = "<a href=\"#{issue_url}\">issue ##{issue_iid}</a>"
    message = "#{user_name} #{state} #{issue_link} in #{project_link}: <b>#{title}</b>"
154
155

    if description
156
157
      description = format_body(description)
      message << description
158
159
160
161
162
163
    end

    message
  end

  def create_merge_request_message(data)
164
    user_name = data[:user][:name]
165
166
167
168
169
170
171
172
173

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

    merge_request_url = "#{project_url}/merge_requests/#{merge_request_id}"
174
175
    merge_request_link = "<a href=\"#{merge_request_url}\">merge request ##{merge_request_id}</a>"
    message = "#{user_name} #{state} #{merge_request_link} in " \
176
177
178
      "#{project_link}: <b>#{title}</b>"

    if description
179
180
181
182
183
184
185
186
187
188
189
190
191
      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)
192
    user_name = data[:user][:name]
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
222
223
224
225
226

    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>"
227
    message = "#{user_name} commented on #{subject_html} in #{project_link}: "
228
229
230
231
232
    message << title

    if note
      note = format_body(note)
      message << note
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
    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's avatar
Dmitriy Zaporozhets committed
253
end