Commit bdb5e677 authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch 'issue_22269' into 'master'

Mattermost Notifications Service

## What does this MR do?
closes #22269 

## Screenshots 

![mattermost](/uploads/de71c121f544a91305b6dfa6dc4c5738/mattermost.png)  
![slack](/uploads/081d75d49239319d94332abda214fb98/slack.png)

## Does this MR meet the acceptance criteria?

- [x] [Changelog entry](https://docs.gitlab.com/ce/development/changelog.html) added
- [x] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md)
- [x] API support added
- Tests
  - [x] Added for this feature/bug
  - [x] All builds are passing
- [x] Conform by the [merge request performance guides](http://docs.gitlab.com/ce/development/merge_request_performance_guidelines.html)
- [x] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides)
- [x] Branch has no merge conflicts with `master` (if it does - rebase it please)
- [x] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)


See merge request !7764
parents ea59a84f 18b65cb8
...@@ -95,7 +95,8 @@ class Project < ActiveRecord::Base ...@@ -95,7 +95,8 @@ class Project < ActiveRecord::Base
has_one :asana_service, dependent: :destroy has_one :asana_service, dependent: :destroy
has_one :gemnasium_service, dependent: :destroy has_one :gemnasium_service, dependent: :destroy
has_one :mattermost_slash_commands_service, dependent: :destroy has_one :mattermost_slash_commands_service, dependent: :destroy
has_one :slack_service, dependent: :destroy has_one :mattermost_notification_service, dependent: :destroy
has_one :slack_notification_service, dependent: :destroy
has_one :buildkite_service, dependent: :destroy has_one :buildkite_service, dependent: :destroy
has_one :bamboo_service, dependent: :destroy has_one :bamboo_service, dependent: :destroy
has_one :teamcity_service, dependent: :destroy has_one :teamcity_service, dependent: :destroy
......
require 'slack-notifier' require 'slack-notifier'
class SlackService module ChatMessage
class BaseMessage class BaseMessage
def initialize(params) def initialize(params)
raise NotImplementedError raise NotImplementedError
......
class SlackService module ChatMessage
class BuildMessage < BaseMessage class BuildMessage < BaseMessage
attr_reader :sha attr_reader :sha
attr_reader :ref_type attr_reader :ref_type
......
class SlackService module ChatMessage
class IssueMessage < BaseMessage class IssueMessage < BaseMessage
attr_reader :user_name attr_reader :user_name
attr_reader :title attr_reader :title
......
class SlackService module ChatMessage
class MergeMessage < BaseMessage class MergeMessage < BaseMessage
attr_reader :user_name attr_reader :user_name
attr_reader :project_name attr_reader :project_name
......
class SlackService module ChatMessage
class NoteMessage < BaseMessage class NoteMessage < BaseMessage
attr_reader :message attr_reader :message
attr_reader :user_name attr_reader :user_name
......
class SlackService module ChatMessage
class PipelineMessage < BaseMessage class PipelineMessage < BaseMessage
attr_reader :ref_type, :ref, :status, :project_name, :project_url, attr_reader :ref_type, :ref, :status, :project_name, :project_url,
:user_name, :duration, :pipeline_id :user_name, :duration, :pipeline_id
......
class SlackService module ChatMessage
class PushMessage < BaseMessage class PushMessage < BaseMessage
attr_reader :after attr_reader :after
attr_reader :before attr_reader :before
......
class SlackService module ChatMessage
class WikiPageMessage < BaseMessage class WikiPageMessage < BaseMessage
attr_reader :user_name attr_reader :user_name
attr_reader :title attr_reader :title
......
class SlackService < Service # Base class for Chat notifications services
# This class is not meant to be used directly, but only to inherit from.
class ChatNotificationService < Service
include ChatMessage
default_value_for :category, 'chat'
prop_accessor :webhook, :username, :channel prop_accessor :webhook, :username, :channel
boolean_accessor :notify_only_broken_builds, :notify_only_broken_pipelines boolean_accessor :notify_only_broken_builds, :notify_only_broken_pipelines
validates :webhook, presence: true, url: true, if: :activated? validates :webhook, presence: true, url: true, if: :activated?
def initialize_properties def initialize_properties
...@@ -14,35 +21,8 @@ class SlackService < Service ...@@ -14,35 +21,8 @@ class SlackService < Service
end end
end end
def title def can_test?
'Slack' valid?
end
def description
'A team communication tool for the 21st century'
end
def to_param
'slack'
end
def help
'This service sends notifications to your Slack channel.<br/>
To setup this Service you need to create a new <b>"Incoming webhook"</b> in your Slack integration panel,
and enter the Webhook URL below.'
end
def fields
default_fields =
[
{ type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' },
{ type: 'text', name: 'username', placeholder: 'username' },
{ type: 'text', name: 'channel', placeholder: "#general" },
{ type: 'checkbox', name: 'notify_only_broken_builds' },
{ type: 'checkbox', name: 'notify_only_broken_pipelines' },
]
default_fields + build_event_channels
end end
def supported_events def supported_events
...@@ -67,21 +47,16 @@ class SlackService < Service ...@@ -67,21 +47,16 @@ class SlackService < Service
message = get_message(object_kind, data) message = get_message(object_kind, data)
if message return false unless message
opt = {}
event_channel = get_channel_field(object_kind) || channel opt = {}
opt[:channel] = event_channel if event_channel opt[:channel] = get_channel_field(object_kind).presence || channel || default_channel
opt[:username] = username if username opt[:username] = username if username
notifier = Slack::Notifier.new(webhook, opt) notifier = Slack::Notifier.new(webhook, opt)
notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback) notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback)
true true
else
false
end
end end
def event_channel_names def event_channel_names
...@@ -96,6 +71,10 @@ class SlackService < Service ...@@ -96,6 +71,10 @@ class SlackService < Service
fields.reject { |field| field[:name].end_with?('channel') } fields.reject { |field| field[:name].end_with?('channel') }
end end
def default_channel
raise NotImplementedError
end
private private
def get_message(object_kind, data) def get_message(object_kind, data)
...@@ -124,7 +103,7 @@ class SlackService < Service ...@@ -124,7 +103,7 @@ class SlackService < Service
def build_event_channels def build_event_channels
supported_events.reduce([]) do |channels, event| supported_events.reduce([]) do |channels, event|
channels << { type: 'text', name: event_channel_name(event), placeholder: "#general" } channels << { type: 'text', name: event_channel_name(event), placeholder: default_channel }
end end
end end
...@@ -166,11 +145,3 @@ class SlackService < Service ...@@ -166,11 +145,3 @@ class SlackService < Service
end end
end end
end end
require "slack_service/issue_message"
require "slack_service/push_message"
require "slack_service/merge_message"
require "slack_service/note_message"
require "slack_service/build_message"
require "slack_service/pipeline_message"
require "slack_service/wiki_page_message"
# Base class for Chat services # Base class for Chat services
# This class is not meant to be used directly, but only to inherrit from. # This class is not meant to be used directly, but only to inherit from.
class ChatService < Service class ChatService < Service
default_value_for :category, 'chat' default_value_for :category, 'chat'
......
class MattermostNotificationService < ChatNotificationService
def title
'Mattermost notifications'
end
def description
'Receive event notifications in Mattermost'
end
def to_param
'mattermost_notification'
end
def help
'This service sends notifications about projects events to Mattermost channels.<br />
To set up this service:
<ol>
<li><a href="https://docs.mattermost.com/developer/webhooks-incoming.html#enabling-incoming-webhooks">Enable incoming webhooks</a> in your Mattermost installation. </li>
<li><a href="https://docs.mattermost.com/developer/webhooks-incoming.html#creating-integrations-using-incoming-webhooks">Add an incoming webhook</a> in your Mattermost team. The default channel can be overridden for each event. </li>
<li>Paste the webhook <strong>URL</strong> into the field bellow. </li>
<li>Select events below to enable notifications. The channel and username are optional. </li>
</ol>'
end
def fields
default_fields + build_event_channels
end
def default_fields
[
{ type: 'text', name: 'webhook', placeholder: 'http://mattermost_host/hooks/...' },
{ type: 'text', name: 'username', placeholder: 'username' },
{ type: 'checkbox', name: 'notify_only_broken_builds' },
{ type: 'checkbox', name: 'notify_only_broken_pipelines' },
]
end
def default_channel
"#town-square"
end
end
class SlackNotificationService < ChatNotificationService
def title
'Slack notifications'
end
def description
'Receive event notifications in Slack'
end
def to_param
'slack_notification'
end
def help
'This service sends notifications about projects events to Slack channels.<br />
To setup this service:
<ol>
<li><a href="https://slack.com/apps/A0F7XDUAZ-incoming-webhooks">Add an incoming webhook</a> in your Slack team. The default channel can be overridden for each event. </li>
<li>Paste the <strong>Webhook URL</strong> into the field below. </li>
<li>Select events below to enable notifications. The channel and username are optional. </li>
</ol>'
end
def fields
default_fields + build_event_channels
end
def default_fields
[
{ type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' },
{ type: 'text', name: 'username', placeholder: 'username' },
{ type: 'checkbox', name: 'notify_only_broken_builds' },
{ type: 'checkbox', name: 'notify_only_broken_pipelines' },
]
end
def default_channel
"#general"
end
end
...@@ -220,7 +220,8 @@ class Service < ActiveRecord::Base ...@@ -220,7 +220,8 @@ class Service < ActiveRecord::Base
pivotaltracker pivotaltracker
pushover pushover
redmine redmine
slack mattermost_notification
slack_notification
teamcity teamcity
] ]
end end
......
---
title: Create mattermost service
merge_request:
author:
# rubocop:disable all # rubocop:disable all
class MoveSlackServiceToWebhook < ActiveRecord::Migration class MoveSlackServiceToWebhook < ActiveRecord::Migration
DOWNTIME = true
DOWNTIME_REASON = 'Move old fields "token" and "subdomain" to one single field "webhook"'
def change def change
SlackService.all.each do |slack_service| SlackNotificationService.all.each do |slack_service|
if ["token", "subdomain"].all? { |property| slack_service.properties.key? property } if ["token", "subdomain"].all? { |property| slack_service.properties.key? property }
token = slack_service.properties['token'] token = slack_service.properties['token']
subdomain = slack_service.properties['subdomain'] subdomain = slack_service.properties['subdomain']
......
class ChangeSlackServiceToSlackNotificationService < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
DOWNTIME_REASON = 'Rename SlackService to SlackNotificationService'
def up
execute("UPDATE services SET type = 'SlackNotificationService' WHERE type = 'SlackService'")
end
def down
execute("UPDATE services SET type = 'SlackService' WHERE type = 'SlackNotificationService'")
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20161212142807) do ActiveRecord::Schema.define(version: 20161213172958) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
......
...@@ -703,9 +703,9 @@ Get Redmine service settings for a project. ...@@ -703,9 +703,9 @@ Get Redmine service settings for a project.
GET /projects/:id/services/redmine GET /projects/:id/services/redmine
``` ```
## Slack ## Slack notifications
A team communication tool for the 21st century Receive event notifications in Slack
### Create/Edit Slack service ### Create/Edit Slack service
...@@ -737,6 +737,40 @@ Get Slack service settings for a project. ...@@ -737,6 +737,40 @@ Get Slack service settings for a project.
GET /projects/:id/services/slack GET /projects/:id/services/slack
``` ```
## Mattermost notifications
Receive event notifications in Mattermost
### Create/Edit Mattermost notifications service
Set Mattermost service for a project.
```
PUT /projects/:id/services/mattermost
```
Parameters:
- `webhook` (**required**) - https://mattermost.example/hooks/1298aff...
- `username` (optional) - username
- `channel` (optional) - #channel
### Delete Mattermost notifications service
Delete Mattermost Notifications service for a project.
```
DELETE /projects/:id/services/mattermost
```
### Get Mattermost notifications service settings
Get Mattermost notifications service settings for a project.
```
GET /projects/:id/services/mattermost
```
## JetBrains TeamCity CI ## JetBrains TeamCity CI
A continuous integration and build server A continuous integration and build server
......
# Mattermost Notifications Service
## On Mattermost
To enable Mattermost integration you must create an incoming webhook integration:
1. Sign in to your Mattermost instance
1. Visit incoming webhooks, that will be something like: https://mattermost.example/your_team_name/integrations/incoming_webhooks/add
1. Choose a display name, description and channel, those can be overridden on GitLab
1. Save it, copy the **Webhook URL**, we'll need this later for GitLab.
There might be some cases that Incoming Webhooks are blocked by admin, ask your mattermost admin to enable
it on https://mattermost.example/admin_console/integrations/custom.
Display name override is not enabled by default, you need to ask your admin to enable it on that same section.
## On GitLab
After you set up Mattermost, it's time to set up GitLab.
Go to your project's **Settings > Services > Mattermost Notifications** and you will see a
checkbox with the following events that can be triggered:
- Push
- Issue
- Merge request
- Note
- Tag push
- Build
- Wiki page
Bellow each of these event checkboxes, you will have an input field to insert
which Mattermost channel you want to send that event message, with `#town-square`
being the default. The hash sign is optional.
At the end, fill in your Mattermost details:
| Field | Description |
| ----- | ----------- |
| **Webhook** | The incoming webhooks which you have to setup on Mattermost, it will be something like: http://mattermost.example/hooks/5xo... |
| **Username** | Optional username which can be on messages sent to Mattermost. Fill this in if you want to change the username of the bot. |
| **Notify only broken builds** | If you choose to enable the **Build** event and you want to be only notified about failed builds. |
![Mattermost configuration](img/mattermost_configuration.png)
...@@ -44,10 +44,11 @@ further configuration instructions and details. Contributions are welcome. ...@@ -44,10 +44,11 @@ further configuration instructions and details. Contributions are welcome.
| JetBrains TeamCity CI | A continuous integration and build server | | JetBrains TeamCity CI | A continuous integration and build server |
| [Kubernetes](kubernetes.md) | A containerized deployment service | | [Kubernetes](kubernetes.md) | A containerized deployment service |
| [Mattermost slash commands](mattermost_slash_commands.md) | Mattermost chat and ChatOps slash commands | | [Mattermost slash commands](mattermost_slash_commands.md) | Mattermost chat and ChatOps slash commands |
| [Mattermost Notifications](mattermost.md) | Receive event notifications in Mattermost |
| [Slack Notifications](slack.md) | Receive event notifications in Slack |
| PivotalTracker | Project Management Software (Source Commits Endpoint) | | PivotalTracker | Project Management Software (Source Commits Endpoint) |
| Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop | | Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop |
| [Redmine](redmine.md) | Redmine issue tracker | | [Redmine](redmine.md) | Redmine issue tracker |
| [Slack](slack.md) | A team communication tool for the 21st century |
## Services Templates ## Services Templates
......
# Slack Service # Slack Notifications Service
## On Slack ## On Slack
...@@ -15,7 +15,7 @@ Slack: ...@@ -15,7 +15,7 @@ Slack:
After you set up Slack, it's time to set up GitLab. After you set up Slack, it's time to set up GitLab.
Go to your project's **Settings > Services > Slack** and you will see a Go to your project's **Settings > Services > Slack Notifications** and you will see a
checkbox with the following events that can be triggered: checkbox with the following events that can be triggered:
- Push - Push
......
...@@ -473,7 +473,7 @@ module API ...@@ -473,7 +473,7 @@ module API
desc: 'The description of the tracker' desc: 'The description of the tracker'
} }
], ],
'slack' => [ 'slack-notification' => [
{ {
required: true, required: true,
name: :webhook, name: :webhook,
...@@ -493,6 +493,14 @@ module API ...@@ -493,6 +493,14 @@ module API
desc: 'The channel name' desc: 'The channel name'
} }
], ],
'mattermost-notification' => [
{
required: true,
name: :webhook,
type: String,
desc: 'The Mattermost webhook. e.g. http://mattermost_host/hooks/...'
}
],
'teamcity' => [ 'teamcity' => [
{ {
required: true, required: true,
......
...@@ -2,8 +2,8 @@ require 'spec_helper' ...@@ -2,8 +2,8 @@ require 'spec_helper'
feature 'Projects > Slack service > Setup events', feature: true do feature 'Projects > Slack service > Setup events', feature: true do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:service) { SlackService.new } let(:service) { SlackNotificationService.new }
let(:project) { create(:project, slack_service: service) } let(:project) { create(:project, slack_notification_service: service) }
background do background do
service.fields service.fields
......
...@@ -136,7 +136,8 @@ project: ...@@ -136,7 +136,8 @@ project:
- assembla_service - assembla_service
- asana_service - asana_service
- gemnasium_service - gemnasium_service
- slack_service - slack_notification_service
- mattermost_notification_service
- buildkite_service - buildkite_service
- bamboo_service - bamboo_service
- teamcity_service - teamcity_service
......
require 'spec_helper' require 'spec_helper'
describe SlackService::BuildMessage do describe ChatMessage::BuildMessage do
subject { SlackService::BuildMessage.new(args) } subject { described_class.new(args) }
let(:args) do let(:args) do
{ {
......
require 'spec_helper' require 'spec_helper'
describe SlackService::IssueMessage, models: true do describe ChatMessage::IssueMessage, models: true do
subject { SlackService::IssueMessage.new(args) } subject { described_class.new(args) }
let(:args) do let(:args) do
{ {
......
require 'spec_helper' require 'spec_helper'
describe SlackService::MergeMessage, models: true do describe ChatMessage::MergeMessage, models: true do
subject { SlackService::MergeMessage.new(args) } subject { described_class.new(args) }
let(:args) do let(:args) do
{ {
......
require 'spec_helper' require 'spec_helper'
describe SlackService::NoteMessage, models: true do describe ChatMessage::NoteMessage, models: true do
let(:color) { '#345' } let(:color) { '#345' }
before do before do
...@@ -36,7 +36,7 @@ describe SlackService::NoteMessage, models: true do ...@@ -36,7 +36,7 @@ describe SlackService::NoteMessage, models: true do
end end
it 'returns a message regarding notes on commits' do it 'returns a message regarding notes on commits' do
message = SlackService::NoteMessage.new(@args) message = described_class.new(@args)
expect(message.pretext).to eq("test.user <url|commented on " \ expect(message.pretext).to eq("test.user <url|commented on " \
"commit 5f163b2b> in <somewhere.com|project_name>: " \ "commit 5f163b2b> in <somewhere.com|project_name>: " \
"*Added a commit message*") "*Added a commit message*")
...@@ -62,7 +62,7 @@ describe SlackService::NoteMessage, models: true do ...@@ -62,7 +62,7 @@ describe SlackService::NoteMessage, models: true do
end end
it 'returns a message regarding notes on a merge request' do it 'returns a message regarding notes on a merge request' do
message = SlackService::NoteMessage.new(@args) message = described_class.new(@args)
expect(message.pretext).to eq("test.user <url|commented on " \ expect(message.pretext).to eq("test.user <url|commented on " \
"merge request !30> in <somewhere.com|project_name>: " \ "merge request !30> in <somewhere.com|project_name>: " \
"*merge request title*") "*merge request title*")
...@@ -88,7 +88,7 @@ describe SlackService::NoteMessage, models: true do ...@@ -88,7 +88,7 @@ describe SlackService::NoteMessage, models: true do
end end
it 'returns a message regarding notes on an issue' do it 'returns a message regarding notes on an issue' do
message = SlackService::NoteMessage.new(@args) message = described_class.new(@args)
expect(message.pretext).to eq( expect(message.pretext).to eq(
"test.user <url|commented on " \ "test.user <url|commented on " \
"issue #20> in <somewhere.com|project_name>: " \ "issue #20> in <somewhere.com|project_name>: " \
...@@ -114,7 +114,7 @@ describe SlackService::NoteMessage, models: true do ...@@ -114,7 +114,7 @@ describe SlackService::NoteMessage, models: true do
end end
it 'returns a message regarding notes on a project snippet' do it 'returns a message regarding notes on a project snippet' do
message = SlackService::NoteMessage.new(@args) message = described_class.new(@args)
expect(message.pretext).to eq("test.user <url|commented on " \ expect(message.pretext).to eq("test.user <url|commented on " \
"snippet #5> in <somewhere.com|project_name>: " \ "snippet #5> in <somewhere.com|project_name>: " \
"*snippet title*") "*snippet title*")
......
require 'spec_helper' require 'spec_helper'
describe SlackService::PipelineMessage do describe ChatMessage::PipelineMessage do
subject { SlackService::PipelineMessage.new(args) } subject { described_class.new(args) }
let(:user) { { name: 'hacker' } } let(:user) { { name: 'hacker' } }
let(:args) do let(:args) do
......
require 'spec_helper' require 'spec_helper'
describe SlackService::PushMessage, models: true do describe ChatMessage::PushMessage, models: true do
subject { SlackService::PushMessage.new(args) } subject { described_class.new(args) }
let(:args) do let(:args) do
{ {
......
require 'spec_helper' require 'spec_helper'
describe SlackService::WikiPageMessage, models: true do describe ChatMessage::WikiPageMessage, models: true do
subject { described_class.new(args) } subject { described_class.new(args) }
let(:args) do let(:args) do
......
require 'spec_helper'
describe ChatNotificationService, models: true do
describe "Associations" do
before do
allow(subject).to receive(:activated?).and_return(true)
end
it { is_expected.to validate_presence_of :webhook }
end
end
require 'spec_helper'
describe MattermostNotificationService, models: true do
it_behaves_like "slack or mattermost"
end
require 'spec_helper'
describe SlackNotificationService, models: true do
it_behaves_like "slack or mattermost"
end
...@@ -22,7 +22,8 @@ describe Project, models: true do ...@@ -22,7 +22,8 @@ describe Project, models: true do
it { is_expected.to have_many(:protected_branches).dependent(:destroy) } it { is_expected.to have_many(:protected_branches).dependent(:destroy) }
it { is_expected.to have_many(:chat_services) } it { is_expected.to have_many(:chat_services) }
it { is_expected.to have_one(:forked_project_link).dependent(:destroy) } it { is_expected.to have_one(:forked_project_link).dependent(:destroy) }
it { is_expected.to have_one(:slack_service).dependent(:destroy) } it { is_expected.to have_one(:slack_notification_service).dependent(:destroy) }
it { is_expected.to have_one(:mattermost_notification_service).dependent(:destroy) }
it { is_expected.to have_one(:pushover_service).dependent(:destroy) } it { is_expected.to have_one(:pushover_service).dependent(:destroy) }
it { is_expected.to have_one(:asana_service).dependent(:destroy) } it { is_expected.to have_one(:asana_service).dependent(:destroy) }
it { is_expected.to have_many(:boards).dependent(:destroy) } it { is_expected.to have_many(:boards).dependent(:destroy) }
......
require 'spec_helper' Dir[Rails.root.join("app/models/project_services/chat_message/*.rb")].each { |f| require f }
describe SlackService, models: true do RSpec.shared_examples 'slack or mattermost' do
let(:slack) { SlackService.new } let(:chat_service) { described_class.new }
let(:webhook_url) { 'https://example.gitlab.com/' } let(:webhook_url) { 'https://example.gitlab.com/' }
describe "Associations" do describe "Associations" do
...@@ -24,7 +24,7 @@ describe SlackService, models: true do ...@@ -24,7 +24,7 @@ describe SlackService, models: true do
end end
end end
describe "Execute" do describe "#execute" do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project) } let(:project) { create(:project) }
let(:username) { 'slack_username' } let(:username) { 'slack_username' }
...@@ -35,7 +35,7 @@ describe SlackService, models: true do ...@@ -35,7 +35,7 @@ describe SlackService, models: true do
end end
before do before do
allow(slack).to receive_messages( allow(chat_service).to receive_messages(
project: project, project: project,
project_id: project.id, project_id: project.id,
service_hook: true, service_hook: true,
...@@ -77,54 +77,55 @@ describe SlackService, models: true do ...@@ -77,54 +77,55 @@ describe SlackService, models: true do
@wiki_page_sample_data = wiki_page_service.hook_data(@wiki_page, 'create') @wiki_page_sample_data = wiki_page_service.hook_data(@wiki_page, 'create')
end end
it "calls Slack API for push events" do it "calls Slack/Mattermost API for push events" do
slack.execute(push_sample_data) chat_service.execute(push_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 API for issue events" do it "calls Slack/Mattermost API for issue events" do
slack.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 API for merge requests events" do it "calls Slack/Mattermost API for merge requests events" do
slack.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 API for wiki page events" do it "calls Slack/Mattermost API for wiki page events" do
slack.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 'uses the username as an option for slack when configured' do it 'uses the username as an option for slack when configured' do
allow(slack).to receive(:username).and_return(username) allow(chat_service).to receive(:username).and_return(username)
expect(Slack::Notifier).to receive(:new). expect(Slack::Notifier).to receive(:new).
with(webhook_url, username: username). with(webhook_url, username: username, channel: chat_service.default_channel).
and_return( and_return(
double(:slack_service).as_null_object double(:slack_service).as_null_object
) )
slack.execute(push_sample_data) chat_service.execute(push_sample_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
allow(slack).to receive(:channel).and_return(channel) allow(chat_service).to receive(:channel).and_return(channel)
expect(Slack::Notifier).to receive(:new). expect(Slack::Notifier).to receive(:new).
with(webhook_url, channel: channel). with(webhook_url, channel: channel).
and_return( and_return(
double(:slack_service).as_null_object double(:slack_service).as_null_object
) )
slack.execute(push_sample_data) chat_service.execute(push_sample_data)
end end
context "event channels" do context "event channels" do
it "uses the right channel for push event" do it "uses the right channel for push event" do
slack.update_attributes(push_channel: "random") chat_service.update_attributes(push_channel: "random")
expect(Slack::Notifier).to receive(:new). expect(Slack::Notifier).to receive(:new).
with(webhook_url, channel: "random"). with(webhook_url, channel: "random").
...@@ -132,11 +133,11 @@ describe SlackService, models: true do ...@@ -132,11 +133,11 @@ describe SlackService, models: true do
double(:slack_service).as_null_object double(:slack_service).as_null_object
) )
slack.execute(push_sample_data) chat_service.execute(push_sample_data)
end end
it "uses the right channel for merge request event" do it "uses the right channel for merge request event" do
slack.update_attributes(merge_request_channel: "random") chat_service.update_attributes(merge_request_channel: "random")
expect(Slack::Notifier).to receive(:new). expect(Slack::Notifier).to receive(:new).
with(webhook_url, channel: "random"). with(webhook_url, channel: "random").
...@@ -144,11 +145,11 @@ describe SlackService, models: true do ...@@ -144,11 +145,11 @@ describe SlackService, models: true do
double(:slack_service).as_null_object double(:slack_service).as_null_object
) )
slack.execute(@merge_sample_data) chat_service.execute(@merge_sample_data)
end end
it "uses the right channel for issue event" do it "uses the right channel for issue event" do
slack.update_attributes(issue_channel: "random") chat_service.update_attributes(issue_channel: "random")
expect(Slack::Notifier).to receive(:new). expect(Slack::Notifier).to receive(:new).
with(webhook_url, channel: "random"). with(webhook_url, channel: "random").
...@@ -156,11 +157,11 @@ describe SlackService, models: true do ...@@ -156,11 +157,11 @@ describe SlackService, models: true do
double(:slack_service).as_null_object double(:slack_service).as_null_object
) )
slack.execute(@issues_sample_data) chat_service.execute(@issues_sample_data)
end end
it "uses the right channel for wiki event" do it "uses the right channel for wiki event" do
slack.update_attributes(wiki_page_channel: "random") chat_service.update_attributes(wiki_page_channel: "random")
expect(Slack::Notifier).to receive(:new). expect(Slack::Notifier).to receive(:new).
with(webhook_url, channel: "random"). with(webhook_url, channel: "random").
...@@ -168,7 +169,7 @@ describe SlackService, models: true do ...@@ -168,7 +169,7 @@ describe SlackService, models: true do
double(:slack_service).as_null_object double(:slack_service).as_null_object
) )
slack.execute(@wiki_page_sample_data) chat_service.execute(@wiki_page_sample_data)
end end
context "note event" do context "note event" do
...@@ -177,7 +178,7 @@ describe SlackService, models: true do ...@@ -177,7 +178,7 @@ describe SlackService, models: true do
end end
it "uses the right channel" do it "uses the right channel" do
slack.update_attributes(note_channel: "random") chat_service.update_attributes(note_channel: "random")
note_data = Gitlab::DataBuilder::Note.build(issue_note, user) note_data = Gitlab::DataBuilder::Note.build(issue_note, user)
...@@ -187,7 +188,7 @@ describe SlackService, models: true do ...@@ -187,7 +188,7 @@ describe SlackService, models: true do
double(:slack_service).as_null_object double(:slack_service).as_null_object
) )
slack.execute(note_data) chat_service.execute(note_data)
end end
end end
end end
...@@ -198,7 +199,7 @@ describe SlackService, models: true do ...@@ -198,7 +199,7 @@ describe SlackService, models: true do
let(:project) { create(:project, creator_id: user.id) } let(:project) { create(:project, creator_id: user.id) }
before do before do
allow(slack).to receive_messages( allow(chat_service).to receive_messages(
project: project, project: project,
project_id: project.id, project_id: project.id,
service_hook: true, service_hook: true,
...@@ -216,9 +217,9 @@ describe SlackService, models: true do ...@@ -216,9 +217,9 @@ describe SlackService, models: true do
note: 'a comment on a commit') note: 'a comment on a commit')
end end
it "calls Slack API for commit comment events" do it "calls Slack/Mattermost API for commit comment events" do
data = Gitlab::DataBuilder::Note.build(commit_note, user) data = Gitlab::DataBuilder::Note.build(commit_note, user)
slack.execute(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
...@@ -232,7 +233,7 @@ describe SlackService, models: true do ...@@ -232,7 +233,7 @@ describe SlackService, models: true do
it "calls Slack API for merge request comment events" do it "calls Slack API for merge request comment events" do
data = Gitlab::DataBuilder::Note.build(merge_request_note, user) data = Gitlab::DataBuilder::Note.build(merge_request_note, user)
slack.execute(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
...@@ -245,7 +246,7 @@ describe SlackService, models: true do ...@@ -245,7 +246,7 @@ describe SlackService, models: true do
it "calls Slack API for issue comment events" do it "calls Slack API for issue comment events" do
data = Gitlab::DataBuilder::Note.build(issue_note, user) data = Gitlab::DataBuilder::Note.build(issue_note, user)
slack.execute(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
...@@ -259,7 +260,7 @@ describe SlackService, models: true do ...@@ -259,7 +260,7 @@ describe SlackService, models: true do
it "calls Slack API for snippet comment events" do it "calls Slack API for snippet comment events" do
data = Gitlab::DataBuilder::Note.build(snippet_note, user) data = Gitlab::DataBuilder::Note.build(snippet_note, user)
slack.execute(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
...@@ -277,21 +278,21 @@ describe SlackService, models: true do ...@@ -277,21 +278,21 @@ describe SlackService, models: true do
end end
before do before do
allow(slack).to receive_messages( allow(chat_service).to receive_messages(
project: project, project: project,
service_hook: true, service_hook: true,
webhook: webhook_url webhook: webhook_url
) )
end end
shared_examples 'call Slack API' do shared_examples 'call Slack/Mattermost API' do
before do before do
WebMock.stub_request(:post, webhook_url) WebMock.stub_request(:post, webhook_url)
end end
it 'calls Slack API for pipeline events' do it 'calls Slack/Mattermost API for pipeline events' do
data = Gitlab::DataBuilder::Pipeline.build(pipeline) data = Gitlab::DataBuilder::Pipeline.build(pipeline)
slack.execute(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
...@@ -300,16 +301,16 @@ describe SlackService, models: true do ...@@ -300,16 +301,16 @@ describe SlackService, models: true do
context 'with failed pipeline' do context 'with failed pipeline' do
let(:status) { 'failed' } let(:status) { 'failed' }
it_behaves_like 'call Slack API' it_behaves_like 'call Slack/Mattermost API'
end end
context 'with succeeded pipeline' do context 'with succeeded pipeline' do
let(:status) { 'success' } let(:status) { 'success' }
context 'with default to notify_only_broken_pipelines' do context 'with default to notify_only_broken_pipelines' do
it 'does not call Slack API for pipeline events' do it 'does not call Slack/Mattermost API for pipeline events' do
data = Gitlab::DataBuilder::Pipeline.build(pipeline) data = Gitlab::DataBuilder::Pipeline.build(pipeline)
result = slack.execute(data) result = chat_service.execute(data)
expect(result).to be_falsy expect(result).to be_falsy
end end
...@@ -317,10 +318,10 @@ describe SlackService, models: true do ...@@ -317,10 +318,10 @@ describe SlackService, models: true do
context 'with setting notify_only_broken_pipelines to false' do context 'with setting notify_only_broken_pipelines to false' do
before do before do
slack.notify_only_broken_pipelines = false chat_service.notify_only_broken_pipelines = false
end end
it_behaves_like 'call Slack API' it_behaves_like 'call Slack/Mattermost API'
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