Commit bca260ad authored by Robert Speicher's avatar Robert Speicher

Merge branch 'ee-slack-protected-branch-notification' into 'master'

[EE port]  Support notifications to be fired for protected branches also

See merge request gitlab-org/gitlab!16405
parents 1d197c06 3e12f61a
...@@ -10,6 +10,7 @@ module ServiceParams ...@@ -10,6 +10,7 @@ module ServiceParams
:api_url, :api_url,
:api_version, :api_version,
:bamboo_url, :bamboo_url,
:branches_to_be_notified,
:build_key, :build_key,
:build_type, :build_type,
:ca_pem, :ca_pem,
...@@ -41,7 +42,6 @@ module ServiceParams ...@@ -41,7 +42,6 @@ module ServiceParams
:new_issue_url, :new_issue_url,
:notify, :notify,
:notify_only_broken_pipelines, :notify_only_broken_pipelines,
:notify_only_default_branch,
:password, :password,
:priority, :priority,
:project_key, :project_key,
......
# frozen_string_literal: true
# Concern handling functionality around deciding whether to send notification
# for activities on a specified branch or not. Will be included in
# ChatNotificationService and PipelinesEmailService classes.
module NotificationBranchSelection
extend ActiveSupport::Concern
BRANCH_CHOICES = [
[_('All branches'), 'all'],
[_('Default branch'), 'default'],
[_('Protected branches'), 'protected'],
[_('Default branch and protected branches'), 'default_and_protected']
].freeze
def notify_for_branch?(data)
ref = if data[:ref]
Gitlab::Git.ref_name(data[:ref])
else
data.dig(:object_attributes, :ref)
end
is_default_branch = ref == project.default_branch
is_protected_branch = project.protected_branches.exists?(name: ref)
case branches_to_be_notified
when "all"
true
when "default"
is_default_branch
when "protected"
is_protected_branch
when "default_and_protected"
is_default_branch || is_protected_branch
else
false
end
end
end
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
# This class is not meant to be used directly, but only to inherit from. # This class is not meant to be used directly, but only to inherit from.
class ChatNotificationService < Service class ChatNotificationService < Service
include ChatMessage include ChatMessage
include NotificationBranchSelection
SUPPORTED_EVENTS = %w[ SUPPORTED_EVENTS = %w[
push issue confidential_issue merge_request note confidential_note push issue confidential_issue merge_request note confidential_note
...@@ -14,7 +15,7 @@ class ChatNotificationService < Service ...@@ -14,7 +15,7 @@ class ChatNotificationService < Service
default_value_for :category, 'chat' default_value_for :category, 'chat'
prop_accessor :webhook, :username, :channel prop_accessor :webhook, :username, :channel, :branches_to_be_notified
# Custom serialized properties initialization # Custom serialized properties initialization
prop_accessor(*SUPPORTED_EVENTS.map { |event| EVENT_CHANNEL[event] }) prop_accessor(*SUPPORTED_EVENTS.map { |event| EVENT_CHANNEL[event] })
...@@ -27,7 +28,16 @@ class ChatNotificationService < Service ...@@ -27,7 +28,16 @@ class ChatNotificationService < Service
if properties.nil? if properties.nil?
self.properties = {} self.properties = {}
self.notify_only_broken_pipelines = true self.notify_only_broken_pipelines = true
self.notify_only_default_branch = true self.branches_to_be_notified = "default"
elsif !self.notify_only_default_branch.nil?
# In older versions, there was only a boolean property named
# `notify_only_default_branch`. Now we have a string property named
# `branches_to_be_notified`. Instead of doing a background migration, we
# opted to set a value for the new property based on the old one, if
# users hasn't specified one already. When users edit the service and
# selects a value for this new property, it will override everything.
self.branches_to_be_notified ||= notify_only_default_branch? ? "default" : "all"
end end
end end
...@@ -52,7 +62,7 @@ class ChatNotificationService < Service ...@@ -52,7 +62,7 @@ class ChatNotificationService < Service
{ type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}", required: true }, { type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}", required: true },
{ type: 'text', name: 'username', placeholder: 'e.g. GitLab' }, { type: 'text', name: 'username', placeholder: 'e.g. GitLab' },
{ type: 'checkbox', name: 'notify_only_broken_pipelines' }, { type: 'checkbox', name: 'notify_only_broken_pipelines' },
{ type: 'checkbox', name: 'notify_only_default_branch' } { type: 'select', name: 'branches_to_be_notified', choices: BRANCH_CHOICES }
] ]
end end
...@@ -168,15 +178,8 @@ class ChatNotificationService < Service ...@@ -168,15 +178,8 @@ class ChatNotificationService < Service
def notify_for_ref?(data) def notify_for_ref?(data)
return true if data[:object_kind] == 'tag_push' return true if data[:object_kind] == 'tag_push'
return true if data.dig(:object_attributes, :tag) return true if data.dig(:object_attributes, :tag)
return true unless notify_only_default_branch?
ref = if data[:ref] notify_for_branch?(data)
Gitlab::Git.ref_name(data[:ref])
else
data.dig(:object_attributes, :ref)
end
ref == project.default_branch
end end
def notify_for_pipeline?(data) def notify_for_pipeline?(data)
......
...@@ -42,7 +42,7 @@ class DiscordService < ChatNotificationService ...@@ -42,7 +42,7 @@ class DiscordService < ChatNotificationService
[ [
{ type: "text", name: "webhook", placeholder: "e.g. https://discordapp.com/api/webhooks/…" }, { type: "text", name: "webhook", placeholder: "e.g. https://discordapp.com/api/webhooks/…" },
{ type: "checkbox", name: "notify_only_broken_pipelines" }, { type: "checkbox", name: "notify_only_broken_pipelines" },
{ type: "checkbox", name: "notify_only_default_branch" } { type: 'select', name: 'branches_to_be_notified', choices: BRANCH_CHOICES }
] ]
end end
......
...@@ -44,7 +44,7 @@ class HangoutsChatService < ChatNotificationService ...@@ -44,7 +44,7 @@ class HangoutsChatService < ChatNotificationService
[ [
{ type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}" }, { type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}" },
{ type: 'checkbox', name: 'notify_only_broken_pipelines' }, { type: 'checkbox', name: 'notify_only_broken_pipelines' },
{ type: 'checkbox', name: 'notify_only_default_branch' } { type: 'select', name: 'branches_to_be_notified', choices: BRANCH_CHOICES }
] ]
end end
......
...@@ -42,7 +42,7 @@ class MicrosoftTeamsService < ChatNotificationService ...@@ -42,7 +42,7 @@ class MicrosoftTeamsService < ChatNotificationService
[ [
{ type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}" }, { type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}" },
{ type: 'checkbox', name: 'notify_only_broken_pipelines' }, { type: 'checkbox', name: 'notify_only_broken_pipelines' },
{ type: 'checkbox', name: 'notify_only_default_branch' } { type: 'select', name: 'branches_to_be_notified', choices: BRANCH_CHOICES }
] ]
end end
......
# frozen_string_literal: true # frozen_string_literal: true
class PipelinesEmailService < Service class PipelinesEmailService < Service
prop_accessor :recipients include NotificationBranchSelection
prop_accessor :recipients, :branches_to_be_notified
boolean_accessor :notify_only_broken_pipelines, :notify_only_default_branch boolean_accessor :notify_only_broken_pipelines, :notify_only_default_branch
validates :recipients, presence: true, if: :valid_recipients? validates :recipients, presence: true, if: :valid_recipients?
def initialize_properties def initialize_properties
self.properties ||= { notify_only_broken_pipelines: true, notify_only_default_branch: false } if properties.nil?
self.properties = {}
self.notify_only_broken_pipelines = true
self.branches_to_be_notified = "default"
elsif !self.notify_only_default_branch.nil?
# In older versions, there was only a boolean property named
# `notify_only_default_branch`. Now we have a string property named
# `branches_to_be_notified`. Instead of doing a background migration, we
# opted to set a value for the new property based on the old one, if
# users hasn't specified one already. When users edit the service and
# selects a value for this new property, it will override everything.
self.branches_to_be_notified ||= notify_only_default_branch? ? "default" : "all"
end
end end
def title def title
...@@ -55,8 +70,9 @@ class PipelinesEmailService < Service ...@@ -55,8 +70,9 @@ class PipelinesEmailService < Service
required: true }, required: true },
{ type: 'checkbox', { type: 'checkbox',
name: 'notify_only_broken_pipelines' }, name: 'notify_only_broken_pipelines' },
{ type: 'checkbox', { type: 'select',
name: 'notify_only_default_branch' } name: 'branches_to_be_notified',
choices: BRANCH_CHOICES }
] ]
end end
...@@ -69,13 +85,7 @@ class PipelinesEmailService < Service ...@@ -69,13 +85,7 @@ class PipelinesEmailService < Service
end end
def should_pipeline_be_notified?(data) def should_pipeline_be_notified?(data)
notify_for_pipeline_branch?(data) && notify_for_pipeline?(data) notify_for_branch?(data) && notify_for_pipeline?(data)
end
def notify_for_pipeline_branch?(data)
return true unless notify_only_default_branch?
data[:object_attributes][:ref] == data[:project][:default_branch]
end end
def notify_for_pipeline?(data) def notify_for_pipeline?(data)
......
---
title: Support chat notifications to be fired for protected branches
merge_request: 32176
author:
type: added
...@@ -436,7 +436,8 @@ Parameters: ...@@ -436,7 +436,8 @@ Parameters:
| --------- | ---- | -------- | ----------- | | --------- | ---- | -------- | ----------- |
| `webhook` | string | true | The Hangouts Chat webhook. For example, `https://chat.googleapis.com/v1/spaces...`. | | `webhook` | string | true | The Hangouts Chat webhook. For example, `https://chat.googleapis.com/v1/spaces...`. |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines | | `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
| `notify_only_default_branch` | boolean | false | Send notifications only for the default branch | | `notify_only_default_branch` | boolean | false | DEPRECATED: This parameter has been replaced with `branches_to_be_notified` |
| `branches_to_be_notified` | string | all | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected" |
| `push_events` | boolean | false | Enable notifications for push events | | `push_events` | boolean | false | Enable notifications for push events |
| `issues_events` | boolean | false | Enable notifications for issue events | | `issues_events` | boolean | false | Enable notifications for issue events |
| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events | | `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events |
...@@ -745,7 +746,8 @@ Parameters: ...@@ -745,7 +746,8 @@ Parameters:
| `recipients` | string | yes | Comma-separated list of recipient email addresses | | `recipients` | string | yes | Comma-separated list of recipient email addresses |
| `add_pusher` | boolean | no | Add pusher to recipients list | | `add_pusher` | boolean | no | Add pusher to recipients list |
| `notify_only_broken_pipelines` | boolean | no | Notify only broken pipelines | | `notify_only_broken_pipelines` | boolean | no | Notify only broken pipelines |
| `notify_only_default_branch` | boolean | no | Send notifications only for the default branch ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/28271)) | | `notify_only_default_branch` | boolean | no | DEPRECATED: This parameter has been replaced with `branches_to_be_notified` ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/28271)) |
| `branches_to_be_notified` | string | all | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected" |
| `pipeline_events` | boolean | false | Enable notifications for pipeline events | | `pipeline_events` | boolean | false | Enable notifications for pipeline events |
### Delete Pipeline-Emails service ### Delete Pipeline-Emails service
...@@ -933,7 +935,8 @@ Parameters: ...@@ -933,7 +935,8 @@ Parameters:
| `username` | string | false | username | | `username` | string | false | username |
| `channel` | string | false | Default channel to use if others are not configured | | `channel` | string | false | Default channel to use if others are not configured |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines | | `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
| `notify_only_default_branch` | boolean | false | Send notifications only for the default branch | | `notify_only_default_branch` | boolean | false | DEPRECATED: This parameter has been replaced with `branches_to_be_notified` |
| `branches_to_be_notified` | string | all | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected" |
| `commit_events` | boolean | false | Enable notifications for commit events | | `commit_events` | boolean | false | Enable notifications for commit events |
| `confidential_issue_channel` | string | false | The name of the channel to receive confidential issues events notifications | | `confidential_issue_channel` | string | false | The name of the channel to receive confidential issues events notifications |
| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events | | `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events |
...@@ -991,7 +994,8 @@ Parameters: ...@@ -991,7 +994,8 @@ Parameters:
| --------- | ---- | -------- | ----------- | | --------- | ---- | -------- | ----------- |
| `webhook` | string | true | The Microsoft Teams webhook. For example, `https://outlook.office.com/webhook/...` | | `webhook` | string | true | The Microsoft Teams webhook. For example, `https://outlook.office.com/webhook/...` |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines | | `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
| `notify_only_default_branch` | boolean | false | Send notifications only for the default branch | | `notify_only_default_branch` | boolean | false | DEPRECATED: This parameter has been replaced with `branches_to_be_notified` |
| `branches_to_be_notified` | string | all | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected" |
| `push_events` | boolean | false | Enable notifications for push events | | `push_events` | boolean | false | Enable notifications for push events |
| `issues_events` | boolean | false | Enable notifications for issue events | | `issues_events` | boolean | false | Enable notifications for issue events |
| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events | | `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events |
...@@ -1040,7 +1044,8 @@ Parameters: ...@@ -1040,7 +1044,8 @@ Parameters:
| `username` | string | false | username | | `username` | string | false | username |
| `channel` | string | false | Default channel to use if others are not configured | | `channel` | string | false | Default channel to use if others are not configured |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines | | `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
| `notify_only_default_branch` | boolean | false | Send notifications only for the default branch | | `notify_only_default_branch` | boolean | false | DEPRECATED: This parameter has been replaced with `branches_to_be_notified` |
| `branches_to_be_notified` | string | all | Branches to send notifications for. Valid options are "all", "default", "protected", and "default_and_protected" |
| `push_events` | boolean | false | Enable notifications for push events | | `push_events` | boolean | false | Enable notifications for push events |
| `issues_events` | boolean | false | Enable notifications for issue events | | `issues_events` | boolean | false | Enable notifications for issue events |
| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events | | `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events |
......
...@@ -27,6 +27,12 @@ module API ...@@ -27,6 +27,12 @@ module API
name: :channel, name: :channel,
type: String, type: String,
desc: 'The default chat channel' desc: 'The default chat channel'
},
{
required: false,
name: :branches_to_be_notified,
type: String,
desc: 'Branches for which notifications are to be sent'
} }
].freeze ].freeze
end end
...@@ -38,12 +44,6 @@ module API ...@@ -38,12 +44,6 @@ module API
name: :notify_only_broken_pipelines, name: :notify_only_broken_pipelines,
type: Boolean, type: Boolean,
desc: 'Send notifications for broken pipelines' desc: 'Send notifications for broken pipelines'
},
{
required: false,
name: :notify_only_default_branch,
type: Boolean,
desc: 'Send notifications only for the default branch'
} }
].freeze ].freeze
end end
...@@ -540,9 +540,9 @@ module API ...@@ -540,9 +540,9 @@ module API
}, },
{ {
required: false, required: false,
name: :notify_only_default_branch, name: :branches_to_be_notified,
type: Boolean, type: String,
desc: 'Send notifications only for the default branch' desc: 'Branches for which notifications are to be sent'
} }
], ],
'pivotaltracker' => [ 'pivotaltracker' => [
......
...@@ -1228,6 +1228,9 @@ msgstr "" ...@@ -1228,6 +1228,9 @@ msgstr ""
msgid "All Members" msgid "All Members"
msgstr "" msgstr ""
msgid "All branches"
msgstr ""
msgid "All changes are committed" msgid "All changes are committed"
msgstr "" msgstr ""
...@@ -4650,6 +4653,12 @@ msgstr "" ...@@ -4650,6 +4653,12 @@ msgstr ""
msgid "Default artifacts expiration" msgid "Default artifacts expiration"
msgstr "" msgstr ""
msgid "Default branch"
msgstr ""
msgid "Default branch and protected branches"
msgstr ""
msgid "Default classification label" msgid "Default classification label"
msgstr "" msgstr ""
...@@ -12343,6 +12352,9 @@ msgstr "" ...@@ -12343,6 +12352,9 @@ msgstr ""
msgid "Protected Tag" msgid "Protected Tag"
msgstr "" msgstr ""
msgid "Protected branches"
msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?" msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "" msgstr ""
......
...@@ -216,7 +216,7 @@ describe 'Admin updates settings' do ...@@ -216,7 +216,7 @@ describe 'Admin updates settings' do
fill_in 'Username', with: 'test_user' fill_in 'Username', with: 'test_user'
fill_in 'service_push_channel', with: '#test_channel' fill_in 'service_push_channel', with: '#test_channel'
page.check('Notify only broken pipelines') page.check('Notify only broken pipelines')
page.check('Notify only default branch') page.select 'All branches', from: 'Branches to be notified'
check_all_events check_all_events
click_on 'Save' click_on 'Save'
......
...@@ -3,5 +3,5 @@ ...@@ -3,5 +3,5 @@
require 'spec_helper' require 'spec_helper'
describe MattermostService do describe MattermostService do
it_behaves_like "slack or mattermost notifications" it_behaves_like "slack or mattermost notifications", "Mattermost"
end end
...@@ -226,9 +226,10 @@ describe MicrosoftTeamsService do ...@@ -226,9 +226,10 @@ describe MicrosoftTeamsService do
) )
end end
shared_examples 'call Microsoft Teams API' do shared_examples 'call Microsoft Teams API' do |branches_to_be_notified: nil|
before do before do
WebMock.stub_request(:post, webhook_url) WebMock.stub_request(:post, webhook_url)
chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
end end
it 'calls Microsoft Teams API for pipeline events' do it 'calls Microsoft Teams API for pipeline events' do
...@@ -245,6 +246,18 @@ describe MicrosoftTeamsService do ...@@ -245,6 +246,18 @@ describe MicrosoftTeamsService do
end end
end end
shared_examples 'does not call Microsoft Teams API' do |branches_to_be_notified: nil|
before do
chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
end
it 'does not call Microsoft Teams API for pipeline events' do
data = Gitlab::DataBuilder::Pipeline.build(pipeline)
result = chat_service.execute(data)
expect(result).to be_falsy
end
end
context 'with failed pipeline' do context 'with failed pipeline' do
let(:status) { 'failed' } let(:status) { 'failed' }
...@@ -272,35 +285,73 @@ describe MicrosoftTeamsService do ...@@ -272,35 +285,73 @@ describe MicrosoftTeamsService do
end end
end end
context 'only notify for the default branch' do context 'with default branch' do
context 'when enabled' do let(:pipeline) do
let(:pipeline) do create(:ci_pipeline, project: project, status: 'failed', sha: project.commit.sha, ref: project.default_branch)
create(:ci_pipeline, project: project, status: 'failed', ref: 'not-the-default-branch') end
end
before do context 'only notify for the default branch' do
chat_service.notify_only_default_branch = true it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "default"
end end
it 'does not call the Microsoft Teams API for pipeline events' do context 'notify for only protected branches' do
data = Gitlab::DataBuilder::Pipeline.build(pipeline) it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "protected"
result = chat_service.execute(data) end
expect(result).to be_falsy context 'notify for only default and protected branches' do
end it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "default_and_protected"
end end
context 'when disabled' do context 'notify for all branches' do
let(:pipeline) do it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "all"
create(:ci_pipeline, :failed, project: project, end
sha: project.commit.sha, ref: 'not-the-default-branch') end
end
before do context 'with protected branch' do
chat_service.notify_only_default_branch = false before do
end create(:protected_branch, project: project, name: 'a-protected-branch')
end
it_behaves_like 'call Microsoft Teams API' let(:pipeline) do
create(:ci_pipeline, project: project, status: 'failed', sha: project.commit.sha, ref: 'a-protected-branch')
end
context 'only notify for the default branch' do
it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "default"
end
context 'notify for only protected branches' do
it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "protected"
end
context 'notify for only default and protected branches' do
it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "default_and_protected"
end
context 'notify for all branches' do
it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "all"
end
end
context 'with neither protected nor default branch' do
let(:pipeline) do
create(:ci_pipeline, project: project, status: 'failed', sha: project.commit.sha, ref: 'a-random-branch')
end
context 'only notify for the default branch' do
it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "default"
end
context 'notify for only protected branches' do
it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "protected"
end
context 'notify for only default and protected branches' do
it_behaves_like 'does not call Microsoft Teams API', branches_to_be_notified: "default_and_protected"
end
context 'notify for all branches' do
it_behaves_like 'call Microsoft Teams API', branches_to_be_notified: "all"
end end
end end
end end
......
...@@ -53,9 +53,10 @@ describe PipelinesEmailService, :mailer do ...@@ -53,9 +53,10 @@ describe PipelinesEmailService, :mailer do
end end
end end
shared_examples 'sending email' do shared_examples 'sending email' do |branches_to_be_notified: nil|
before do before do
subject.recipients = recipients subject.recipients = recipients
subject.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
perform_enqueued_jobs do perform_enqueued_jobs do
run run
...@@ -69,9 +70,10 @@ describe PipelinesEmailService, :mailer do ...@@ -69,9 +70,10 @@ describe PipelinesEmailService, :mailer do
end end
end end
shared_examples 'not sending email' do shared_examples 'not sending email' do |branches_to_be_notified: nil|
before do before do
subject.recipients = recipients subject.recipients = recipients
subject.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
perform_enqueued_jobs do perform_enqueued_jobs do
run run
...@@ -101,27 +103,84 @@ describe PipelinesEmailService, :mailer do ...@@ -101,27 +103,84 @@ describe PipelinesEmailService, :mailer do
it_behaves_like 'sending email' it_behaves_like 'sending email'
end end
context 'when pipeline is failed and on a non-default branch' do context 'when the pipeline failed' do
before do context 'on default branch' do
data[:object_attributes][:ref] = 'not-the-default-branch' before do
pipeline.update(ref: 'not-the-default-branch') data[:object_attributes][:ref] = project.default_branch
pipeline.update(ref: project.default_branch)
end
context 'notifications are enabled only for default branch' do
it_behaves_like 'sending email', branches_to_be_notified: "default"
end
context 'notifications are enabled only for protected branch' do
it_behaves_like 'sending email', branches_to_be_notified: "protected"
end
context 'notifications are enabled only for default and protected branches ' do
it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
end
context 'notifications are enabled only for all branches' do
it_behaves_like 'sending email', branches_to_be_notified: "all"
end
end end
context 'with notify_only_default branch on' do context 'on a protected branch' do
before do before do
subject.notify_only_default_branch = true create(:protected_branch, project: project, name: 'a-protected-branch')
data[:object_attributes][:ref] = 'a-protected-branch'
pipeline.update(ref: 'a-protected-branch')
end end
it_behaves_like 'sending email' context 'notifications are enabled only for default branch' do
it_behaves_like 'sending email', branches_to_be_notified: "default"
end
context 'notifications are enabled only for protected branch' do
it_behaves_like 'sending email', branches_to_be_notified: "protected"
end
context 'notifications are enabled only for default and protected branches ' do
it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
end
context 'notifications are enabled only for all branches' do
it_behaves_like 'sending email', branches_to_be_notified: "all"
end
end end
context 'with notify_only_default_branch off' do context 'on a neither protected nor default branch' do
it_behaves_like 'sending email' before do
data[:object_attributes][:ref] = 'a-random-branch'
pipeline.update(ref: 'a-random-branch')
end
context 'notifications are enabled only for default branch' do
it_behaves_like 'sending email', branches_to_be_notified: "default"
end
context 'notifications are enabled only for protected branch' do
it_behaves_like 'sending email', branches_to_be_notified: "protected"
end
context 'notifications are enabled only for default and protected branches ' do
it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
end
context 'notifications are enabled only for all branches' do
it_behaves_like 'sending email', branches_to_be_notified: "all"
end
end end
end end
end end
describe '#execute' do describe '#execute' do
before do
subject.project = project
end
def run def run
subject.execute(data) subject.execute(data)
end end
...@@ -159,37 +218,75 @@ describe PipelinesEmailService, :mailer do ...@@ -159,37 +218,75 @@ describe PipelinesEmailService, :mailer do
end end
end end
context 'with notify_only_default_branch off' do context 'when the pipeline failed' do
context 'with default branch' do context 'on default branch' do
it_behaves_like 'sending email' before do
data[:object_attributes][:ref] = project.default_branch
pipeline.update(ref: project.default_branch)
end
context 'notifications are enabled only for default branch' do
it_behaves_like 'sending email', branches_to_be_notified: "default"
end
context 'notifications are enabled only for protected branch' do
it_behaves_like 'not sending email', branches_to_be_notified: "protected"
end
context 'notifications are enabled only for default and protected branches ' do
it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
end
context 'notifications are enabled only for all branches' do
it_behaves_like 'sending email', branches_to_be_notified: "all"
end
end end
context 'with non default branch' do context 'on a protected branch' do
before do before do
data[:object_attributes][:ref] = 'not-the-default-branch' create(:protected_branch, project: project, name: 'a-protected-branch')
pipeline.update(ref: 'not-the-default-branch') data[:object_attributes][:ref] = 'a-protected-branch'
pipeline.update(ref: 'a-protected-branch')
end end
it_behaves_like 'sending email' context 'notifications are enabled only for default branch' do
end it_behaves_like 'not sending email', branches_to_be_notified: "default"
end end
context 'with notify_only_default_branch on' do context 'notifications are enabled only for protected branch' do
before do it_behaves_like 'sending email', branches_to_be_notified: "protected"
subject.notify_only_default_branch = true end
end
context 'with default branch' do context 'notifications are enabled only for default and protected branches ' do
it_behaves_like 'sending email' it_behaves_like 'sending email', branches_to_be_notified: "default_and_protected"
end
context 'notifications are enabled only for all branches' do
it_behaves_like 'sending email', branches_to_be_notified: "all"
end
end end
context 'with non default branch' do context 'on a neither protected nor default branch' do
before do before do
data[:object_attributes][:ref] = 'not-the-default-branch' data[:object_attributes][:ref] = 'a-random-branch'
pipeline.update(ref: 'not-the-default-branch') pipeline.update(ref: 'a-random-branch')
end end
it_behaves_like 'not sending email' context 'notifications are enabled only for default branch' do
it_behaves_like 'not sending email', branches_to_be_notified: "default"
end
context 'notifications are enabled only for protected branch' do
it_behaves_like 'not sending email', branches_to_be_notified: "protected"
end
context 'notifications are enabled only for default and protected branches ' do
it_behaves_like 'not sending email', branches_to_be_notified: "default_and_protected"
end
context 'notifications are enabled only for all branches' do
it_behaves_like 'sending email', branches_to_be_notified: "all"
end
end end
end end
end end
......
...@@ -3,5 +3,5 @@ ...@@ -3,5 +3,5 @@
require 'spec_helper' require 'spec_helper'
describe SlackService do describe SlackService do
it_behaves_like "slack or mattermost notifications" it_behaves_like "slack or mattermost notifications", "Slack"
end end
...@@ -49,7 +49,11 @@ shared_examples_for "chat service" do |service_name| ...@@ -49,7 +49,11 @@ shared_examples_for "chat service" do |service_name|
WebMock.stub_request(:post, webhook_url) WebMock.stub_request(:post, webhook_url)
end end
shared_examples "#{service_name} service" do shared_examples "triggered #{service_name} service" do |branches_to_be_notified: nil|
before do
subject.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
end
it "calls #{service_name} API" do it "calls #{service_name} API" do
subject.execute(sample_data) subject.execute(sample_data)
...@@ -57,12 +61,24 @@ shared_examples_for "chat service" do |service_name| ...@@ -57,12 +61,24 @@ shared_examples_for "chat service" do |service_name|
end end
end end
shared_examples "untriggered #{service_name} service" do |branches_to_be_notified: nil|
before do
subject.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
end
it "does not call #{service_name} API" do
result = subject.execute(sample_data)
expect(result).to be_falsy
end
end
context "with push events" do context "with push events" do
let(:sample_data) do let(:sample_data) do
Gitlab::DataBuilder::Push.build_sample(project, user) Gitlab::DataBuilder::Push.build_sample(project, user)
end end
it_behaves_like "#{service_name} service" it_behaves_like "triggered #{service_name} service"
it "specifies the webhook when it is configured" do it "specifies the webhook when it is configured" do
expect(client).to receive(:new).with(client_arguments).and_return(double(:chat_service).as_null_object) expect(client).to receive(:new).with(client_arguments).and_return(double(:chat_service).as_null_object)
...@@ -70,29 +86,73 @@ shared_examples_for "chat service" do |service_name| ...@@ -70,29 +86,73 @@ shared_examples_for "chat service" do |service_name|
subject.execute(sample_data) subject.execute(sample_data)
end end
context "with not default branch" do context "with default branch" do
let(:sample_data) do let(:sample_data) do
Gitlab::DataBuilder::Push.build(project: project, user: user, ref: "not-the-default-branch") Gitlab::DataBuilder::Push.build(project: project, user: user, ref: project.default_branch)
end end
context "when notify_only_default_branch enabled" do context "when only default branch are to be notified" do
before do it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "default"
subject.notify_only_default_branch = true end
end
it "does not call the Discord Webhooks API" do context "when only protected branches are to be notified" do
result = subject.execute(sample_data) it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "protected"
end
expect(result).to be_falsy context "when default and protected branches are to be notified" do
end it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "default_and_protected"
end end
context "when notify_only_default_branch disabled" do context "when all branches are to be notified" do
before do it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "all"
subject.notify_only_default_branch = false end
end end
context "with protected branch" do
before do
create(:protected_branch, project: project, name: "a-protected-branch")
end
let(:sample_data) do
Gitlab::DataBuilder::Push.build(project: project, user: user, ref: "a-protected-branch")
end
context "when only default branch are to be notified" do
it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "default"
end
context "when only protected branches are to be notified" do
it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "protected"
end
it_behaves_like "#{service_name} service" context "when default and protected branches are to be notified" do
it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "default_and_protected"
end
context "when all branches are to be notified" do
it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "all"
end
end
context "with neither default nor protected branch" do
let(:sample_data) do
Gitlab::DataBuilder::Push.build(project: project, user: user, ref: "a-random-branch")
end
context "when only default branch are to be notified" do
it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "default"
end
context "when only protected branches are to be notified" do
it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "protected"
end
context "when default and protected branches are to be notified" do
it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "default_and_protected"
end
context "when all branches are to be notified" do
it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "all"
end end
end end
end end
...@@ -105,7 +165,7 @@ shared_examples_for "chat service" do |service_name| ...@@ -105,7 +165,7 @@ shared_examples_for "chat service" do |service_name|
service.hook_data(issue, "open") service.hook_data(issue, "open")
end end
it_behaves_like "#{service_name} service" it_behaves_like "triggered #{service_name} service"
end end
context "with merge events" do context "with merge events" do
...@@ -128,7 +188,7 @@ shared_examples_for "chat service" do |service_name| ...@@ -128,7 +188,7 @@ shared_examples_for "chat service" do |service_name|
project.add_developer(user) project.add_developer(user)
end end
it_behaves_like "#{service_name} service" it_behaves_like "triggered #{service_name} service"
end end
context "with wiki page events" do context "with wiki page events" do
...@@ -143,7 +203,7 @@ shared_examples_for "chat service" do |service_name| ...@@ -143,7 +203,7 @@ shared_examples_for "chat service" do |service_name|
let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) } let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) }
let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, "create") } let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, "create") }
it_behaves_like "#{service_name} service" it_behaves_like "triggered #{service_name} service"
end end
context "with note events" do context "with note events" do
...@@ -158,7 +218,7 @@ shared_examples_for "chat service" do |service_name| ...@@ -158,7 +218,7 @@ shared_examples_for "chat service" do |service_name|
note: "a comment on a commit") note: "a comment on a commit")
end end
it_behaves_like "#{service_name} service" it_behaves_like "triggered #{service_name} service"
end end
context "with merge request comment" do context "with merge request comment" do
...@@ -166,7 +226,7 @@ shared_examples_for "chat service" do |service_name| ...@@ -166,7 +226,7 @@ shared_examples_for "chat service" do |service_name|
create(:note_on_merge_request, project: project, note: "merge request note") create(:note_on_merge_request, project: project, note: "merge request note")
end end
it_behaves_like "#{service_name} service" it_behaves_like "triggered #{service_name} service"
end end
context "with issue comment" do context "with issue comment" do
...@@ -174,7 +234,7 @@ shared_examples_for "chat service" do |service_name| ...@@ -174,7 +234,7 @@ shared_examples_for "chat service" do |service_name|
create(:note_on_issue, project: project, note: "issue note") create(:note_on_issue, project: project, note: "issue note")
end end
it_behaves_like "#{service_name} service" it_behaves_like "triggered #{service_name} service"
end end
context "with snippet comment" do context "with snippet comment" do
...@@ -182,7 +242,7 @@ shared_examples_for "chat service" do |service_name| ...@@ -182,7 +242,7 @@ shared_examples_for "chat service" do |service_name|
create(:note_on_project_snippet, project: project, note: "snippet note") create(:note_on_project_snippet, project: project, note: "snippet note")
end end
it_behaves_like "#{service_name} service" it_behaves_like "triggered #{service_name} service"
end end
end end
...@@ -197,14 +257,14 @@ shared_examples_for "chat service" do |service_name| ...@@ -197,14 +257,14 @@ shared_examples_for "chat service" do |service_name|
context "with failed pipeline" do context "with failed pipeline" do
let(:status) { "failed" } let(:status) { "failed" }
it_behaves_like "#{service_name} service" it_behaves_like "triggered #{service_name} service"
end end
context "with succeeded pipeline" do context "with succeeded pipeline" do
let(:status) { "success" } let(:status) { "success" }
context "with default notify_only_broken_pipelines" do context "with default notify_only_broken_pipelines" do
it "does not call Discord Webhooks API" do it "does not call #{service_name} API" do
result = subject.execute(sample_data) result = subject.execute(sample_data)
expect(result).to be_falsy expect(result).to be_falsy
...@@ -216,34 +276,77 @@ shared_examples_for "chat service" do |service_name| ...@@ -216,34 +276,77 @@ shared_examples_for "chat service" do |service_name|
subject.notify_only_broken_pipelines = false subject.notify_only_broken_pipelines = false
end end
it_behaves_like "#{service_name} service" it_behaves_like "triggered #{service_name} service"
end end
end end
context "with not default branch" do context "with default branch" do
let(:pipeline) do let(:sample_data) do
create(:ci_pipeline, :failed, project: project, Gitlab::DataBuilder::Push.build(project: project, user: user, ref: project.default_branch)
sha: project.commit.sha, ref: "not-the-default-branch")
end end
context "when notify_only_default_branch enabled" do context "when only default branch are to be notified" do
before do it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "default"
subject.notify_only_default_branch = true end
end
it "does not call the Discord Webhooks API" do context "when only protected branches are to be notified" do
result = subject.execute(sample_data) it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "protected"
end
expect(result).to be_falsy context "when default and protected branches are to be notified" do
end it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "default_and_protected"
end end
context "when notify_only_default_branch disabled" do context "when all branches are to be notified" do
before do it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "all"
subject.notify_only_default_branch = false end
end end
context "with protected branch" do
before do
create(:protected_branch, project: project, name: "a-protected-branch")
end
let(:sample_data) do
Gitlab::DataBuilder::Push.build(project: project, user: user, ref: "a-protected-branch")
end
context "when only default branch are to be notified" do
it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "default"
end
context "when only protected branches are to be notified" do
it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "protected"
end
context "when default and protected branches are to be notified" do
it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "default_and_protected"
end
context "when all branches are to be notified" do
it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "all"
end
end
context "with neither default nor protected branch" do
let(:sample_data) do
Gitlab::DataBuilder::Push.build(project: project, user: user, ref: "a-random-branch")
end
context "when only default branch are to be notified" do
it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "default"
end
context "when only protected branches are to be notified" do
it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "protected"
end
context "when default and protected branches are to be notified" do
it_behaves_like "untriggered #{service_name} service", branches_to_be_notified: "default_and_protected"
end
it_behaves_like "#{service_name} service" context "when all branches are to be notified" do
it_behaves_like "triggered #{service_name} service", branches_to_be_notified: "all"
end end
end end
end end
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Dir[Rails.root.join("app/models/project_services/chat_message/*.rb")].each { |f| require f } Dir[Rails.root.join("app/models/project_services/chat_message/*.rb")].each { |f| require f }
RSpec.shared_examples 'slack or mattermost notifications' do RSpec.shared_examples 'slack or mattermost notifications' do |service_name|
let(:chat_service) { described_class.new } let(:chat_service) { described_class.new }
let(:webhook_url) { 'https://example.gitlab.com/' } let(:webhook_url) { 'https://example.gitlab.com/' }
...@@ -35,6 +35,28 @@ RSpec.shared_examples 'slack or mattermost notifications' do ...@@ -35,6 +35,28 @@ RSpec.shared_examples 'slack or mattermost notifications' do
end end
end end
shared_examples "triggered #{service_name} service" do |event_type: nil, branches_to_be_notified: nil|
before do
chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
end
it "notifies about #{event_type} events" do
chat_service.execute(data)
expect(WebMock).to have_requested(:post, webhook_url)
end
end
shared_examples "untriggered #{service_name} service" do |event_type: nil, branches_to_be_notified: nil|
before do
chat_service.branches_to_be_notified = branches_to_be_notified if branches_to_be_notified
end
it "notifies about #{event_type} events" do
chat_service.execute(data)
expect(WebMock).not_to have_requested(:post, webhook_url)
end
end
describe "#execute" do describe "#execute" do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project, :repository, :wiki_repo) } let(:project) { create(:project, :repository, :wiki_repo) }
...@@ -42,7 +64,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do ...@@ -42,7 +64,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do
let(:channel) { 'slack_channel' } let(:channel) { 'slack_channel' }
let(:issue_service_options) { { title: 'Awesome issue', description: 'please fix' } } let(:issue_service_options) { { title: 'Awesome issue', description: 'please fix' } }
let(:push_sample_data) do let(:data) do
Gitlab::DataBuilder::Push.build_sample(project, user) Gitlab::DataBuilder::Push.build_sample(project, user)
end end
...@@ -84,31 +106,31 @@ RSpec.shared_examples 'slack or mattermost notifications' do ...@@ -84,31 +106,31 @@ RSpec.shared_examples 'slack or mattermost notifications' do
@wiki_page_sample_data = Gitlab::DataBuilder::WikiPage.build(@wiki_page, user, 'create') @wiki_page_sample_data = Gitlab::DataBuilder::WikiPage.build(@wiki_page, user, 'create')
end end
it "calls Slack/Mattermost API for push events" do it "calls #{service_name} API for push events" do
chat_service.execute(push_sample_data) chat_service.execute(data)
expect(WebMock).to have_requested(:post, webhook_url).once expect(WebMock).to have_requested(:post, webhook_url).once
end end
it "calls Slack/Mattermost API for issue events" do it "calls #{service_name} API for issue events" do
chat_service.execute(@issues_sample_data) chat_service.execute(@issues_sample_data)
expect(WebMock).to have_requested(:post, webhook_url).once expect(WebMock).to have_requested(:post, webhook_url).once
end end
it "calls Slack/Mattermost API for merge requests events" do it "calls #{service_name} API for merge requests events" do
chat_service.execute(@merge_sample_data) chat_service.execute(@merge_sample_data)
expect(WebMock).to have_requested(:post, webhook_url).once expect(WebMock).to have_requested(:post, webhook_url).once
end end
it "calls Slack/Mattermost API for wiki page events" do it "calls #{service_name} API for wiki page events" do
chat_service.execute(@wiki_page_sample_data) chat_service.execute(@wiki_page_sample_data)
expect(WebMock).to have_requested(:post, webhook_url).once expect(WebMock).to have_requested(:post, webhook_url).once
end end
it "calls Slack/Mattermost API for deployment events" do it "calls #{service_name} API for deployment events" do
deployment_event_data = { object_kind: 'deployment' } deployment_event_data = { object_kind: 'deployment' }
chat_service.execute(deployment_event_data) chat_service.execute(deployment_event_data)
...@@ -125,7 +147,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do ...@@ -125,7 +147,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do
double(:slack_service).as_null_object double(:slack_service).as_null_object
) )
chat_service.execute(push_sample_data) chat_service.execute(data)
end end
it 'uses the channel as an option when it is configured' do it 'uses the channel as an option when it is configured' do
...@@ -135,7 +157,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do ...@@ -135,7 +157,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do
.and_return( .and_return(
double(:slack_service).as_null_object double(:slack_service).as_null_object
) )
chat_service.execute(push_sample_data) chat_service.execute(data)
end end
context "event channels" do context "event channels" do
...@@ -148,7 +170,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do ...@@ -148,7 +170,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do
double(:slack_service).as_null_object double(:slack_service).as_null_object
) )
chat_service.execute(push_sample_data) chat_service.execute(data)
end end
it "uses the right channel for merge request event" do it "uses the right channel for merge request event" do
...@@ -269,64 +291,132 @@ RSpec.shared_examples 'slack or mattermost notifications' do ...@@ -269,64 +291,132 @@ RSpec.shared_examples 'slack or mattermost notifications' do
WebMock.stub_request(:post, webhook_url) WebMock.stub_request(:post, webhook_url)
end end
context 'only notify for the default branch' do context 'on default branch' do
context 'when enabled' do let(:data) do
before do Gitlab::DataBuilder::Push.build(
chat_service.notify_only_default_branch = true project: project,
user: user,
ref: project.default_branch
)
end
context 'pushing tags' do
let(:data) do
Gitlab::DataBuilder::Push.build(
project: project,
user: user,
ref: "#{Gitlab::Git::TAG_REF_PREFIX}test"
)
end end
it 'does not notify push events if they are not for the default branch' do it_behaves_like "triggered #{service_name} service", event_type: "push"
ref = "#{Gitlab::Git::BRANCH_REF_PREFIX}test" end
push_sample_data = Gitlab::DataBuilder::Push.build(project: project, user: user, ref: ref)
chat_service.execute(push_sample_data) context 'notification enabled only for default branch' do
it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default"
end
expect(WebMock).not_to have_requested(:post, webhook_url) context 'notification enabled only for protected branches' do
end it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected"
end
context 'notification enabled only for default and protected branches' do
it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected"
end
context 'notification enabled for all branches' do
it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all"
end
end
it 'notifies about push events for the default branch' do context 'on a protected branch' do
push_sample_data = Gitlab::DataBuilder::Push.build_sample(project, user) before do
create(:protected_branch, project: project, name: 'a-protected-branch')
end
chat_service.execute(push_sample_data) let(:data) do
Gitlab::DataBuilder::Push.build(
project: project,
user: user,
ref: 'a-protected-branch'
)
end
expect(WebMock).to have_requested(:post, webhook_url).once context 'pushing tags' do
let(:data) do
Gitlab::DataBuilder::Push.build(
project: project,
user: user,
ref: "#{Gitlab::Git::TAG_REF_PREFIX}test"
)
end end
it 'still notifies about pushed tags' do it_behaves_like "triggered #{service_name} service", event_type: "push"
ref = "#{Gitlab::Git::TAG_REF_PREFIX}test" end
push_sample_data = Gitlab::DataBuilder::Push.build(project: project, user: user, ref: ref)
chat_service.execute(push_sample_data) context 'notification enabled only for default branch' do
it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default"
end
expect(WebMock).to have_requested(:post, webhook_url).once context 'notification enabled only for protected branches' do
end it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected"
end end
context 'when disabled' do context 'notification enabled only for default and protected branches' do
before do it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected"
chat_service.notify_only_default_branch = false end
end
it 'notifies about all push events' do context 'notification enabled for all branches' do
ref = "#{Gitlab::Git::BRANCH_REF_PREFIX}test" it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all"
push_sample_data = Gitlab::DataBuilder::Push.build(project: project, user: user, ref: ref) end
end
chat_service.execute(push_sample_data) context 'on a neither protected nor default branch' do
let(:data) do
Gitlab::DataBuilder::Push.build(
project: project,
user: user,
ref: 'a-random-branch'
)
end
expect(WebMock).to have_requested(:post, webhook_url).once context 'pushing tags' do
let(:data) do
Gitlab::DataBuilder::Push.build(
project: project,
user: user,
ref: "#{Gitlab::Git::TAG_REF_PREFIX}test"
)
end end
it_behaves_like "triggered #{service_name} service", event_type: "push"
end
context 'notification enabled only for default branch' do
it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default"
end
context 'notification enabled only for protected branches' do
it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "protected"
end
context 'notification enabled only for default and protected branches' do
it_behaves_like "untriggered #{service_name} service", event_type: "push", branches_to_be_notified: "default_and_protected"
end
context 'notification enabled for all branches' do
it_behaves_like "triggered #{service_name} service", event_type: "push", branches_to_be_notified: "all"
end end
end end
end end
describe "Note events" do describe 'Note events' do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project, :repository, creator: user) } let(:project) { create(:project, :repository, creator: user) }
before do before do
allow(chat_service).to receive_messages( allow(chat_service).to receive_messages(
project: project, project: project,
project_id: project.id,
service_hook: true, service_hook: true,
webhook: webhook_url webhook: webhook_url
) )
...@@ -342,61 +432,56 @@ RSpec.shared_examples 'slack or mattermost notifications' do ...@@ -342,61 +432,56 @@ RSpec.shared_examples 'slack or mattermost notifications' do
note: 'a comment on a commit') note: 'a comment on a commit')
end end
it "calls Slack/Mattermost API for commit comment events" do let(:data) do
data = Gitlab::DataBuilder::Note.build(commit_note, user) Gitlab::DataBuilder::Note.build(commit_note, user)
chat_service.execute(data)
expect(WebMock).to have_requested(:post, webhook_url).once
end end
it_behaves_like "triggered #{service_name} service", event_type: "commit comment"
end end
context 'when merge request comment event executed' do context 'when merge request comment event executed' do
let(:merge_request_note) do let(:merge_request_note) do
create(:note_on_merge_request, project: project, create(:note_on_merge_request, project: project,
note: "merge request note") note: 'a comment on a merge request')
end end
it "calls Slack API for merge request comment events" do let(:data) do
data = Gitlab::DataBuilder::Note.build(merge_request_note, user) Gitlab::DataBuilder::Note.build(merge_request_note, user)
chat_service.execute(data)
expect(WebMock).to have_requested(:post, webhook_url).once
end end
it_behaves_like "triggered #{service_name} service", event_type: "merge request comment"
end end
context 'when issue comment event executed' do context 'when issue comment event executed' do
let(:issue_note) do let(:issue_note) do
create(:note_on_issue, project: project, note: "issue note") create(:note_on_issue, project: project,
note: 'a comment on an issue')
end end
let(:data) { Gitlab::DataBuilder::Note.build(issue_note, user) } let(:data) do
Gitlab::DataBuilder::Note.build(issue_note, user)
it "calls Slack API for issue comment events" do
chat_service.execute(data)
expect(WebMock).to have_requested(:post, webhook_url).once
end end
it_behaves_like "triggered #{service_name} service", event_type: "issue comment"
end end
context 'when snippet comment event executed' do context 'when snippet comment event executed' do
let(:snippet_note) do let(:snippet_note) do
create(:note_on_project_snippet, project: project, create(:note_on_project_snippet, project: project,
note: "snippet note") note: 'a comment on a snippet')
end end
it "calls Slack API for snippet comment events" do let(:data) do
data = Gitlab::DataBuilder::Note.build(snippet_note, user) Gitlab::DataBuilder::Note.build(snippet_note, user)
chat_service.execute(data)
expect(WebMock).to have_requested(:post, webhook_url).once
end end
it_behaves_like "triggered #{service_name} service", event_type: "snippet comment"
end end
end end
describe 'Pipeline events' do describe 'Pipeline events' do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository, creator: user) }
let(:pipeline) do let(:pipeline) do
create(:ci_pipeline, create(:ci_pipeline,
project: project, status: status, project: project, status: status,
...@@ -409,77 +494,108 @@ RSpec.shared_examples 'slack or mattermost notifications' do ...@@ -409,77 +494,108 @@ RSpec.shared_examples 'slack or mattermost notifications' do
service_hook: true, service_hook: true,
webhook: webhook_url webhook: webhook_url
) )
WebMock.stub_request(:post, webhook_url)
end end
shared_examples 'call Slack/Mattermost API' do context 'with succeeded pipeline' do
before do let(:status) { 'success' }
WebMock.stub_request(:post, webhook_url) let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
context 'with default to notify_only_broken_pipelines' do
it_behaves_like "untriggered #{service_name} service", event_type: "pipeline"
end end
it 'calls Slack/Mattermost API for pipeline events' do context 'with setting notify_only_broken_pipelines to false' do
data = Gitlab::DataBuilder::Pipeline.build(pipeline) before do
chat_service.execute(data) chat_service.notify_only_broken_pipelines = false
end
expect(WebMock).to have_requested(:post, webhook_url).once it_behaves_like "triggered #{service_name} service", event_type: "pipeline"
end end
end end
context 'with failed pipeline' do context 'with failed pipeline' do
let(:status) { 'failed' } context 'on default branch' do
let(:pipeline) do
create(:ci_pipeline,
project: project, status: :failed,
sha: project.commit.sha, ref: project.default_branch)
end
it_behaves_like 'call Slack/Mattermost API' let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
end
context 'with succeeded pipeline' do context 'notification enabled only for default branch' do
let(:status) { 'success' } it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default"
end
context 'with default to notify_only_broken_pipelines' do context 'notification enabled only for protected branches' do
it 'does not call Slack/Mattermost API for pipeline events' do it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected"
data = Gitlab::DataBuilder::Pipeline.build(pipeline) end
result = chat_service.execute(data)
expect(result).to be_falsy context 'notification enabled only for default and protected branches' do
it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected"
end
context 'notification enabled for all branches' do
it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all"
end end
end end
context 'with setting notify_only_broken_pipelines to false' do context 'on a protected branch' do
before do before do
chat_service.notify_only_broken_pipelines = false create(:protected_branch, project: project, name: 'a-protected-branch')
end end
it_behaves_like 'call Slack/Mattermost API'
end
end
context 'only notify for the default branch' do
context 'when enabled' do
let(:pipeline) do let(:pipeline) do
create(:ci_pipeline, :failed, project: project, sha: project.commit.sha, ref: 'not-the-default-branch') create(:ci_pipeline,
project: project, status: :failed,
sha: project.commit.sha, ref: 'a-protected-branch')
end end
before do let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
chat_service.notify_only_default_branch = true
WebMock.stub_request(:post, webhook_url) context 'notification enabled only for default branch' do
it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default"
end end
it 'does not call the Slack/Mattermost API for pipeline events' do context 'notification enabled only for protected branches' do
data = Gitlab::DataBuilder::Pipeline.build(pipeline) it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected"
result = chat_service.execute(data) end
expect(result).to be_falsy context 'notification enabled only for default and protected branches' do
it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected"
end
context 'notification enabled for all branches' do
it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all"
end end
end end
context 'when disabled' do context 'on a neither protected nor default branch' do
let(:pipeline) do let(:pipeline) do
create(:ci_pipeline, :failed, project: project, sha: project.commit.sha, ref: 'not-the-default-branch') create(:ci_pipeline,
project: project, status: :failed,
sha: project.commit.sha, ref: 'a-random-branch')
end end
before do let(:data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
chat_service.notify_only_default_branch = false
context 'notification enabled only for default branch' do
it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default"
end
context 'notification enabled only for protected branches' do
it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "protected"
end end
it_behaves_like 'call Slack/Mattermost API' context 'notification enabled only for default and protected branches' do
it_behaves_like "untriggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "default_and_protected"
end
context 'notification enabled for all branches' do
it_behaves_like "triggered #{service_name} service", event_type: "pipeline", branches_to_be_notified: "all"
end
end end
end end
end end
......
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