diff options
author | Kamil Trzcinski <ayufan@ayufan.eu> | 2014-12-05 12:20:40 +0100 |
---|---|---|
committer | Kamil Trzcinski <ayufan@ayufan.eu> | 2015-01-12 19:53:13 +0100 |
commit | a40989d27ea8a1c5d23dfd5b82f25e09527b2c80 (patch) | |
tree | 9be1f8feaaf66103ed4affed070a784d5a474ff8 | |
parent | 0e93695f8ef3a889104b23ce9be4f37042d7388f (diff) | |
download | gitlab-ci-a40989d27ea8a1c5d23dfd5b82f25e09527b2c80.tar.gz |
Added Slack notification service
- Send notification at once for all commits
-rw-r--r-- | Gemfile | 2 | ||||
-rw-r--r-- | Gemfile.lock | 4 | ||||
-rw-r--r-- | app/controllers/services_controller.rb | 3 | ||||
-rw-r--r-- | app/models/build.rb | 2 | ||||
-rw-r--r-- | app/models/project.rb | 4 | ||||
-rw-r--r-- | app/models/project_services/slack_message.rb | 106 | ||||
-rw-r--r-- | app/models/project_services/slack_service.rb | 50 | ||||
-rw-r--r-- | app/views/services/_form.html.haml | 3 | ||||
-rw-r--r-- | app/workers/slack_notifier_worker.rb | 8 |
9 files changed, 145 insertions, 37 deletions
@@ -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 |