summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzcinski <ayufan@ayufan.eu>2014-12-05 12:20:40 +0100
committerKamil Trzcinski <ayufan@ayufan.eu>2015-01-12 19:53:13 +0100
commita40989d27ea8a1c5d23dfd5b82f25e09527b2c80 (patch)
tree9be1f8feaaf66103ed4affed070a784d5a474ff8
parent0e93695f8ef3a889104b23ce9be4f37042d7388f (diff)
downloadgitlab-ci-a40989d27ea8a1c5d23dfd5b82f25e09527b2c80.tar.gz
Added Slack notification service
- Send notification at once for all commits
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/controllers/services_controller.rb3
-rw-r--r--app/models/build.rb2
-rw-r--r--app/models/project.rb4
-rw-r--r--app/models/project_services/slack_message.rb106
-rw-r--r--app/models/project_services/slack_service.rb50
-rw-r--r--app/views/services/_form.html.haml3
-rw-r--r--app/workers/slack_notifier_worker.rb8
9 files changed, 145 insertions, 37 deletions
diff --git a/Gemfile b/Gemfile
index bb81174..ac47c37 100644
--- a/Gemfile
+++ b/Gemfile
@@ -56,7 +56,7 @@ gem 'virtus', '1.0.1'
gem "default_value_for", "~> 3.0.0"
# Slack integration
-gem "slack-notifier", "~> 0.3.2"
+gem "slack-notifier", "~> 1.0.0"
# Other
gem 'rake'
diff --git a/Gemfile.lock b/Gemfile.lock
index 6c84df5..33dc15d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -256,7 +256,7 @@ GEM
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (~> 1.3, >= 1.3.4)
- slack-notifier (0.3.2)
+ slack-notifier (1.0.0)
slim (2.0.2)
temple (~> 0.6.6)
tilt (>= 1.3.3, < 2.1)
@@ -357,7 +357,7 @@ DEPENDENCIES
sidekiq
simplecov
sinatra
- slack-notifier (~> 0.3.2)
+ slack-notifier (~> 1.0.0)
slim
stamp
state_machine
diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb
index 87481a3..83a737e 100644
--- a/app/controllers/services_controller.rb
+++ b/app/controllers/services_controller.rb
@@ -46,7 +46,8 @@ class ServicesController < ApplicationController
params.require(:service).permit(
:title, :token, :type, :active, :api_key, :subdomain,
:room, :recipients, :project_url, :webhook,
- :user_key, :device, :priority, :sound
+ :user_key, :device, :priority, :sound,
+ :notify_only_broken_builds
)
end
end
diff --git a/app/models/build.rb b/app/models/build.rb
index 03393c5..0e88b86 100644
--- a/app/models/build.rb
+++ b/app/models/build.rb
@@ -103,6 +103,8 @@ class Build < ActiveRecord::Base
WebHookService.new.build_end(build)
end
+ project.execute_services(build)
+
if project.email_notification?
if build.status.to_sym == :failed || !project.email_only_broken_builds
NotificationService.new.build_ended(build)
diff --git a/app/models/project.rb b/app/models/project.rb
index 9c93d08..143a286 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -141,6 +141,10 @@ ls -la
web_hooks.any?
end
+ def services?
+ services.any?
+ end
+
def timeout_in_minutes
timeout / 60
end
diff --git a/app/models/project_services/slack_message.rb b/app/models/project_services/slack_message.rb
index b5a790b..82715d1 100644
--- a/app/models/project_services/slack_message.rb
+++ b/app/models/project_services/slack_message.rb
@@ -6,71 +6,131 @@ class SlackMessage
# default_url_options[:port] = GitlabCi.config.gitlab_ci.port if GitlabCi.config.gitlab_ci_on_non_standard_port?
# default_url_options[:script_name] = GitlabCi.config.gitlab_ci.relative_url_root
- def initialize(build)
- @build = build
+ def initialize(commit)
+ @commit = commit
end
def pretext
- format(message)
+ ''
end
def color
attachment_color
end
+ def fallback
+ format(attachment_message)
+ end
+
def attachments
- message_attachments
+ fields = []
+
+ if commit.matrix?
+ commit.builds_without_retry.each do |build|
+ next unless build.failed?
+ fields << {
+ title: build.job_name,
+ value: "Build <#{build_log_link(build)}|\##{build.id}> failed in #{build.duration.to_i} second(s)."
+ }
+ end
+ end
+
+ [{
+ text: attachment_message,
+ color: attachment_color,
+ fields: fields
+ }]
end
private
- attr_reader :build
+ attr_reader :commit
- def message
- if build.complete?
- "<#{project_url}|#{project_name}>: Build <#{build_url}|\##{build.id}> (<#{build_ref_link}|#{build.short_sha}>) of #{build.ref} by #{build.commit.git_author_name} #{build.status} in #{build.duration} second(s)"
+ def attachment_message
+ out = "<#{project_url}|#{project_name}>: "
+ if commit.matrix?
+ out << "Commit <#{commit_url}|\##{commit.id}> "
+ else
+ build = commit.builds_without_retry.first
+ out << "Build <#{build_log_link(build)}|\##{build.id}> "
end
- end
-
- def message_attachments
- []
+ out << "(<#{commit_sha_link}|#{commit.short_sha}>) "
+ out << "of <#{commit_ref_link}|#{commit.ref}> "
+ out << "by #{commit.git_author_name} " if commit.git_author_name
+ out << "#{commit_status} in "
+ out << "#{commit.duration} second(s)"
end
def format(string)
Slack::Notifier::LinkFormatter.format(string)
end
+ def project
+ commit.project
+ end
+
def project_name
- build.project.name
+ project.name
end
- def build_ref_link
- if build.project.gitlab?
- "#{build.project.gitlab_url}/commits/#{build.ref}"
+ def commit_sha_link
+ if commit.project.gitlab?
+ "#{project.gitlab_url}/commit/#{commit.sha}"
else
- build.ref
+ commit.ref
+ end
+ end
+
+ def commit_ref_link
+ if commit.project.gitlab?
+ "#{project.gitlab_url}/commits/#{commit.ref}"
+ else
+ commit.ref
end
end
def attachment_color
- if build.success?
+ if commit.success?
'good'
else
'danger'
end
end
+ def commit_status
+ if commit.success?
+ 'succeeded'
+ else
+ 'failed'
+ end
+ end
+
def project_url
Rails.application.routes.url_helpers.project_url(
- build.project,
- host: Settings.gitlab_ci['host'], protocol: Settings.gitlab_ci['https'] ? "https" : "http", port: Settings.gitlab_ci['port']
+ project,
+ url_helper_options
)
end
- def build_url
+ def commit_url
+ Rails.application.routes.url_helpers.project_commit_url(
+ project, commit,
+ url_helper_options
+ )
+ end
+
+ def build_log_link(build)
Rails.application.routes.url_helpers.project_build_url(
- build.project, build,
- host: Settings.gitlab_ci['host'], protocol: Settings.gitlab_ci['https'] ? "https" : "http", port: Settings.gitlab_ci['port']
+ project, build,
+ url_helper_options
)
end
+
+ def url_helper_options
+ {
+ host: Settings.gitlab_ci['host'],
+ protocol: Settings.gitlab_ci['https'] ? "https" : "http",
+ port: Settings.gitlab_ci['port']
+ }
+ end
end
diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb
index 2554719..3820df1 100644
--- a/app/models/project_services/slack_service.rb
+++ b/app/models/project_services/slack_service.rb
@@ -14,8 +14,11 @@
class SlackService < Service
prop_accessor :webhook
+ prop_accessor :notify_only_broken_builds
validates :webhook, presence: true, if: :activated?
+ default_value_for :notify_only_broken_builds, true
+
def title
'Slack'
end
@@ -34,20 +37,49 @@ class SlackService < Service
def fields
[
- {type: 'text', name: 'webhook', placeholder: ''}
+ {type: 'text', name: 'webhook', label: 'Webhook URL', placeholder: ''},
+ {type: 'checkbox', name: 'notify_only_broken_builds', label: 'Notify only broken builds'}
]
end
- def execute(build)
- message = SlackMessage.new(build)
+ def notify_only_broken_builds?
+ notify_only_broken_builds == '1'
+ end
+
+ def can_test?
+ # slack notification is useful only for builds either successful or failed
+ builds = project.builds
+ return builds.failed.any? if notify_only_broken_builds?
+ builds.failed.any? || builds.success.any?
+ end
- credentials = webhook.match(/([\w-]*).slack.com.*services\/(.*)/)
+ def execute(build)
+ commit = build.commit
+ return unless commit
+ return unless commit.builds_without_retry.include?(build)
- if credentials.present?
- subdomain = credentials[1]
- token = credentials[2].split("token=").last
- notifier = Slack::Notifier.new(subdomain, token)
- notifier.ping(message.pretext, color: message.color, fallback: message.pretext, attachments: message.attachments)
+ case commit.status.to_sym
+ when :failed
+ when :success
+ return if notify_only_broken_builds?
+ else
+ return
end
+
+ message = SlackMessage.new(commit)
+ options = default_options.merge(
+ color: message.color,
+ fallback: message.fallback,
+ attachments: message.attachments
+ )
+ SlackNotifierWorker.perform_async(webhook, message.pretext, options)
+ end
+
+ private
+
+ def default_options
+ {
+ username: 'GitLab CI'
+ }
end
end
diff --git a/app/views/services/_form.html.haml b/app/views/services/_form.html.haml
index 16d59d1..5e4bb76 100644
--- a/app/views/services/_form.html.haml
+++ b/app/views/services/_form.html.haml
@@ -28,6 +28,7 @@
- @service.fields.each do |field|
- name = field[:name]
+ - label = field[:label] || name
- value = @service.send(name)
- type = field[:type]
- placeholder = field[:placeholder]
@@ -35,7 +36,7 @@
- default_choice = field[:default_choice]
.form-group
- = f.label name, class: "control-label"
+ = f.label label, class: "control-label"
.col-sm-10
- if type == 'text'
= f.text_field name, class: "form-control", placeholder: placeholder
diff --git a/app/workers/slack_notifier_worker.rb b/app/workers/slack_notifier_worker.rb
new file mode 100644
index 0000000..54c7d11
--- /dev/null
+++ b/app/workers/slack_notifier_worker.rb
@@ -0,0 +1,8 @@
+class SlackNotifierWorker
+ include Sidekiq::Worker
+
+ def perform(webhook_url, message, options={})
+ notifier = Slack::Notifier.new(webhook_url)
+ notifier.ping(message, options)
+ end
+end \ No newline at end of file