ad0511f5b0
* upstream/master: (368 commits) Don't fail on an empty database Refactor authorization_for_merge_requests.md Support MySQL too, when removing gitorious from import_sources Remove gitorious from import_sources on ApplicationSetting model Add links to new docs in merge_requests.md and workflow/README.md Move merge request versions to its own document Move "Only allow merge requests to be merged if the build succeeds" to new location Move revert_changes.md to new location Move cherry_pick_changes.md to new location Move `wip_merge_requests.md` to a new location Move merge_when_build_succeeds.md to new location Fix missing flash messages on service edit page Move authorization_for_merge_requests.md to new location Move `workflow/merge_requests.md` to `user/project/merge_requests.md` Update README.md Fix randomly failing specs in expand_collapse_diff_spec: Add link on API docs index page Move CHANGELOG entries of !5361, !5451 and !5887 from 8.11 to 8.12 Remove suggested colors hover underline Fix markdown anchor icon interaction ...
176 lines
4.4 KiB
Ruby
176 lines
4.4 KiB
Ruby
class SlackService < Service
|
|
prop_accessor :webhook, :username, :channel
|
|
boolean_accessor :notify_only_broken_builds, :notify_only_broken_pipelines
|
|
validates :webhook, presence: true, url: true, if: :activated?
|
|
|
|
def initialize_properties
|
|
# Custom serialized properties initialization
|
|
self.supported_events.each { |event| self.class.prop_accessor(event_channel_name(event)) }
|
|
|
|
if properties.nil?
|
|
self.properties = {}
|
|
self.notify_only_broken_builds = true
|
|
self.notify_only_broken_pipelines = true
|
|
end
|
|
end
|
|
|
|
def title
|
|
'Slack'
|
|
end
|
|
|
|
def description
|
|
'A team communication tool for the 21st century'
|
|
end
|
|
|
|
def to_param
|
|
'slack'
|
|
end
|
|
|
|
def help
|
|
'This service sends notifications to your Slack channel.<br/>
|
|
To setup this Service you need to create a new <b>"Incoming webhook"</b> in your Slack integration panel,
|
|
and enter the Webhook URL below.'
|
|
end
|
|
|
|
def fields
|
|
default_fields =
|
|
[
|
|
{ type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' },
|
|
{ type: 'text', name: 'username', placeholder: 'username' },
|
|
{ type: 'text', name: 'channel', placeholder: "#general" },
|
|
{ type: 'checkbox', name: 'notify_only_broken_builds' },
|
|
{ type: 'checkbox', name: 'notify_only_broken_pipelines' },
|
|
]
|
|
|
|
default_fields + build_event_channels
|
|
end
|
|
|
|
def supported_events
|
|
%w[push issue confidential_issue merge_request note tag_push
|
|
build pipeline wiki_page]
|
|
end
|
|
|
|
def execute(data)
|
|
return unless supported_events.include?(data[:object_kind])
|
|
return unless webhook.present?
|
|
|
|
object_kind = data[:object_kind]
|
|
|
|
data = data.merge(
|
|
project_url: project_url,
|
|
project_name: project_name
|
|
)
|
|
|
|
# WebHook events often have an 'update' event that follows a 'open' or
|
|
# 'close' action. Ignore update events for now to prevent duplicate
|
|
# messages from arriving.
|
|
|
|
message = get_message(object_kind, data)
|
|
|
|
if message
|
|
opt = {}
|
|
|
|
event_channel = get_channel_field(object_kind) || channel
|
|
|
|
opt[:channel] = event_channel if event_channel
|
|
opt[:username] = username if username
|
|
|
|
notifier = Slack::Notifier.new(webhook, opt)
|
|
notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback)
|
|
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
def event_channel_names
|
|
supported_events.map { |event| event_channel_name(event) }
|
|
end
|
|
|
|
def event_field(event)
|
|
fields.find { |field| field[:name] == event_channel_name(event) }
|
|
end
|
|
|
|
def global_fields
|
|
fields.reject { |field| field[:name].end_with?('channel') }
|
|
end
|
|
|
|
private
|
|
|
|
def get_message(object_kind, data)
|
|
case object_kind
|
|
when "push", "tag_push"
|
|
PushMessage.new(data)
|
|
when "issue"
|
|
IssueMessage.new(data) unless is_update?(data)
|
|
when "merge_request"
|
|
MergeMessage.new(data) unless is_update?(data)
|
|
when "note"
|
|
NoteMessage.new(data)
|
|
when "build"
|
|
BuildMessage.new(data) if should_build_be_notified?(data)
|
|
when "pipeline"
|
|
PipelineMessage.new(data) if should_pipeline_be_notified?(data)
|
|
when "wiki_page"
|
|
WikiPageMessage.new(data)
|
|
end
|
|
end
|
|
|
|
def get_channel_field(event)
|
|
field_name = event_channel_name(event)
|
|
self.public_send(field_name)
|
|
end
|
|
|
|
def build_event_channels
|
|
supported_events.reduce([]) do |channels, event|
|
|
channels << { type: 'text', name: event_channel_name(event), placeholder: "#general" }
|
|
end
|
|
end
|
|
|
|
def event_channel_name(event)
|
|
"#{event}_channel"
|
|
end
|
|
|
|
def project_name
|
|
project.name_with_namespace.gsub(/\s/, '')
|
|
end
|
|
|
|
def project_url
|
|
project.web_url
|
|
end
|
|
|
|
def is_update?(data)
|
|
data[:object_attributes][:action] == 'update'
|
|
end
|
|
|
|
def should_build_be_notified?(data)
|
|
case data[:commit][:status]
|
|
when 'success'
|
|
!notify_only_broken_builds?
|
|
when 'failed'
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
def should_pipeline_be_notified?(data)
|
|
case data[:object_attributes][:status]
|
|
when 'success'
|
|
!notify_only_broken_pipelines?
|
|
when 'failed'
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|
|
|
|
require "slack_service/issue_message"
|
|
require "slack_service/push_message"
|
|
require "slack_service/merge_message"
|
|
require "slack_service/note_message"
|
|
require "slack_service/build_message"
|
|
require "slack_service/pipeline_message"
|
|
require "slack_service/wiki_page_message"
|