Read about our upcoming Code of Conduct on this issue

Commit afe5d7d2 authored by Stan Hu's avatar Stan Hu Committed by Douwe Maan
Browse files

Issue #595: Support Slack notifications upon issue and merge request events

1) Adds a DB migration for all services to toggle on push, issue, and merge events.

2) Upon an issue or merge request event, fire service hooks.

3) Slack service supports custom messages for each of these events. Other services
not supported at the moment.

4) Label merge request hooks with their corresponding actions.
parent 7fb58d4fc844
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 7.9.0 (unreleased)
- Added issue and merge request events to Slack service (Stan Hu)
- Fix broken access control for note attachments (Hannes Rosenögger)
v 7.9.0 (unreleased) v 7.9.0 (unreleased)
- Move labels/milestones tabs to sidebar - Move labels/milestones tabs to sidebar
......
...@@ -51,7 +51,8 @@ def service_params ...@@ -51,7 +51,8 @@ def service_params
:user_key, :device, :priority, :sound, :bamboo_url, :username, :password, :user_key, :device, :priority, :sound, :bamboo_url, :username, :password,
:build_key, :server, :teamcity_url, :build_type, :build_key, :server, :teamcity_url, :build_type,
:description, :issues_url, :new_issue_url, :restrict_to_branch, :channel, :description, :issues_url, :new_issue_url, :restrict_to_branch, :channel,
:colorize_messages, :channels :colorize_messages, :channels,
:push_events, :issues_events, :merge_requests_events, :tag_push_events
) )
end end
end end
...@@ -479,8 +479,9 @@ def execute_hooks(data, hooks_scope = :push_hooks) ...@@ -479,8 +479,9 @@ def execute_hooks(data, hooks_scope = :push_hooks)
end end
end end
def execute_services(data) def execute_services(data, hooks_scope = :push_hooks)
services.select(&:active).each do |service| # Call only service hooks that are active for this scope
services.send(hooks_scope).each do |service|
service.async_execute(data) service.async_execute(data)
end end
end end
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # 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)
# #
require 'asana' require 'asana'
...@@ -62,6 +66,9 @@ def fields ...@@ -62,6 +66,9 @@ def fields
end end
def execute(push) def execute(push)
object_kind = push[:object_kind]
return unless object_kind == "push"
Asana.configure do |client| Asana.configure do |client|
client.api_key = api_key client.api_key = api_key
end end
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # 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)
# #
class AssemblaService < Service class AssemblaService < Service
...@@ -38,8 +42,11 @@ def fields ...@@ -38,8 +42,11 @@ def fields
] ]
end end
def execute(push) def execute(data)
object_kind = data[:object_kind]
return unless object_kind == "push"
url = "https://atlas.assembla.com/spaces/#{subdomain}/github_tool?secret_key=#{token}" url = "https://atlas.assembla.com/spaces/#{subdomain}/github_tool?secret_key=#{token}"
AssemblaService.post(url, body: { payload: push }.to_json, headers: { 'Content-Type' => 'application/json' }) AssemblaService.post(url, body: { payload: data }.to_json, headers: { 'Content-Type' => 'application/json' })
end end
end end
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # 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)
# #
class BambooService < CiService class BambooService < CiService
...@@ -118,7 +122,10 @@ def commit_status(sha) ...@@ -118,7 +122,10 @@ def commit_status(sha)
end end
end end
def execute(_data) def execute(data)
object_kind = data[:object_kind]
return unless object_kind == "push"
# Bamboo requires a GET and does not take any data. # Bamboo requires a GET and does not take any data.
self.class.get("#{bamboo_url}/updateAndBuild.action?buildKey=#{build_key}", self.class.get("#{bamboo_url}/updateAndBuild.action?buildKey=#{build_key}",
verify: false) verify: false)
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # 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)
# #
require "addressable/uri" require "addressable/uri"
...@@ -33,6 +37,9 @@ def compose_service_hook ...@@ -33,6 +37,9 @@ def compose_service_hook
end end
def execute(data) def execute(data)
object_kind = data[:object_kind]
return unless object_kind == "push"
service_hook.execute(data) service_hook.execute(data)
end end
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # 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)
# #
class CampfireService < Service class CampfireService < Service
...@@ -38,6 +42,9 @@ def fields ...@@ -38,6 +42,9 @@ def fields
end end
def execute(push_data) def execute(push_data)
object_kind = push_data[:object_kind]
return unless object_kind == "push"
room = gate.find_room_by_name(self.room) room = gate.find_room_by_name(self.room)
return true unless room return true unless room
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # template :boolean default(FALSE)
# push_events :boolean
# issues_events :boolean
# merge_requests_events :boolean
# tag_push_events :boolean
# #
# Base class for CI services # Base class for CI services
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # template :boolean default(FALSE)
# push_events :boolean
# issues_events :boolean
# merge_requests_events :boolean
# tag_push_events :boolean
# #
class EmailsOnPushService < Service class EmailsOnPushService < Service
...@@ -30,6 +34,9 @@ def to_param ...@@ -30,6 +34,9 @@ def to_param
end end
def execute(push_data) def execute(push_data)
object_kind = push_data[:object_kind]
return unless object_kind == "push"
EmailsOnPushWorker.perform_async(project_id, recipients, push_data) EmailsOnPushWorker.perform_async(project_id, recipients, push_data)
end end
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # template :boolean default(FALSE)
# push_events :boolean
# issues_events :boolean
# merge_requests_events :boolean
# tag_push_events :boolean
# #
require "flowdock-git-hook" require "flowdock-git-hook"
...@@ -38,6 +42,9 @@ def fields ...@@ -38,6 +42,9 @@ def fields
end end
def execute(push_data) def execute(push_data)
object_kind = push_data[:object_kind]
return unless object_kind == "push"
Flowdock::Git.post( Flowdock::Git.post(
push_data[:ref], push_data[:ref],
push_data[:before], push_data[:before],
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # template :boolean default(FALSE)
# push_events :boolean
# issues_events :boolean
# merge_requests_events :boolean
# tag_push_events :boolean
# #
require "gemnasium/gitlab_service" require "gemnasium/gitlab_service"
...@@ -39,6 +43,9 @@ def fields ...@@ -39,6 +43,9 @@ def fields
end end
def execute(push_data) def execute(push_data)
object_kind = push_data[:object_kind]
return unless object_kind == "push"
Gemnasium::GitlabService.execute( Gemnasium::GitlabService.execute(
ref: push_data[:ref], ref: push_data[:ref],
before: push_data[:before], before: push_data[:before],
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # template :boolean default(FALSE)
# push_events :boolean
# issues_events :boolean
# merge_requests_events :boolean
# tag_push_events :boolean
# #
class GitlabCiService < CiService class GitlabCiService < CiService
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # 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)
# #
class GitlabIssueTrackerService < IssueTrackerService class GitlabIssueTrackerService < IssueTrackerService
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # template :boolean default(FALSE)
# push_events :boolean
# issues_events :boolean
# merge_requests_events :boolean
# tag_push_events :boolean
# #
class HipchatService < Service class HipchatService < Service
...@@ -41,6 +45,9 @@ def fields ...@@ -41,6 +45,9 @@ def fields
end end
def execute(push_data) def execute(push_data)
object_kind = push_data.fetch(:object_kind)
return unless object_kind == "push"
gate[room].send('GitLab', create_message(push_data)) gate[room].send('GitLab', create_message(push_data))
end end
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # 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)
# #
class IssueTrackerService < Service class IssueTrackerService < Service
...@@ -66,6 +70,9 @@ def initialize_properties ...@@ -66,6 +70,9 @@ def initialize_properties
end end
def execute(data) def execute(data)
object_kind = data[:object_kind]
return unless object_kind == "push"
message = "#{self.type} was unable to reach #{self.project_url}. Check the url and try again." message = "#{self.type} was unable to reach #{self.project_url}. Check the url and try again."
result = false result = false
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # 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)
# #
class JiraService < IssueTrackerService class JiraService < IssueTrackerService
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # 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)
# #
class PivotaltrackerService < Service class PivotaltrackerService < Service
...@@ -38,6 +42,9 @@ def fields ...@@ -38,6 +42,9 @@ def fields
end end
def execute(push) def execute(push)
object_kind = push[:object_kind]
return unless object_kind == "push"
url = 'https://www.pivotaltracker.com/services/v5/source_commits' url = 'https://www.pivotaltracker.com/services/v5/source_commits'
push[:commits].each do |commit| push[:commits].each do |commit|
message = { message = {
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # 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)
# #
class PushoverService < Service class PushoverService < Service
...@@ -77,6 +81,9 @@ def fields ...@@ -77,6 +81,9 @@ def fields
end end
def execute(push_data) def execute(push_data)
object_kind = push_data[:object_kind]
return unless object_kind == "push"
ref = push_data[:ref].gsub('refs/heads/', '') ref = push_data[:ref].gsub('refs/heads/', '')
before = push_data[:before] before = push_data[:before]
after = push_data[:after] after = push_data[:after]
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# template :boolean default(FALSE) # 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)
# #
class RedmineService < IssueTrackerService class RedmineService < IssueTrackerService
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment