Skip to content
Snippets Groups Projects
Commit 4c63ef93 authored by Howard P. Logsdon's avatar Howard P. Logsdon
Browse files

HipChat Notification Service

    * Move existing Slack service spec into a subdir, mirroring /app
    * Wire up HipChat service to the project and services controller.
    * Split the message building into own class.
    * 'namespace' room and token variables.
    * Enforce v2 client (bug in HipChat gem v1.5.0. fixed in 1.5.1). Note
      that I'm using the same version string as GitLab-CE, for shared
      installations.
    * Defer execution to a notifier worker, like the Slack service.
    * Ensure passing specs (basically a Slack service spec copy, fwiw)
    * Added change to the CHANGELOG
parent 3bbd2f55
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -4,6 +4,7 @@ v7.11.0
- Improved runners page
- Running and Pending tabs on admin builds page
- Fix [ci skip] tag, so you can skip CI triggering now
- Add HipChat notifications
 
v7.10.1
- Fix failing migration when update to 7.10 from 7.8 and older versions
Loading
Loading
Loading
Loading
@@ -63,6 +63,9 @@ gem "default_value_for", "~> 3.0.0"
# Slack integration
gem "slack-notifier", "~> 1.0.0"
 
# HipChat integration
gem 'hipchat', '~> 1.5.0'
# Other
gem 'rake'
gem 'foreman'
Loading
Loading
Loading
Loading
@@ -156,6 +156,9 @@ GEM
hashie (2.0.5)
highline (1.6.21)
hike (1.2.3)
hipchat (1.5.0)
httparty
mimemagic
httparty (0.11.0)
multi_json (~> 1.0)
multi_xml (>= 0.5.2)
Loading
Loading
@@ -186,6 +189,7 @@ GEM
mime-types (>= 1.16, < 3)
method_source (0.8.2)
mime-types (2.4.3)
mimemagic (0.3.0)
mini_portile (0.5.2)
minitest (5.5.1)
multi_json (1.11.0)
Loading
Loading
@@ -390,6 +394,7 @@ DEPENDENCIES
growl
guard-rspec
haml-rails (~> 0.5.3)
hipchat (~> 1.5.0)
httparty (= 0.11.0)
jquery-rails
jquery-turbolinks
Loading
Loading
Loading
Loading
@@ -50,7 +50,8 @@ class ServicesController < ApplicationController
def service_params
params.require(:service).permit(
:type, :active, :webhook, :notify_only_broken_builds,
:email_recipients, :email_only_broken_builds, :email_add_pusher
:email_recipients, :email_only_broken_builds, :email_add_pusher,
:hipchat_token, :hipchat_room, :hipchat_server
)
end
end
Loading
Loading
@@ -37,6 +37,7 @@ class Project < ActiveRecord::Base
 
# Project services
has_many :services, dependent: :destroy
has_one :hip_chat_service, dependent: :destroy
has_one :slack_service, dependent: :destroy
has_one :mail_service, dependent: :destroy
 
Loading
Loading
@@ -210,7 +211,7 @@ ls -la
end
 
def available_services_names
%w(slack mail)
%w(slack mail hip_chat)
end
 
def build_missing_services
Loading
Loading
class HipChatMessage
attr_reader :build
def initialize(build)
@build = build
end
def to_s
lines = Array.new
lines.push("<a href=\"#{RoutesHelper.project_url(build.project)}\">#{build.project.name}</a> - ")
if build.commit.matrix?
lines.push("<a href=\"#{RoutesHelper.project_ref_commit_url(build.project, build.commit.ref, build.commit.sha)}\">Commit ##{commit.id}</a></br>")
else
lines.push("<a href=\"#{RoutesHelper.project_build_url(build.project, build)}\">Build '#{build.job_name}' ##{build.id}</a></br>")
end
lines.push("#{build.commit.short_sha} #{build.commit.git_author_name} - #{build.commit.git_commit_message}</br>")
lines.push("#{humanized_status} in #{build.commit.duration} second(s).")
lines.join('')
end
def color
case status
when :success
'green'
when :failed, :canceled
'red'
when :pending, :running
'yellow'
else
'random'
end
end
def notify?
[:failed, :canceled].include?(status)
end
private
def status
build.status.to_sym
end
def humanized_status
case status
when :pending
"Pending"
when :running
"Running"
when :failed
"Failed"
when :success
"Successful"
when :canceled
"Canceled"
else
"Unknown"
end
end
end
# == Schema Information
#
# Table name: services
#
# id :integer not null, primary key
# type :string(255)
# title :string(255)
# project_id :integer not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# properties :text
#
class HipChatService < Service
prop_accessor :hipchat_token, :hipchat_room, :hipchat_server
boolean_accessor :notify_only_broken_builds
validates :hipchat_token, presence: true, if: :activated?
validates :hipchat_room, presence: true, if: :activated?
default_value_for :notify_only_broken_builds, true
def title
"HipChat"
end
def description
"Private group chat, video chat, instant messaging for teams"
end
def help
end
def to_param
'hip_chat'
end
def fields
[
{ type: 'text', name: 'hipchat_token', label: 'Token', placeholder: '' },
{ type: 'text', name: 'hipchat_room', label: 'Room', placeholder: '' },
{ type: 'text', name: 'hipchat_server', label: 'Server', placeholder: 'https://hipchat.example.com', help: 'Leave blank for default' },
{ type: 'checkbox', name: 'notify_only_broken_builds', label: 'Notify only broken builds' }
]
end
def execute build
commit = build.commit
return unless commit
return unless commit.builds_without_retry.include? build
msg = HipChatMessage.new(build)
HipChatNotifierWorker.perform_async(hipchat_room, hipchat_token, msg.to_s, {
message_format: 'html',
color: msg.color,
notify: notify_only_broken_builds? && msg.notify?
})
end
private
def default_options
{
hipchat_server: 'https://api.hipchat.com'
}
end
end
class HipChatNotifierWorker
include Sidekiq::Worker
def perform(room, token, message, options={})
client = HipChat::Client.new(token, api_version: 'v2') # v1.5.0 requires explicit version (
client[room].send("GitLab CI", message, options)
end
end
require 'spec_helper'
describe HipChatService do
describe "Validations" do
context "active" do
before do
subject.active = true
end
it { should validate_presence_of :hipchat_room }
it { should validate_presence_of :hipchat_token }
end
end
describe "Execute" do
let(:service) { HipChatService.new }
let(:project) { FactoryGirl.create :project }
let(:commit) { FactoryGirl.create :commit, project: project }
let(:build) { FactoryGirl.create :build, commit: commit, status: 'failed' }
let(:api_url) { 'https://api.hipchat.com/v2/room/123/notification?auth_token=a1b2c3d4e5f6' }
before do
service.stub(
project: project,
project_id: project.id,
notify_only_broken_builds: false,
hipchat_room: 123,
hipchat_token: 'a1b2c3d4e5f6'
)
WebMock.stub_request(:post, api_url)
end
it "should call the HipChat API" do
service.execute(build)
HipChatNotifierWorker.drain
WebMock.should have_requested(:post, api_url).once
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment