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
This commit is contained in:
commit
bdb5e67718
39 changed files with 321 additions and 133 deletions
|
@ -95,7 +95,8 @@ class Project < ActiveRecord::Base
|
|||
has_one :asana_service, dependent: :destroy
|
||||
has_one :gemnasium_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 :bamboo_service, dependent: :destroy
|
||||
has_one :teamcity_service, dependent: :destroy
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require 'slack-notifier'
|
||||
|
||||
class SlackService
|
||||
module ChatMessage
|
||||
class BaseMessage
|
||||
def initialize(params)
|
||||
raise NotImplementedError
|
|
@ -1,4 +1,4 @@
|
|||
class SlackService
|
||||
module ChatMessage
|
||||
class BuildMessage < BaseMessage
|
||||
attr_reader :sha
|
||||
attr_reader :ref_type
|
|
@ -1,4 +1,4 @@
|
|||
class SlackService
|
||||
module ChatMessage
|
||||
class IssueMessage < BaseMessage
|
||||
attr_reader :user_name
|
||||
attr_reader :title
|
|
@ -1,4 +1,4 @@
|
|||
class SlackService
|
||||
module ChatMessage
|
||||
class MergeMessage < BaseMessage
|
||||
attr_reader :user_name
|
||||
attr_reader :project_name
|
|
@ -1,4 +1,4 @@
|
|||
class SlackService
|
||||
module ChatMessage
|
||||
class NoteMessage < BaseMessage
|
||||
attr_reader :message
|
||||
attr_reader :user_name
|
|
@ -1,4 +1,4 @@
|
|||
class SlackService
|
||||
module ChatMessage
|
||||
class PipelineMessage < BaseMessage
|
||||
attr_reader :ref_type, :ref, :status, :project_name, :project_url,
|
||||
:user_name, :duration, :pipeline_id
|
|
@ -1,4 +1,4 @@
|
|||
class SlackService
|
||||
module ChatMessage
|
||||
class PushMessage < BaseMessage
|
||||
attr_reader :after
|
||||
attr_reader :before
|
|
@ -1,4 +1,4 @@
|
|||
class SlackService
|
||||
module ChatMessage
|
||||
class WikiPageMessage < BaseMessage
|
||||
attr_reader :user_name
|
||||
attr_reader :title
|
|
@ -1,6 +1,13 @@
|
|||
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
|
||||
boolean_accessor :notify_only_broken_builds, :notify_only_broken_pipelines
|
||||
|
||||
validates :webhook, presence: true, url: true, if: :activated?
|
||||
|
||||
def initialize_properties
|
||||
|
@ -14,35 +21,8 @@ class SlackService < Service
|
|||
end
|
||||
end
|
||||
|
||||
def title
|
||||
'Slack'
|
||||
end
|
||||
|
||||
def description
|
||||
'A team communication tool for the 21st century'
|
||||
end
|
||||
|
||||
def to_param
|
||||
'slack'
|
||||
end
|
||||
|
||||
def help
|
||||
'This service sends notifications to your Slack channel.<br/>
|
||||
To setup this Service you need to create a new <b>"Incoming webhook"</b> in your Slack integration panel,
|
||||
and enter the Webhook URL below.'
|
||||
end
|
||||
|
||||
def fields
|
||||
default_fields =
|
||||
[
|
||||
{ type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' },
|
||||
{ type: 'text', name: 'username', placeholder: 'username' },
|
||||
{ type: 'text', name: 'channel', placeholder: "#general" },
|
||||
{ type: 'checkbox', name: 'notify_only_broken_builds' },
|
||||
{ type: 'checkbox', name: 'notify_only_broken_pipelines' },
|
||||
]
|
||||
|
||||
default_fields + build_event_channels
|
||||
def can_test?
|
||||
valid?
|
||||
end
|
||||
|
||||
def supported_events
|
||||
|
@ -67,21 +47,16 @@ class SlackService < Service
|
|||
|
||||
message = get_message(object_kind, data)
|
||||
|
||||
if message
|
||||
opt = {}
|
||||
return false unless message
|
||||
|
||||
event_channel = get_channel_field(object_kind) || channel
|
||||
opt = {}
|
||||
|
||||
opt[:channel] = event_channel if event_channel
|
||||
opt[:username] = username if username
|
||||
opt[:channel] = get_channel_field(object_kind).presence || channel || default_channel
|
||||
opt[:username] = username if username
|
||||
notifier = Slack::Notifier.new(webhook, opt)
|
||||
notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback)
|
||||
|
||||
notifier = Slack::Notifier.new(webhook, opt)
|
||||
notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback)
|
||||
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def event_channel_names
|
||||
|
@ -96,6 +71,10 @@ class SlackService < Service
|
|||
fields.reject { |field| field[:name].end_with?('channel') }
|
||||
end
|
||||
|
||||
def default_channel
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_message(object_kind, data)
|
||||
|
@ -124,7 +103,7 @@ class SlackService < Service
|
|||
|
||||
def build_event_channels
|
||||
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
|
||||
|
||||
|
@ -166,11 +145,3 @@ class SlackService < Service
|
|||
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"
|
|
@ -1,5 +1,5 @@
|
|||
# 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
|
||||
default_value_for :category, 'chat'
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
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
|
40
app/models/project_services/slack_notification_service.rb
Normal file
40
app/models/project_services/slack_notification_service.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
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
|
|||
pivotaltracker
|
||||
pushover
|
||||
redmine
|
||||
slack
|
||||
mattermost_notification
|
||||
slack_notification
|
||||
teamcity
|
||||
]
|
||||
end
|
||||
|
|
4
changelogs/unreleased/issue_22269.yml
Normal file
4
changelogs/unreleased/issue_22269.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Create mattermost service
|
||||
merge_request:
|
||||
author:
|
|
@ -1,7 +1,11 @@
|
|||
# rubocop:disable all
|
||||
class MoveSlackServiceToWebhook < ActiveRecord::Migration
|
||||
|
||||
DOWNTIME = true
|
||||
DOWNTIME_REASON = 'Move old fields "token" and "subdomain" to one single field "webhook"'
|
||||
|
||||
def change
|
||||
SlackService.all.each do |slack_service|
|
||||
SlackNotificationService.all.each do |slack_service|
|
||||
if ["token", "subdomain"].all? { |property| slack_service.properties.key? property }
|
||||
token = slack_service.properties['token']
|
||||
subdomain = slack_service.properties['subdomain']
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
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 @@
|
|||
#
|
||||
# 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
|
||||
enable_extension "plpgsql"
|
||||
|
|
|
@ -703,9 +703,9 @@ Get Redmine service settings for a project.
|
|||
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
|
||||
|
||||
|
@ -737,6 +737,40 @@ Get Slack service settings for a project.
|
|||
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
|
||||
|
||||
A continuous integration and build server
|
||||
|
|
BIN
doc/project_services/img/mattermost_configuration.png
Normal file
BIN
doc/project_services/img/mattermost_configuration.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
45
doc/project_services/mattermost.md
Normal file
45
doc/project_services/mattermost.md
Normal file
|
@ -0,0 +1,45 @@
|
|||
# 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.
|
|||
| JetBrains TeamCity CI | A continuous integration and build server |
|
||||
| [Kubernetes](kubernetes.md) | A containerized deployment service |
|
||||
| [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) |
|
||||
| Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop |
|
||||
| [Redmine](redmine.md) | Redmine issue tracker |
|
||||
| [Slack](slack.md) | A team communication tool for the 21st century |
|
||||
|
||||
## Services Templates
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Slack Service
|
||||
# Slack Notifications Service
|
||||
|
||||
## On Slack
|
||||
|
||||
|
@ -15,7 +15,7 @@ Slack:
|
|||
|
||||
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:
|
||||
|
||||
- Push
|
||||
|
|
|
@ -473,7 +473,7 @@ module API
|
|||
desc: 'The description of the tracker'
|
||||
}
|
||||
],
|
||||
'slack' => [
|
||||
'slack-notification' => [
|
||||
{
|
||||
required: true,
|
||||
name: :webhook,
|
||||
|
@ -493,6 +493,14 @@ module API
|
|||
desc: 'The channel name'
|
||||
}
|
||||
],
|
||||
'mattermost-notification' => [
|
||||
{
|
||||
required: true,
|
||||
name: :webhook,
|
||||
type: String,
|
||||
desc: 'The Mattermost webhook. e.g. http://mattermost_host/hooks/...'
|
||||
}
|
||||
],
|
||||
'teamcity' => [
|
||||
{
|
||||
required: true,
|
||||
|
|
Binary file not shown.
|
@ -2,8 +2,8 @@ require 'spec_helper'
|
|||
|
||||
feature 'Projects > Slack service > Setup events', feature: true do
|
||||
let(:user) { create(:user) }
|
||||
let(:service) { SlackService.new }
|
||||
let(:project) { create(:project, slack_service: service) }
|
||||
let(:service) { SlackNotificationService.new }
|
||||
let(:project) { create(:project, slack_notification_service: service) }
|
||||
|
||||
background do
|
||||
service.fields
|
||||
|
|
|
@ -136,7 +136,8 @@ project:
|
|||
- assembla_service
|
||||
- asana_service
|
||||
- gemnasium_service
|
||||
- slack_service
|
||||
- slack_notification_service
|
||||
- mattermost_notification_service
|
||||
- buildkite_service
|
||||
- bamboo_service
|
||||
- teamcity_service
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe SlackService::BuildMessage do
|
||||
subject { SlackService::BuildMessage.new(args) }
|
||||
describe ChatMessage::BuildMessage do
|
||||
subject { described_class.new(args) }
|
||||
|
||||
let(:args) do
|
||||
{
|
|
@ -1,7 +1,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe SlackService::IssueMessage, models: true do
|
||||
subject { SlackService::IssueMessage.new(args) }
|
||||
describe ChatMessage::IssueMessage, models: true do
|
||||
subject { described_class.new(args) }
|
||||
|
||||
let(:args) do
|
||||
{
|
|
@ -1,7 +1,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe SlackService::MergeMessage, models: true do
|
||||
subject { SlackService::MergeMessage.new(args) }
|
||||
describe ChatMessage::MergeMessage, models: true do
|
||||
subject { described_class.new(args) }
|
||||
|
||||
let(:args) do
|
||||
{
|
|
@ -1,6 +1,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe SlackService::NoteMessage, models: true do
|
||||
describe ChatMessage::NoteMessage, models: true do
|
||||
let(:color) { '#345' }
|
||||
|
||||
before do
|
||||
|
@ -36,7 +36,7 @@ describe SlackService::NoteMessage, models: true do
|
|||
end
|
||||
|
||||
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 " \
|
||||
"commit 5f163b2b> in <somewhere.com|project_name>: " \
|
||||
"*Added a commit message*")
|
||||
|
@ -62,7 +62,7 @@ describe SlackService::NoteMessage, models: true do
|
|||
end
|
||||
|
||||
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 " \
|
||||
"merge request !30> in <somewhere.com|project_name>: " \
|
||||
"*merge request title*")
|
||||
|
@ -88,7 +88,7 @@ describe SlackService::NoteMessage, models: true do
|
|||
end
|
||||
|
||||
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(
|
||||
"test.user <url|commented on " \
|
||||
"issue #20> in <somewhere.com|project_name>: " \
|
||||
|
@ -114,7 +114,7 @@ describe SlackService::NoteMessage, models: true do
|
|||
end
|
||||
|
||||
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 " \
|
||||
"snippet #5> in <somewhere.com|project_name>: " \
|
||||
"*snippet title*")
|
|
@ -1,7 +1,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe SlackService::PipelineMessage do
|
||||
subject { SlackService::PipelineMessage.new(args) }
|
||||
describe ChatMessage::PipelineMessage do
|
||||
subject { described_class.new(args) }
|
||||
let(:user) { { name: 'hacker' } }
|
||||
|
||||
let(:args) do
|
|
@ -1,7 +1,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe SlackService::PushMessage, models: true do
|
||||
subject { SlackService::PushMessage.new(args) }
|
||||
describe ChatMessage::PushMessage, models: true do
|
||||
subject { described_class.new(args) }
|
||||
|
||||
let(:args) do
|
||||
{
|
|
@ -1,6 +1,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe SlackService::WikiPageMessage, models: true do
|
||||
describe ChatMessage::WikiPageMessage, models: true do
|
||||
subject { described_class.new(args) }
|
||||
|
||||
let(:args) do
|
|
@ -0,0 +1,11 @@
|
|||
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
|
|
@ -0,0 +1,5 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe MattermostNotificationService, models: true do
|
||||
it_behaves_like "slack or mattermost"
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe SlackNotificationService, models: true do
|
||||
it_behaves_like "slack or mattermost"
|
||||
end
|
|
@ -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(:chat_services) }
|
||||
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(:asana_service).dependent(:destroy) }
|
||||
it { is_expected.to have_many(:boards).dependent(:destroy) }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
require 'spec_helper'
|
||||
Dir[Rails.root.join("app/models/project_services/chat_message/*.rb")].each { |f| require f }
|
||||
|
||||
describe SlackService, models: true do
|
||||
let(:slack) { SlackService.new }
|
||||
RSpec.shared_examples 'slack or mattermost' do
|
||||
let(:chat_service) { described_class.new }
|
||||
let(:webhook_url) { 'https://example.gitlab.com/' }
|
||||
|
||||
describe "Associations" do
|
||||
|
@ -24,7 +24,7 @@ describe SlackService, models: true do
|
|||
end
|
||||
end
|
||||
|
||||
describe "Execute" do
|
||||
describe "#execute" do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project) }
|
||||
let(:username) { 'slack_username' }
|
||||
|
@ -35,7 +35,7 @@ describe SlackService, models: true do
|
|||
end
|
||||
|
||||
before do
|
||||
allow(slack).to receive_messages(
|
||||
allow(chat_service).to receive_messages(
|
||||
project: project,
|
||||
project_id: project.id,
|
||||
service_hook: true,
|
||||
|
@ -77,54 +77,55 @@ describe SlackService, models: true do
|
|||
@wiki_page_sample_data = wiki_page_service.hook_data(@wiki_page, 'create')
|
||||
end
|
||||
|
||||
it "calls Slack API for push events" do
|
||||
slack.execute(push_sample_data)
|
||||
it "calls Slack/Mattermost API for push events" do
|
||||
chat_service.execute(push_sample_data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, webhook_url).once
|
||||
end
|
||||
|
||||
it "calls Slack API for issue events" do
|
||||
slack.execute(@issues_sample_data)
|
||||
it "calls Slack/Mattermost API for issue events" do
|
||||
chat_service.execute(@issues_sample_data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, webhook_url).once
|
||||
end
|
||||
|
||||
it "calls Slack API for merge requests events" do
|
||||
slack.execute(@merge_sample_data)
|
||||
it "calls Slack/Mattermost API for merge requests events" do
|
||||
chat_service.execute(@merge_sample_data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, webhook_url).once
|
||||
end
|
||||
|
||||
it "calls Slack API for wiki page events" do
|
||||
slack.execute(@wiki_page_sample_data)
|
||||
it "calls Slack/Mattermost API for wiki page events" do
|
||||
chat_service.execute(@wiki_page_sample_data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, webhook_url).once
|
||||
end
|
||||
|
||||
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).
|
||||
with(webhook_url, username: username).
|
||||
with(webhook_url, username: username, channel: chat_service.default_channel).
|
||||
and_return(
|
||||
double(:slack_service).as_null_object
|
||||
)
|
||||
|
||||
slack.execute(push_sample_data)
|
||||
chat_service.execute(push_sample_data)
|
||||
end
|
||||
|
||||
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).
|
||||
with(webhook_url, channel: channel).
|
||||
and_return(
|
||||
double(:slack_service).as_null_object
|
||||
)
|
||||
slack.execute(push_sample_data)
|
||||
chat_service.execute(push_sample_data)
|
||||
end
|
||||
|
||||
context "event channels" 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).
|
||||
with(webhook_url, channel: "random").
|
||||
|
@ -132,11 +133,11 @@ describe SlackService, models: true do
|
|||
double(:slack_service).as_null_object
|
||||
)
|
||||
|
||||
slack.execute(push_sample_data)
|
||||
chat_service.execute(push_sample_data)
|
||||
end
|
||||
|
||||
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).
|
||||
with(webhook_url, channel: "random").
|
||||
|
@ -144,11 +145,11 @@ describe SlackService, models: true do
|
|||
double(:slack_service).as_null_object
|
||||
)
|
||||
|
||||
slack.execute(@merge_sample_data)
|
||||
chat_service.execute(@merge_sample_data)
|
||||
end
|
||||
|
||||
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).
|
||||
with(webhook_url, channel: "random").
|
||||
|
@ -156,11 +157,11 @@ describe SlackService, models: true do
|
|||
double(:slack_service).as_null_object
|
||||
)
|
||||
|
||||
slack.execute(@issues_sample_data)
|
||||
chat_service.execute(@issues_sample_data)
|
||||
end
|
||||
|
||||
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).
|
||||
with(webhook_url, channel: "random").
|
||||
|
@ -168,7 +169,7 @@ describe SlackService, models: true do
|
|||
double(:slack_service).as_null_object
|
||||
)
|
||||
|
||||
slack.execute(@wiki_page_sample_data)
|
||||
chat_service.execute(@wiki_page_sample_data)
|
||||
end
|
||||
|
||||
context "note event" do
|
||||
|
@ -177,7 +178,7 @@ describe SlackService, models: true do
|
|||
end
|
||||
|
||||
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)
|
||||
|
||||
|
@ -187,7 +188,7 @@ describe SlackService, models: true do
|
|||
double(:slack_service).as_null_object
|
||||
)
|
||||
|
||||
slack.execute(note_data)
|
||||
chat_service.execute(note_data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -198,7 +199,7 @@ describe SlackService, models: true do
|
|||
let(:project) { create(:project, creator_id: user.id) }
|
||||
|
||||
before do
|
||||
allow(slack).to receive_messages(
|
||||
allow(chat_service).to receive_messages(
|
||||
project: project,
|
||||
project_id: project.id,
|
||||
service_hook: true,
|
||||
|
@ -216,9 +217,9 @@ describe SlackService, models: true do
|
|||
note: 'a comment on a commit')
|
||||
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)
|
||||
slack.execute(data)
|
||||
chat_service.execute(data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, webhook_url).once
|
||||
end
|
||||
|
@ -232,7 +233,7 @@ describe SlackService, models: true do
|
|||
|
||||
it "calls Slack API for merge request comment events" do
|
||||
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
|
||||
end
|
||||
|
@ -245,7 +246,7 @@ describe SlackService, models: true do
|
|||
|
||||
it "calls Slack API for issue comment events" do
|
||||
data = Gitlab::DataBuilder::Note.build(issue_note, user)
|
||||
slack.execute(data)
|
||||
chat_service.execute(data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, webhook_url).once
|
||||
end
|
||||
|
@ -259,7 +260,7 @@ describe SlackService, models: true do
|
|||
|
||||
it "calls Slack API for snippet comment events" do
|
||||
data = Gitlab::DataBuilder::Note.build(snippet_note, user)
|
||||
slack.execute(data)
|
||||
chat_service.execute(data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, webhook_url).once
|
||||
end
|
||||
|
@ -277,21 +278,21 @@ describe SlackService, models: true do
|
|||
end
|
||||
|
||||
before do
|
||||
allow(slack).to receive_messages(
|
||||
allow(chat_service).to receive_messages(
|
||||
project: project,
|
||||
service_hook: true,
|
||||
webhook: webhook_url
|
||||
)
|
||||
end
|
||||
|
||||
shared_examples 'call Slack API' do
|
||||
shared_examples 'call Slack/Mattermost API' do
|
||||
before do
|
||||
WebMock.stub_request(:post, webhook_url)
|
||||
end
|
||||
|
||||
it 'calls Slack API for pipeline events' do
|
||||
it 'calls Slack/Mattermost API for pipeline events' do
|
||||
data = Gitlab::DataBuilder::Pipeline.build(pipeline)
|
||||
slack.execute(data)
|
||||
chat_service.execute(data)
|
||||
|
||||
expect(WebMock).to have_requested(:post, webhook_url).once
|
||||
end
|
||||
|
@ -300,16 +301,16 @@ describe SlackService, models: true do
|
|||
context 'with failed pipeline' do
|
||||
let(:status) { 'failed' }
|
||||
|
||||
it_behaves_like 'call Slack API'
|
||||
it_behaves_like 'call Slack/Mattermost API'
|
||||
end
|
||||
|
||||
context 'with succeeded pipeline' do
|
||||
let(:status) { 'success' }
|
||||
|
||||
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)
|
||||
result = slack.execute(data)
|
||||
result = chat_service.execute(data)
|
||||
|
||||
expect(result).to be_falsy
|
||||
end
|
||||
|
@ -317,10 +318,10 @@ describe SlackService, models: true do
|
|||
|
||||
context 'with setting notify_only_broken_pipelines to false' do
|
||||
before do
|
||||
slack.notify_only_broken_pipelines = false
|
||||
chat_service.notify_only_broken_pipelines = false
|
||||
end
|
||||
|
||||
it_behaves_like 'call Slack API'
|
||||
it_behaves_like 'call Slack/Mattermost API'
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue