diff --git a/CHANGELOG b/CHANGELOG index 5270a81dfe0..de13ef3da55 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -32,6 +32,7 @@ v 7.8.2 - Fix response of push to repository to return "Not found" if user doesn't have access - Fix check if user is allowed to view the file attachment - Fix import check for case sensetive namespaces + - Added issue and merge request events to Slack service (Stan Hu) v 7.8.1 - Fix run of custom post receive hooks diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 82aad329c1a..087579de106 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -51,7 +51,8 @@ class Projects::ServicesController < Projects::ApplicationController :user_key, :device, :priority, :sound, :bamboo_url, :username, :password, :build_key, :server, :teamcity_url, :build_type, :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 diff --git a/app/models/project.rb b/app/models/project.rb index 907f331d8f1..c45338bf4eb 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -479,8 +479,9 @@ class Project < ActiveRecord::Base end end - def execute_services(data) - services.select(&:active).each do |service| + def execute_services(data, hooks_scope = :push_hooks) + # Call only service hooks that are active for this scope + services.send(hooks_scope).each do |service| service.async_execute(data) end end diff --git a/app/models/project_services/asana_service.rb b/app/models/project_services/asana_service.rb index 66b72572b9c..8ad1ad6267a 100644 --- a/app/models/project_services/asana_service.rb +++ b/app/models/project_services/asana_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # 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' @@ -61,13 +65,19 @@ automatically inspected. Leave blank to include all branches.' ] end - def execute(push) + def supported_events + %w(push) + end + + def execute(data) + return unless supported_events.include?(data[:object_kind]) + Asana.configure do |client| client.api_key = api_key end - user = push[:user_name] - branch = push[:ref].gsub('refs/heads/', '') + user = data[:user_name] + branch = data[:ref].gsub('refs/heads/', '') branch_restriction = restrict_to_branch.to_s @@ -79,7 +89,7 @@ automatically inspected. Leave blank to include all branches.' project_name = project.name_with_namespace push_msg = user + ' pushed to branch ' + branch + ' of ' + project_name - push[:commits].each do |commit| + data[:commits].each do |commit| check_commit(' ( ' + commit[:url] + ' ): ' + commit[:message], push_msg) end end diff --git a/app/models/project_services/assembla_service.rb b/app/models/project_services/assembla_service.rb index cf7598f35eb..02aa7c972e7 100644 --- a/app/models/project_services/assembla_service.rb +++ b/app/models/project_services/assembla_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # 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 @@ -38,8 +42,14 @@ class AssemblaService < Service ] end - def execute(push) + def supported_events + %w(push) + end + + def execute(data) + return unless supported_events.include?(data[:object_kind]) + 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 diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb index df68803152f..6c6d74c615e 100644 --- a/app/models/project_services/bamboo_service.rb +++ b/app/models/project_services/bamboo_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # 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 @@ -69,6 +73,10 @@ class BambooService < CiService ] end + def supported_events + %w(push) + end + def build_info(sha) url = URI.parse("#{bamboo_url}/rest/api/latest/result?label=#{sha}") @@ -118,7 +126,9 @@ class BambooService < CiService end end - def execute(_data) + def execute(data) + return unless supported_events.include?(data[:object_kind]) + # Bamboo requires a GET and does not take any data. self.class.get("#{bamboo_url}/updateAndBuild.action?buildKey=#{build_key}", verify: false) diff --git a/app/models/project_services/buildbox_service.rb b/app/models/project_services/buildbox_service.rb index 058c890ae45..96428c91711 100644 --- a/app/models/project_services/buildbox_service.rb +++ b/app/models/project_services/buildbox_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # 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" @@ -32,7 +36,13 @@ class BuildboxService < CiService hook.save end + def supported_events + %w(push) + end + def execute(data) + return unless supported_events.include?(data[:object_kind]) + service_hook.execute(data) end diff --git a/app/models/project_services/campfire_service.rb b/app/models/project_services/campfire_service.rb index 14b6b87a0b7..2f86fbe7a03 100644 --- a/app/models/project_services/campfire_service.rb +++ b/app/models/project_services/campfire_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # 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 @@ -37,11 +41,17 @@ class CampfireService < Service ] end - def execute(push_data) + def supported_events + %w(push) + end + + def execute(data) + return unless supported_events.include?(data[:object_kind]) + room = gate.find_room_by_name(self.room) return true unless room - message = build_message(push_data) + message = build_message(data) room.speak(message) end diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb index 5a26c25b3c3..646783c8733 100644 --- a/app/models/project_services/ci_service.rb +++ b/app/models/project_services/ci_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # template :boolean default(FALSE) +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean # # Base class for CI services @@ -21,6 +25,10 @@ class CiService < Service :ci end + def supported_events + %w(push) + end + # Return complete url to build page # # Ex. diff --git a/app/models/project_services/emails_on_push_service.rb b/app/models/project_services/emails_on_push_service.rb index 86693ad0c7e..21041e08a20 100644 --- a/app/models/project_services/emails_on_push_service.rb +++ b/app/models/project_services/emails_on_push_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # template :boolean default(FALSE) +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean # class EmailsOnPushService < Service @@ -29,8 +33,14 @@ class EmailsOnPushService < Service 'emails_on_push' end - def execute(push_data) - EmailsOnPushWorker.perform_async(project_id, recipients, push_data) + def supported_events + %w(push) + end + + def execute(data) + return unless supported_events.include?(data[:object_kind]) + + EmailsOnPushWorker.perform_async(project_id, recipients, data) end def fields diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb index 13e2dfceb1a..443dca72a8c 100644 --- a/app/models/project_services/flowdock_service.rb +++ b/app/models/project_services/flowdock_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # template :boolean default(FALSE) +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean # require "flowdock-git-hook" @@ -37,11 +41,17 @@ class FlowdockService < Service ] end - def execute(push_data) + def supported_events + %w(push) + end + + def execute(data) + return unless supported_events.include?(data[:object_kind]) + Flowdock::Git.post( - push_data[:ref], - push_data[:before], - push_data[:after], + data[:ref], + data[:before], + data[:after], token: token, repo: project.repository.path_to_repo, repo_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}", diff --git a/app/models/project_services/gemnasium_service.rb b/app/models/project_services/gemnasium_service.rb index a2c87ae88f1..41eedc215d5 100644 --- a/app/models/project_services/gemnasium_service.rb +++ b/app/models/project_services/gemnasium_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # template :boolean default(FALSE) +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean # require "gemnasium/gitlab_service" @@ -38,11 +42,17 @@ class GemnasiumService < Service ] end - def execute(push_data) + def supported_events + %w(push) + end + + def execute(data) + return unless supported_events.include?(data[:object_kind]) + Gemnasium::GitlabService.execute( - ref: push_data[:ref], - before: push_data[:before], - after: push_data[:after], + ref: data[:ref], + before: data[:before], + after: data[:after], token: token, api_key: api_key, repo: project.repository.path_to_repo diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb index f4b463e8199..02bf305f8f2 100644 --- a/app/models/project_services/gitlab_ci_service.rb +++ b/app/models/project_services/gitlab_ci_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # template :boolean default(FALSE) +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean # class GitlabCiService < CiService @@ -18,8 +22,6 @@ class GitlabCiService < CiService validates :project_url, presence: true, if: :activated? validates :token, presence: true, if: :activated? - delegate :execute, to: :service_hook, prefix: nil - after_save :compose_service_hook, if: :activated? def compose_service_hook @@ -28,6 +30,16 @@ class GitlabCiService < CiService hook.save end + def supported_events + %w(push tag_push) + end + + def execute(data) + return unless supported_events.include?(data[:object_kind]) + + service_hook.execute(data) + end + def commit_status_path(sha) project_url + "/commits/#{sha}/status.json?token=#{token}" end diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb index 05c048e4e45..00f8d430fd5 100644 --- a/app/models/project_services/gitlab_issue_tracker_service.rb +++ b/app/models/project_services/gitlab_issue_tracker_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # 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 diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb index 003e06a4c80..b85863d2f0d 100644 --- a/app/models/project_services/hipchat_service.rb +++ b/app/models/project_services/hipchat_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # template :boolean default(FALSE) +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean # class HipchatService < Service @@ -40,8 +44,14 @@ class HipchatService < Service ] end - def execute(push_data) - gate[room].send('GitLab', create_message(push_data)) + def supported_events + %w(push) + end + + def execute(data) + return unless supported_events.include?(data[:object_kind]) + + gate[room].send('GitLab', create_message(data)) end private diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index c991a34ecdb..bfc65b5379f 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # 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 @@ -65,7 +69,13 @@ class IssueTrackerService < Service end end + def supported_events + %w(push) + end + def execute(data) + return unless supported_events.include?(data[:object_kind]) + message = "#{self.type} was unable to reach #{self.project_url}. Check the url and try again." result = false diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index 4c056605ea8..20611eeb60c 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # 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 diff --git a/app/models/project_services/pivotaltracker_service.rb b/app/models/project_services/pivotaltracker_service.rb index 287812c57a5..a2fa9788f10 100644 --- a/app/models/project_services/pivotaltracker_service.rb +++ b/app/models/project_services/pivotaltracker_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # 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 @@ -37,9 +41,15 @@ class PivotaltrackerService < Service ] end - def execute(push) + def supported_events + %w(push) + end + + def execute(data) + return unless supported_events.include?(data[:object_kind]) + url = 'https://www.pivotaltracker.com/services/v5/source_commits' - push[:commits].each do |commit| + data[:commits].each do |commit| message = { 'source_commit' => { 'commit_id' => commit[:id], diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb index 3a3af59390a..586d9e94a95 100644 --- a/app/models/project_services/pushover_service.rb +++ b/app/models/project_services/pushover_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # 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 @@ -76,21 +80,27 @@ class PushoverService < Service ] end - def execute(push_data) - ref = push_data[:ref].gsub('refs/heads/', '') - before = push_data[:before] - after = push_data[:after] + def supported_events + %w(push) + end + + def execute(data) + return unless supported_events.include?(data[:object_kind]) + + ref = data[:ref].gsub('refs/heads/', '') + before = data[:before] + after = data[:after] if before.include?('000000') - message = "#{push_data[:user_name]} pushed new branch \"#{ref}\"." + message = "#{data[:user_name]} pushed new branch \"#{ref}\"." elsif after.include?('000000') - message = "#{push_data[:user_name]} deleted branch \"#{ref}\"." + message = "#{data[:user_name]} deleted branch \"#{ref}\"." else - message = "#{push_data[:user_name]} push to branch \"#{ref}\"." + message = "#{data[:user_name]} push to branch \"#{ref}\"." end - if push_data[:total_commits_count] > 0 - message << "\nTotal commits count: #{push_data[:total_commits_count]}" + if data[:total_commits_count] > 0 + message << "\nTotal commits count: #{data[:total_commits_count]}" end pushover_data = { @@ -100,7 +110,7 @@ class PushoverService < Service priority: priority, title: "#{project.name_with_namespace}", message: message, - url: push_data[:repository][:homepage], + url: data[:repository][:homepage], url_title: "See project #{project.name_with_namespace}" } diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb index e1dc10415e0..f96eae2daa1 100644 --- a/app/models/project_services/redmine_service.rb +++ b/app/models/project_services/redmine_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # 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 diff --git a/app/models/project_services/slack_message.rb b/app/models/project_services/slack_message.rb deleted file mode 100644 index 6c6446db45f..00000000000 --- a/app/models/project_services/slack_message.rb +++ /dev/null @@ -1,110 +0,0 @@ -require 'slack-notifier' - -class SlackMessage - attr_reader :after - attr_reader :before - attr_reader :commits - attr_reader :project_name - attr_reader :project_url - attr_reader :ref - attr_reader :username - - def initialize(params) - @after = params.fetch(:after) - @before = params.fetch(:before) - @commits = params.fetch(:commits, []) - @project_name = params.fetch(:project_name) - @project_url = params.fetch(:project_url) - @ref = params.fetch(:ref).gsub('refs/heads/', '') - @username = params.fetch(:user_name) - end - - def pretext - format(message) - end - - def attachments - return [] if new_branch? || removed_branch? - - commit_message_attachments - end - - private - - def message - if new_branch? - new_branch_message - elsif removed_branch? - removed_branch_message - else - push_message - end - end - - def format(string) - Slack::Notifier::LinkFormatter.format(string) - end - - def new_branch_message - "#{username} pushed new branch #{branch_link} to #{project_link}" - end - - def removed_branch_message - "#{username} removed branch #{ref} from #{project_link}" - end - - def push_message - "#{username} pushed to branch #{branch_link} of #{project_link} (#{compare_link})" - end - - def commit_messages - commits.each_with_object('') do |commit, str| - str << compose_commit_message(commit) - end.chomp - end - - def commit_message_attachments - [{ text: format(commit_messages), color: attachment_color }] - end - - def compose_commit_message(commit) - author = commit.fetch(:author).fetch(:name) - id = commit.fetch(:id)[0..8] - message = commit.fetch(:message) - url = commit.fetch(:url) - - "[#{id}](#{url}): #{message} - #{author}\n" - end - - def new_branch? - before.include?('000000') - end - - def removed_branch? - after.include?('000000') - end - - def branch_url - "#{project_url}/commits/#{ref}" - end - - def compare_url - "#{project_url}/compare/#{before}...#{after}" - end - - def branch_link - "[#{ref}](#{branch_url})" - end - - def project_link - "[#{project_name}](#{project_url})" - end - - def compare_link - "[Compare changes](#{compare_url})" - end - - def attachment_color - '#345' - end -end diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb index c7cbff63fe5..64d6f4327b8 100644 --- a/app/models/project_services/slack_service.rb +++ b/app/models/project_services/slack_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # 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 SlackService < Service @@ -38,20 +42,43 @@ class SlackService < Service ] end - def execute(push_data) + def supported_events + %w(push issue merge_request) + end + + def execute(data) + return unless supported_events.include?(data[:object_kind]) return unless webhook.present? - message = SlackMessage.new(push_data.merge( + 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 = \ + case object_kind + when "push" + PushMessage.new(data) + when "issue" + IssueMessage.new(data) unless is_update?(data) + when "merge_request" + MergeMessage.new(data) unless is_update?(data) + end opt = {} opt[:channel] = channel if channel opt[:username] = username if username - notifier = Slack::Notifier.new(webhook, opt) - notifier.ping(message.pretext, attachments: message.attachments) + if message + notifier = Slack::Notifier.new(webhook, opt) + notifier.ping(message.pretext, attachments: message.attachments) + end end private @@ -63,4 +90,12 @@ class SlackService < Service def project_url project.web_url end + + def is_update?(data) + data[:object_attributes][:action] == 'update' + end end + +require "slack_service/issue_message" +require "slack_service/push_message" +require "slack_service/merge_message" diff --git a/app/models/project_services/slack_service/base_message.rb b/app/models/project_services/slack_service/base_message.rb new file mode 100644 index 00000000000..aa00d6061a1 --- /dev/null +++ b/app/models/project_services/slack_service/base_message.rb @@ -0,0 +1,31 @@ +require 'slack-notifier' + +class SlackService + class BaseMessage + def initialize(params) + raise NotImplementedError + end + + def pretext + format(message) + end + + def attachments + raise NotImplementedError + end + + private + + def message + raise NotImplementedError + end + + def format(string) + Slack::Notifier::LinkFormatter.format(string) + end + + def attachment_color + '#345' + end + end +end diff --git a/app/models/project_services/slack_service/issue_message.rb b/app/models/project_services/slack_service/issue_message.rb new file mode 100644 index 00000000000..e2fed0bb1b9 --- /dev/null +++ b/app/models/project_services/slack_service/issue_message.rb @@ -0,0 +1,56 @@ +class SlackService + class IssueMessage < BaseMessage + attr_reader :username + attr_reader :title + attr_reader :project_name + attr_reader :project_url + attr_reader :issue_iid + attr_reader :issue_url + attr_reader :action + attr_reader :state + attr_reader :description + + def initialize(params) + @username = params[:user][:username] + @project_name = params[:project_name] + @project_url = params[:project_url] + + obj_attr = params[:object_attributes] + obj_attr = HashWithIndifferentAccess.new(obj_attr) + @title = obj_attr[:title] + @issue_iid = obj_attr[:iid] + @issue_url = obj_attr[:url] + @action = obj_attr[:action] + @state = obj_attr[:state] + @description = obj_attr[:description] + end + + def attachments + return [] unless opened_issue? + + description_message + end + + private + + def message + "#{username} #{state} issue #{issue_link} in #{project_link}: #{title}" + end + + def opened_issue? + action == "open" + end + + def description_message + [{ text: format(description), color: attachment_color }] + end + + def project_link + "[#{project_name}](#{project_url})" + end + + def issue_link + "[##{issue_iid}](#{issue_url})" + end + end +end diff --git a/app/models/project_services/slack_service/merge_message.rb b/app/models/project_services/slack_service/merge_message.rb new file mode 100644 index 00000000000..4dcce1d15a0 --- /dev/null +++ b/app/models/project_services/slack_service/merge_message.rb @@ -0,0 +1,54 @@ +class SlackService + class MergeMessage < BaseMessage + attr_reader :username + attr_reader :project_name + attr_reader :project_url + attr_reader :merge_request_id + attr_reader :source_branch + attr_reader :target_branch + attr_reader :state + + def initialize(params) + @username = params[:user][:username] + @project_name = params[:project_name] + @project_url = params[:project_url] + + obj_attr = params[:object_attributes] + obj_attr = HashWithIndifferentAccess.new(obj_attr) + @merge_request_id = obj_attr[:iid] + @source_branch = obj_attr[:source_branch] + @target_branch = obj_attr[:target_branch] + @state = obj_attr[:state] + end + + def pretext + format(message) + end + + def attachments + [] + end + + private + + def message + merge_request_message + end + + def project_link + "[#{project_name}](#{project_url})" + end + + def merge_request_message + "#{username} #{state} merge request #{merge_request_link} in #{project_link}" + end + + def merge_request_link + "[##{merge_request_id}](#{merge_request_url})" + end + + def merge_request_url + "#{project_url}/merge_requests/#{merge_request_id}" + end + end +end diff --git a/app/models/project_services/slack_service/push_message.rb b/app/models/project_services/slack_service/push_message.rb new file mode 100644 index 00000000000..2e566bc317b --- /dev/null +++ b/app/models/project_services/slack_service/push_message.rb @@ -0,0 +1,108 @@ +class SlackService + class PushMessage < BaseMessage + attr_reader :after + attr_reader :before + attr_reader :commits + attr_reader :project_name + attr_reader :project_url + attr_reader :ref + attr_reader :username + + def initialize(params) + @after = params[:after] + @before = params[:before] + @commits = params.fetch(:commits, []) + @project_name = params[:project_name] + @project_url = params[:project_url] + @ref = params[:ref].gsub('refs/heads/', '') + @username = params[:user_name] + end + + def pretext + format(message) + end + + def attachments + return [] if new_branch? || removed_branch? + + commit_message_attachments + end + + private + + def message + if new_branch? + new_branch_message + elsif removed_branch? + removed_branch_message + else + push_message + end + end + + def format(string) + Slack::Notifier::LinkFormatter.format(string) + end + + def new_branch_message + "#{username} pushed new branch #{branch_link} to #{project_link}" + end + + def removed_branch_message + "#{username} removed branch #{ref} from #{project_link}" + end + + def push_message + "#{username} pushed to branch #{branch_link} of #{project_link} (#{compare_link})" + end + + def commit_messages + commits.map { |commit| compose_commit_message(commit) }.join("\n") + end + + def commit_message_attachments + [{ text: format(commit_messages), color: attachment_color }] + end + + def compose_commit_message(commit) + author = commit[:author][:name] + id = Commit.truncate_sha(commit[:id]) + message = commit[:message] + url = commit[:url] + + "[#{id}](#{url}): #{message} - #{author}" + end + + def new_branch? + before.include?('000000') + end + + def removed_branch? + after.include?('000000') + end + + def branch_url + "#{project_url}/commits/#{ref}" + end + + def compare_url + "#{project_url}/compare/#{before}...#{after}" + end + + def branch_link + "[#{ref}](#{branch_url})" + end + + def project_link + "[#{project_name}](#{project_url})" + end + + def compare_link + "[Compare changes](#{compare_url})" + end + + def attachment_color + '#345' + end + end +end diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb index b6932f1c77b..686e6225a2e 100644 --- a/app/models/project_services/teamcity_service.rb +++ b/app/models/project_services/teamcity_service.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # 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 TeamcityService < CiService @@ -57,6 +61,10 @@ class TeamcityService < CiService 'teamcity' end + def supported_events + %w(push) + end + def fields [ { type: 'text', name: 'teamcity_url', @@ -115,13 +123,15 @@ class TeamcityService < CiService end end - def execute(push) + def execute(data) + return unless supported_events.include?(data[:object_kind]) + auth = { username: username, password: password, } - branch = push[:ref].gsub('refs/heads/', '') + branch = data[:ref].gsub('refs/heads/', '') self.class.post("#{teamcity_url}/httpAuth/app/rest/buildQueue", body: ""\ diff --git a/app/models/service.rb b/app/models/service.rb index f4e97da3212..98bd40ae95e 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -11,6 +11,11 @@ # active :boolean default(FALSE), not null # properties :text # template :boolean default(FALSE) +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean +# # To add new service you should build a class inherited from Service # and implement a set of methods @@ -19,6 +24,10 @@ class Service < ActiveRecord::Base serialize :properties, JSON default_value_for :active, false + default_value_for :push_events, true + default_value_for :issues_events, true + default_value_for :merge_requests_events, true + default_value_for :tag_push_events, true after_initialize :initialize_properties @@ -29,6 +38,11 @@ class Service < ActiveRecord::Base scope :visible, -> { where.not(type: 'GitlabIssueTrackerService') } + scope :push_hooks, -> { where(push_events: true, active: true) } + scope :tag_push_hooks, -> { where(tag_push_events: true, active: true) } + scope :issue_hooks, -> { where(issues_events: true, active: true) } + scope :merge_request_hooks, -> { where(merge_requests_events: true, active: true) } + def activated? active end @@ -66,6 +80,10 @@ class Service < ActiveRecord::Base [] end + def supported_events + %w(push tag_push issue merge_request) + end + def execute # implement inside child end @@ -91,6 +109,8 @@ class Service < ActiveRecord::Base end def async_execute(data) + return unless supported_events.include?(data[:object_kind]) + Sidekiq::Client.enqueue(ProjectServiceWorker, id, data) end diff --git a/app/services/create_tag_service.rb b/app/services/create_tag_service.rb index a735d3f7f20..8cd65724cb9 100644 --- a/app/services/create_tag_service.rb +++ b/app/services/create_tag_service.rb @@ -21,12 +21,12 @@ class CreateTagService < BaseService new_tag = repository.find_tag(tag_name) if new_tag - if project.gitlab_ci? - push_data = create_push_data(project, current_user, new_tag) - project.gitlab_ci_service.async_execute(push_data) - end - EventCreateService.new.push_ref(project, current_user, new_tag, 'add', 'refs/tags') + + push_data = create_push_data(project, current_user, new_tag) + project.execute_hooks(push_data.dup, :tag_push_hooks) + project.execute_services(push_data.dup, :tag_push_hooks) + success(new_tag) else error('Invalid reference name') @@ -40,7 +40,9 @@ class CreateTagService < BaseService end def create_push_data(project, user, tag) - Gitlab::PushDataBuilder. + data = Gitlab::PushDataBuilder. build(project, user, Gitlab::Git::BLANK_SHA, tag.target, 'refs/tags/' + tag.name, []) + data[:object_kind] = "tag_push" + data end end diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index f21e6ac207d..13def127763 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -54,7 +54,7 @@ class GitPushService @push_data = post_receive_data(oldrev, newrev, ref) EventCreateService.new.push(project, user, @push_data) project.execute_hooks(@push_data.dup, :push_hooks) - project.execute_services(@push_data.dup) + project.execute_services(@push_data.dup, :push_hooks) end end diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb index 46d8987f12d..cd92f50b02a 100644 --- a/app/services/git_tag_push_service.rb +++ b/app/services/git_tag_push_service.rb @@ -8,10 +8,7 @@ class GitTagPushService EventCreateService.new.push(project, user, @push_data) project.repository.expire_cache project.execute_hooks(@push_data.dup, :tag_push_hooks) - - if project.gitlab_ci? - project.gitlab_ci_service.async_execute(@push_data) - end + project.execute_services(@push_data.dup, :tag_push_hooks) true end @@ -19,7 +16,8 @@ class GitTagPushService private def create_push_data(oldrev, newrev, ref) - Gitlab::PushDataBuilder. - build(project, user, oldrev, newrev, ref, []) + data = Gitlab::PushDataBuilder.build(project, user, oldrev, newrev, ref, []) + data[:object_kind] = "tag_push" + data end end diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb index 755c0ef45a8..c3ca04a4343 100644 --- a/app/services/issues/base_service.rb +++ b/app/services/issues/base_service.rb @@ -1,13 +1,19 @@ module Issues class BaseService < ::IssuableBaseService + def hook_data(issue, action) + issue_data = issue.to_hook_data(current_user) + issue_url = Gitlab::UrlBuilder.new(:issue).build(issue.id) + issue_data[:object_attributes].merge!(url: issue_url, action: action) + issue_data + end + private def execute_hooks(issue, action = 'open') - issue_data = issue.to_hook_data(current_user) - issue_url = Gitlab::UrlBuilder.new(:issue).build(issue.id) - issue_data[:object_attributes].merge!(url: issue_url, action: action) + issue_data = hook_data(issue, action) issue.project.execute_hooks(issue_data, :issue_hooks) + issue.project.execute_services(issue_data, :issue_hooks) end end end diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb index b4199d1c800..f6e1ae6f283 100644 --- a/app/services/merge_requests/base_service.rb +++ b/app/services/merge_requests/base_service.rb @@ -5,13 +5,19 @@ module MergeRequests Note.create_status_change_note(merge_request, merge_request.target_project, current_user, merge_request.state, nil) end + def hook_data(merge_request, action) + hook_data = merge_request.to_hook_data(current_user) + merge_request_url = Gitlab::UrlBuilder.new(:merge_request).build(merge_request.id) + hook_data[:object_attributes][:url] = merge_request_url + hook_data[:object_attributes][:action] = action + hook_data + end + def execute_hooks(merge_request, action = 'open') if merge_request.project - hook_data = merge_request.to_hook_data(current_user) - merge_request_url = Gitlab::UrlBuilder.new(:merge_request).build(merge_request.id) - hook_data[:object_attributes][:url] = merge_request_url - hook_data[:object_attributes][:action] = action - merge_request.project.execute_hooks(hook_data, :merge_request_hooks) + merge_data = hook_data(merge_request, action) + merge_request.project.execute_hooks(merge_data, :merge_request_hooks) + merge_request.project.execute_services(merge_data, :merge_request_hooks) end end end diff --git a/app/views/admin/services/_form.html.haml b/app/views/admin/services/_form.html.haml index 5df8849317b..62f4001ca66 100644 --- a/app/views/admin/services/_form.html.haml +++ b/app/views/admin/services/_form.html.haml @@ -14,6 +14,43 @@ = preserve do = markdown @service.help + .form-group + = f.label :url, "Trigger", class: 'control-label' + - if @service.supported_events.length > 1 + .col-sm-10 + - if @service.supported_events.include?("push") + %div + = f.check_box :push_events, class: 'pull-left' + .prepend-left-20 + = f.label :push_events, class: 'list-label' do + %strong Push events + %p.light + This url will be triggered by a push to the repository + - if @service.supported_events.include?("tag_push") + %div + = f.check_box :tag_push_events, class: 'pull-left' + .prepend-left-20 + = f.label :tag_push_events, class: 'list-label' do + %strong Tag push events + %p.light + This url will be triggered when a new tag is pushed to the repository + - if @service.supported_events.include?("issue") + %div + = f.check_box :issues_events, class: 'pull-left' + .prepend-left-20 + = f.label :issues_events, class: 'list-label' do + %strong Issues events + %p.light + This url will be triggered when an issue is created + - if @service.supported_events.include?("merge_request") + %div + = f.check_box :merge_requests_events, class: 'pull-left' + .prepend-left-20 + = f.label :merge_requests_events, class: 'list-label' do + %strong Merge Request events + %p.light + This url will be triggered when a merge request is created + - @service.fields.each do |field| - name = field[:name] - value = @service.send(name) unless field[:type] == 'password' diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml index 8db6d67e06b..55ac85c32b9 100644 --- a/app/views/projects/services/_form.html.haml +++ b/app/views/projects/services/_form.html.haml @@ -27,6 +27,43 @@ .col-sm-10 = f.check_box :active + .form-group + = f.label :url, "Trigger", class: 'control-label' + - if @service.supported_events.length > 1 + .col-sm-10 + - if @service.supported_events.include?("push") + %div + = f.check_box :push_events, class: 'pull-left' + .prepend-left-20 + = f.label :push_events, class: 'list-label' do + %strong Push events + %p.light + This url will be triggered by a push to the repository + - if @service.supported_events.include?("tag_push") + %div + = f.check_box :tag_push_events, class: 'pull-left' + .prepend-left-20 + = f.label :tag_push_events, class: 'list-label' do + %strong Tag push events + %p.light + This url will be triggered when a new tag is pushed to the repository + - if @service.supported_events.include?("issue") + %div + = f.check_box :issues_events, class: 'pull-left' + .prepend-left-20 + = f.label :issues_events, class: 'list-label' do + %strong Issues events + %p.light + This url will be triggered when an issue is created + - if @service.supported_events.include?("merge_request") + %div + = f.check_box :merge_requests_events, class: 'pull-left' + .prepend-left-20 + = f.label :merge_requests_events, class: 'list-label' do + %strong Merge Request events + %p.light + This url will be triggered when a merge request is created + - @service.fields.each do |field| - name = field[:name] - value = @service.send(name) unless field[:type] == 'password' diff --git a/db/migrate/20150219004514_add_events_to_services.rb b/db/migrate/20150219004514_add_events_to_services.rb new file mode 100644 index 00000000000..cf73a0174f4 --- /dev/null +++ b/db/migrate/20150219004514_add_events_to_services.rb @@ -0,0 +1,8 @@ +class AddEventsToServices < ActiveRecord::Migration + def change + add_column :services, :push_events, :boolean, :default => true + add_column :services, :issues_events, :boolean, :default => true + add_column :services, :merge_requests_events, :boolean, :default => true + add_column :services, :tag_push_events, :boolean, :default => true + end +end diff --git a/db/schema.rb b/db/schema.rb index 2659efe4df9..1a9b512e159 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -364,9 +364,13 @@ ActiveRecord::Schema.define(version: 20150223022001) do t.integer "project_id" t.datetime "created_at" t.datetime "updated_at" - t.boolean "active", default: false, null: false + t.boolean "active", default: false, null: false t.text "properties" - t.boolean "template", default: false + t.boolean "template", default: false + t.boolean "push_events", default: true + t.boolean "issues_events", default: true + t.boolean "merge_requests_events", default: true + t.boolean "tag_push_events", default: true end add_index "services", ["created_at", "id"], name: "index_services_on_created_at_and_id", using: :btree diff --git a/lib/gitlab/push_data_builder.rb b/lib/gitlab/push_data_builder.rb index 6a72efa7221..5cefa67d3ab 100644 --- a/lib/gitlab/push_data_builder.rb +++ b/lib/gitlab/push_data_builder.rb @@ -30,6 +30,7 @@ module Gitlab # Hash to be passed as post_receive_data data = { + object_kind: "push", before: oldrev, after: newrev, ref: ref, diff --git a/spec/models/project_services/assembla_service_spec.rb b/spec/models/project_services/assembla_service_spec.rb index ee7f780c8f6..cd34e006ebe 100644 --- a/spec/models/project_services/assembla_service_spec.rb +++ b/spec/models/project_services/assembla_service_spec.rb @@ -2,14 +2,18 @@ # # 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 +# 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 +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean # require 'spec_helper' diff --git a/spec/models/project_services/buildbox_service_spec.rb b/spec/models/project_services/buildbox_service_spec.rb index 050363e14c7..c246e1c9d41 100644 --- a/spec/models/project_services/buildbox_service_spec.rb +++ b/spec/models/project_services/buildbox_service_spec.rb @@ -2,14 +2,18 @@ # # 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 +# 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 +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean # require 'spec_helper' diff --git a/spec/models/project_services/flowdock_service_spec.rb b/spec/models/project_services/flowdock_service_spec.rb index b34e36bc940..2ec167a7330 100644 --- a/spec/models/project_services/flowdock_service_spec.rb +++ b/spec/models/project_services/flowdock_service_spec.rb @@ -2,14 +2,18 @@ # # 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 +# 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 +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean # require 'spec_helper' diff --git a/spec/models/project_services/gemnasium_service_spec.rb b/spec/models/project_services/gemnasium_service_spec.rb index fe5d62b2f53..5f665fadfff 100644 --- a/spec/models/project_services/gemnasium_service_spec.rb +++ b/spec/models/project_services/gemnasium_service_spec.rb @@ -2,14 +2,18 @@ # # 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 +# 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 +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean # require 'spec_helper' diff --git a/spec/models/project_services/gitlab_ci_service_spec.rb b/spec/models/project_services/gitlab_ci_service_spec.rb index 0cd255f08ea..fcb33b11732 100644 --- a/spec/models/project_services/gitlab_ci_service_spec.rb +++ b/spec/models/project_services/gitlab_ci_service_spec.rb @@ -2,14 +2,18 @@ # # 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 +# 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 +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean # require 'spec_helper' diff --git a/spec/models/project_services/pushover_service_spec.rb b/spec/models/project_services/pushover_service_spec.rb index 188626a7a27..bb2e72c3ac1 100644 --- a/spec/models/project_services/pushover_service_spec.rb +++ b/spec/models/project_services/pushover_service_spec.rb @@ -2,14 +2,18 @@ # # 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 +# 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 +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean # require 'spec_helper' diff --git a/spec/models/project_services/slack_service/issue_message_spec.rb b/spec/models/project_services/slack_service/issue_message_spec.rb new file mode 100644 index 00000000000..a23a7cc068e --- /dev/null +++ b/spec/models/project_services/slack_service/issue_message_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe SlackService::IssueMessage do + subject { SlackService::IssueMessage.new(args) } + + let(:args) { + { + user: { + username: 'username' + }, + project_name: 'project_name', + project_url: 'somewhere.com', + + object_attributes: { + title: 'Issue title', + id: 10, + iid: 100, + assignee_id: 1, + url: 'url', + action: 'open', + state: 'opened', + description: 'issue description' + } + } + } + + let(:color) { '#345' } + + context 'open' do + it 'returns a message regarding opening of issues' do + expect(subject.pretext).to eq( + 'username opened issue in : '\ + 'Issue title') + expect(subject.attachments).to eq([ + { + text: "issue description", + color: color, + } + ]) + end + end + + context 'close' do + before do + args[:object_attributes][:action] = 'close' + args[:object_attributes][:state] = 'closed' + end + it 'returns a message regarding closing of issues' do + expect(subject.pretext). to eq( + 'username closed issue in : '\ + 'Issue title') + expect(subject.attachments).to be_empty + end + end +end diff --git a/spec/models/project_services/slack_service/merge_message_spec.rb b/spec/models/project_services/slack_service/merge_message_spec.rb new file mode 100644 index 00000000000..25d03cd8736 --- /dev/null +++ b/spec/models/project_services/slack_service/merge_message_spec.rb @@ -0,0 +1,50 @@ +require 'spec_helper' + +describe SlackService::MergeMessage do + subject { SlackService::MergeMessage.new(args) } + + let(:args) { + { + user: { + username: 'username' + }, + project_name: 'project_name', + project_url: 'somewhere.com', + + object_attributes: { + title: 'Issue title', + id: 10, + iid: 100, + assignee_id: 1, + url: 'url', + state: 'opened', + description: 'issue description', + source_branch: 'source_branch', + target_branch: 'target_branch', + } + } + } + + let(:color) { '#345' } + + context 'open' do + it 'returns a message regarding opening of merge requests' do + expect(subject.pretext).to eq( + 'username opened merge request '\ + 'in ') + expect(subject.attachments).to be_empty + end + end + + context 'close' do + before do + args[:object_attributes][:state] = 'closed' + end + it 'returns a message regarding closing of merge requests' do + expect(subject.pretext).to eq( + 'username closed merge request '\ + 'in ') + expect(subject.attachments).to be_empty + end + end +end diff --git a/spec/models/project_services/slack_message_spec.rb b/spec/models/project_services/slack_service/push_message_spec.rb similarity index 88% rename from spec/models/project_services/slack_message_spec.rb rename to spec/models/project_services/slack_service/push_message_spec.rb index 7197a94e53f..ef0e7a6ee30 100644 --- a/spec/models/project_services/slack_message_spec.rb +++ b/spec/models/project_services/slack_service/push_message_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' -describe SlackMessage do - subject { SlackMessage.new(args) } +describe SlackService::PushMessage do + subject { SlackService::PushMessage.new(args) } let(:args) { { @@ -31,8 +31,8 @@ describe SlackMessage do ) expect(subject.attachments).to eq([ { - text: ": message1 - author1\n"\ - ": message2 - author2", + text: ": message1 - author1\n"\ + ": message2 - author2", color: color, } ]) diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb index 8a75d8987ab..9024e53f0ff 100644 --- a/spec/models/project_services/slack_service_spec.rb +++ b/spec/models/project_services/slack_service_spec.rb @@ -2,14 +2,18 @@ # # 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 +# 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 +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean # require 'spec_helper' @@ -34,7 +38,7 @@ describe SlackService do let(:slack) { SlackService.new } let(:user) { create(:user) } let(:project) { create(:project) } - let(:sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) } + let(:push_sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) } let(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' } let(:username) { 'slack_username' } let(:channel) { 'slack_channel' } @@ -48,10 +52,43 @@ describe SlackService do ) WebMock.stub_request(:post, webhook_url) + + opts = { + title: 'Awesome issue', + description: 'please fix' + } + + issue_service = Issues::CreateService.new(project, user, opts) + @issue = issue_service.execute + @issues_sample_data = issue_service.hook_data(@issue, 'open') + + opts = { + title: 'Awesome merge_request', + description: 'please fix', + source_branch: 'stable', + target_branch: 'master' + } + merge_service = MergeRequests::CreateService.new(project, + user, opts) + @merge_request = merge_service.execute + @merge_sample_data = merge_service.hook_data(@merge_request, + 'open') end - it "should call Slack API" do - slack.execute(sample_data) + it "should call Slack API for pull requests" do + slack.execute(push_sample_data) + + WebMock.should have_requested(:post, webhook_url).once + end + + it "should call Slack API for issue events" do + slack.execute(@issues_sample_data) + + WebMock.should have_requested(:post, webhook_url).once + end + + it "should call Slack API for merge requests events" do + slack.execute(@merge_sample_data) expect(WebMock).to have_requested(:post, webhook_url).once end @@ -62,8 +99,8 @@ describe SlackService do with(webhook_url, username: username). and_return( double(:slack_service).as_null_object - ) - slack.execute(sample_data) + ) + slack.execute(push_sample_data) end it 'should use the channel as an option when it is configured' do @@ -73,7 +110,7 @@ describe SlackService do and_return( double(:slack_service).as_null_object ) - slack.execute(sample_data) + slack.execute(push_sample_data) end end end diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index 9a1248055b1..cc047a20dd2 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -11,6 +11,10 @@ # active :boolean default(FALSE), not null # properties :text # template :boolean default(FALSE) +# push_events :boolean +# issues_events :boolean +# merge_requests_events :boolean +# tag_push_events :boolean # require 'spec_helper' diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 9924935094e..e264072b573 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -49,6 +49,7 @@ describe GitPushService do subject { @push_data } + it { is_expected.to include(object_kind: 'push') } it { is_expected.to include(before: @oldrev) } it { is_expected.to include(after: @newrev) } it { is_expected.to include(ref: @ref) }