From 846d84602f850ffe7f4ec8b41b2d16f593c1d029 Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Tue, 30 Oct 2018 22:23:20 +1100 Subject: Add Discord integration --- Gemfile | 3 ++ Gemfile.lock | 8 ++++ Gemfile.rails5.lock | 8 ++++ app/models/project.rb | 1 + app/models/project_services/discord_service.rb | 63 ++++++++++++++++++++++++++ app/models/service.rb | 1 + lib/api/services.rb | 9 ++++ spec/lib/gitlab/import_export/all_models.yml | 1 + spec/models/project_spec.rb | 1 + 9 files changed, 95 insertions(+) create mode 100644 app/models/project_services/discord_service.rb diff --git a/Gemfile b/Gemfile index 6674edc1d0c..1182fb7eded 100644 --- a/Gemfile +++ b/Gemfile @@ -204,6 +204,9 @@ gem 'redis-rails', '~> 5.0.2' gem 'redis', '~> 3.2' gem 'connection_pool', '~> 2.0' +# Discord integration +gem 'discordrb-webhooks', '~> 3.3', github: 'blackst0ne/discordrb', require: false + # HipChat integration gem 'hipchat', '~> 1.5.0' diff --git a/Gemfile.lock b/Gemfile.lock index e755b0e0a8d..0cc549b0b30 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,10 @@ +GIT + remote: git://github.com/blackst0ne/discordrb.git + revision: 2de6ec4dda1e2ea2966f1ced063698d7c5fc5225 + specs: + discordrb-webhooks (3.3.0) + rest-client (~> 2.0) + GEM remote: https://rubygems.org/ specs: @@ -972,6 +979,7 @@ DEPENDENCIES devise (~> 4.4) devise-two-factor (~> 3.0.0) diffy (~> 3.1.0) + discordrb-webhooks (~> 3.3)! doorkeeper (~> 4.3) doorkeeper-openid_connect (~> 1.5) ed25519 (~> 1.2) diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock index 6ae7444f18f..22b46333aec 100644 --- a/Gemfile.rails5.lock +++ b/Gemfile.rails5.lock @@ -1,3 +1,10 @@ +GIT + remote: git://github.com/blackst0ne/discordrb.git + revision: 2de6ec4dda1e2ea2966f1ced063698d7c5fc5225 + specs: + discordrb-webhooks (3.3.0) + rest-client (~> 2.0) + GEM remote: https://rubygems.org/ specs: @@ -981,6 +988,7 @@ DEPENDENCIES devise (~> 4.4) devise-two-factor (~> 3.0.0) diffy (~> 3.1.0) + discordrb-webhooks (~> 3.3)! doorkeeper (~> 4.3) doorkeeper-openid_connect (~> 1.5) ed25519 (~> 1.2) diff --git a/app/models/project.rb b/app/models/project.rb index 382fb4f463a..8a6b7abfa6e 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -135,6 +135,7 @@ class Project < ActiveRecord::Base # Project services has_one :campfire_service + has_one :discord_service has_one :drone_ci_service has_one :emails_on_push_service has_one :pipelines_email_service diff --git a/app/models/project_services/discord_service.rb b/app/models/project_services/discord_service.rb new file mode 100644 index 00000000000..ffd82afc131 --- /dev/null +++ b/app/models/project_services/discord_service.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +require "discordrb/webhooks" + +class DiscordService < ChatNotificationService + def title + "Discord Notifications" + end + + def description + "Receive event notifications in Discord" + end + + def self.to_param + "discord" + end + + def help + "This service sends notifications about projects events to Discord channels.
+ To set up this service: +
    +
  1. Setup a custom Incoming Webhook.
  2. +
  3. Paste the Webhook URL into the field below.
  4. +
  5. Select events below to enable notifications.
  6. +
" + end + + def webhook_placeholder + "https://discordapp.com/api/webhooks/..." + end + + def event_field(event) + end + + def default_channel_placeholder + end + + def default_fields + [ + { type: "text", name: "webhook", placeholder: "e.g. #{webhook_placeholder}" }, + { type: "checkbox", name: "notify_only_broken_pipelines" }, + { type: "checkbox", name: "notify_only_default_branch" } + ] + end + + private + + def notify(message, opts) + client = Discordrb::Webhooks::Client.new(url: webhook) + client.execute do |builder| + builder.content = message.pretext + # builder.add_embed do |embed| + # embed.title = 'Embed title' + # embed.description = 'Embed description' + # embed.timestamp = Time.now + # end + end + end + + def custom_data(data) + super(data).merge(markdown: true) + end +end diff --git a/app/models/service.rb b/app/models/service.rb index 4dbda7acab6..5b8bf6e7cf0 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -253,6 +253,7 @@ class Service < ActiveRecord::Base bugzilla campfire custom_issue_tracker + discord drone_ci emails_on_push external_wiki diff --git a/lib/api/services.rb b/lib/api/services.rb index 0ae05ce08f1..1cb3b8a7277 100644 --- a/lib/api/services.rb +++ b/lib/api/services.rb @@ -298,6 +298,14 @@ module API desc: 'Title' } ], + 'discord' => [ + { + required: true, + name: :webhook, + type: String, + desc: 'Discord webhook. e.g. https://discordapp.com/api/webhooks/…' + } + ], 'drone-ci' => [ { required: true, @@ -677,6 +685,7 @@ module API BuildkiteService, CampfireService, CustomIssueTrackerService, + DiscordService, DroneCiService, EmailsOnPushService, ExternalWikiService, diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index a63f34b5536..1f1d23e39eb 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -198,6 +198,7 @@ project: - last_event - services - campfire_service +- discord_service - drone_ci_service - emails_on_push_service - pipelines_email_service diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 62a38c66d99..77e747fcdc9 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -32,6 +32,7 @@ describe Project do it { is_expected.to have_one(:asana_service) } it { is_expected.to have_many(:boards) } it { is_expected.to have_one(:campfire_service) } + it { is_expected.to have_one(:discord_service) } it { is_expected.to have_one(:drone_ci_service) } it { is_expected.to have_one(:emails_on_push_service) } it { is_expected.to have_one(:pipelines_email_service) } -- cgit v1.2.1 From 1ec470fd3893aa50d1db6a9e77164a379e60d63a Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Mon, 5 Nov 2018 10:28:35 +1100 Subject: Add changelog entry --- changelogs/unreleased/blackst0ne-add-discord-service.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelogs/unreleased/blackst0ne-add-discord-service.yml diff --git a/changelogs/unreleased/blackst0ne-add-discord-service.yml b/changelogs/unreleased/blackst0ne-add-discord-service.yml new file mode 100644 index 00000000000..85dedf6d81f --- /dev/null +++ b/changelogs/unreleased/blackst0ne-add-discord-service.yml @@ -0,0 +1,5 @@ +--- +title: Add Discord integration +merge_request: 22684 +author: "@blackst0ne" +type: added -- cgit v1.2.1 From 736b6f1d12e26292a3d2c40bad8334753823ab1e Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Mon, 5 Nov 2018 11:24:26 +1100 Subject: Update discord notification service --- app/models/project_services/discord_service.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/app/models/project_services/discord_service.rb b/app/models/project_services/discord_service.rb index ffd82afc131..3718af3a6e6 100644 --- a/app/models/project_services/discord_service.rb +++ b/app/models/project_services/discord_service.rb @@ -19,7 +19,7 @@ class DiscordService < ChatNotificationService "This service sends notifications about projects events to Discord channels.
To set up this service:
    -
  1. Setup a custom Incoming Webhook.
  2. +
  3. Setup a custom Incoming Webhook.
  4. Paste the Webhook URL into the field below.
  5. Select events below to enable notifications.
" @@ -30,9 +30,11 @@ class DiscordService < ChatNotificationService end def event_field(event) + # No-op. end def default_channel_placeholder + # No-op. end def default_fields @@ -47,13 +49,9 @@ class DiscordService < ChatNotificationService def notify(message, opts) client = Discordrb::Webhooks::Client.new(url: webhook) + client.execute do |builder| builder.content = message.pretext - # builder.add_embed do |embed| - # embed.title = 'Embed title' - # embed.description = 'Embed description' - # embed.timestamp = Time.now - # end end end -- cgit v1.2.1 From 6a4236da9bea129132df2b855c1a916488514818 Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Mon, 5 Nov 2018 12:10:27 +1100 Subject: Add spec for DiscordService --- .../project_services/discord_service_spec.rb | 242 +++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 spec/models/project_services/discord_service_spec.rb diff --git a/spec/models/project_services/discord_service_spec.rb b/spec/models/project_services/discord_service_spec.rb new file mode 100644 index 00000000000..967c6568583 --- /dev/null +++ b/spec/models/project_services/discord_service_spec.rb @@ -0,0 +1,242 @@ +require "spec_helper" + +describe DiscordService do + describe "Associations" do + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } + end + + describe "Validations" do + context "when service is active" do + before do + subject.active = true + end + + it { is_expected.to validate_presence_of(:webhook) } + it_behaves_like "issue tracker service URL attribute", :webhook + end + + context "when service is inactive" do + before do + subject.active = false + end + + it { is_expected.not_to validate_presence_of(:webhook) } + end + end + + describe "#execute" do + let(:user) { create(:user) } + let(:project) { create(:project, :repository) } + let(:webhook_url) { "https://example.gitlab.com/" } + + before do + allow(subject).to receive_messages( + project: project, + project_id: project.id, + service_hook: true, + webhook: webhook_url + ) + + WebMock.stub_request(:post, webhook_url) + end + + shared_examples "Discord service" do + it "calls Discord Webhooks API" do + subject.execute(sample_data) + + expect(WebMock).to have_requested(:post, webhook_url).with { |req| req.body =~ /\A{"content":.+}\Z/ }.once + end + end + + context "with push events" do + let(:sample_data) do + Gitlab::DataBuilder::Push.build_sample(project, user) + end + + it_behaves_like "Discord service" + + it "specifies the webhook when it is configured" do + expect(Discordrb::Webhooks::Client).to receive(:new).with(url: webhook_url).and_return(double(:discord_service).as_null_object) + + subject.execute(sample_data) + end + + context "with not default branch" do + let(:sample_data) do + Gitlab::DataBuilder::Push.build(project, user, nil, nil, "not-the-default-branch") + end + + context "when notify_only_default_branch enabled" do + before do + subject.notify_only_default_branch = true + end + + it "does not call the Discord Webhooks API" do + result = subject.execute(sample_data) + + expect(result).to be_falsy + end + end + + context "when notify_only_default_branch disabled" do + before do + subject.notify_only_default_branch = false + end + + it_behaves_like "Discord service" + end + end + end + + context "with issue events" do + let(:opts) { { title: "Awesome issue", description: "please fix" } } + let(:sample_data) do + service = Issues::CreateService.new(project, user, opts) + issue = service.execute + service.hook_data(issue, "open") + end + + it_behaves_like "Discord service" + end + + context "with merge events" do + let(:opts) do + { + title: "Awesome merge_request", + description: "please fix", + source_branch: "feature", + target_branch: "master" + } + end + + let(:sample_data) do + service = MergeRequests::CreateService.new(project, user, opts) + merge_request = service.execute + service.hook_data(merge_request, "open") + end + + before do + project.add_developer(user) + end + + it_behaves_like "Discord service" + end + + context "with wiki page events" do + let(:opts) do + { + title: "Awesome wiki_page", + content: "Some text describing some thing or another", + format: "md", + message: "user created page: Awesome wiki_page" + } + end + let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) } + let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, "create") } + + it_behaves_like "Discord service" + end + + context "with note events" do + let(:sample_data) { Gitlab::DataBuilder::Note.build(note, user) } + + context "with commit comment" do + let(:note) do + create(:note_on_commit, + author: user, + project: project, + commit_id: project.repository.commit.id, + note: "a comment on a commit") + end + + it_behaves_like "Discord service" + end + + context "with merge request comment" do + let(:note) do + create(:note_on_merge_request, project: project, note: "merge request note") + end + + it_behaves_like "Discord service" + end + + context "with issue comment" do + let(:note) do + create(:note_on_issue, project: project, note: "issue note") + end + + it_behaves_like "Discord service" + end + + context "with snippet comment" do + let(:note) do + create(:note_on_project_snippet, project: project, note: "snippet note") + end + + it_behaves_like "Discord service" + end + end + + context "with pipeline events" do + let(:pipeline) do + create(:ci_pipeline, + project: project, status: status, + sha: project.commit.sha, ref: project.default_branch) + end + let(:sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) } + + context "with failed pipeline" do + let(:status) { "failed" } + + it_behaves_like "Discord service" + end + + context "with succeeded pipeline" do + let(:status) { "success" } + + context "with default notify_only_broken_pipelines" do + it "does not call Discord Webhooks API" do + result = subject.execute(sample_data) + + expect(result).to be_falsy + end + end + + context "when notify_only_broken_pipelines is false" do + before do + subject.notify_only_broken_pipelines = false + end + + it_behaves_like "Discord service" + end + end + + context "with not default branch" do + let(:pipeline) do + create(:ci_pipeline, project: project, status: "failed", ref: "not-the-default-branch") + end + + context "when notify_only_default_branch enabled" do + before do + subject.notify_only_default_branch = true + end + + it "does not call the Discord Webhooks API" do + result = subject.execute(sample_data) + + expect(result).to be_falsy + end + end + + context "when notify_only_default_branch disabled" do + before do + subject.notify_only_default_branch = false + end + + it_behaves_like "Discord service" + end + end + end + end +end -- cgit v1.2.1 From 71e90802ff92e93f12fbe28f376e1b365ca3679b Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Mon, 5 Nov 2018 12:28:08 +1100 Subject: Update documentation --- .../project/integrations/discord_notifications.md | 30 +++++++++++++++++++++ .../img/discord_notifications_configuration.png | Bin 0 -> 110528 bytes doc/user/project/integrations/project_services.md | 1 + 3 files changed, 31 insertions(+) create mode 100644 doc/user/project/integrations/discord_notifications.md create mode 100644 doc/user/project/integrations/img/discord_notifications_configuration.png diff --git a/doc/user/project/integrations/discord_notifications.md b/doc/user/project/integrations/discord_notifications.md new file mode 100644 index 00000000000..99b52d7aa17 --- /dev/null +++ b/doc/user/project/integrations/discord_notifications.md @@ -0,0 +1,30 @@ +# Discord Notifications service + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22684) in GitLab 11.5. + +The Discord Notifications service sends notifications from GitLab to the channel for which the webhook was created. + +## On Discord + +1. Open the channel in which you want to see the notifications. +1. From the channel menu, select **Edit channel**. +1. Click on **Webhooks** menu item. +1. Click on **Create Webhook** and fill in the name of the bot that will post the messages. Optionally define avatar. +1. Copy the **WEBHOOK URL** of your webhook and click **Save**. + +See also [Intro to Webhooks](https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks) article. + +## On GitLab + +When you have the **Webhook URL** for your Discord Notifications channel webhook, you can set up the GitLab service. + +1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings, i.e. **Project > Settings > Integrations**. +1. Select the **Discord Notifications** project service to configure it. +1. Check the **Active** checkbox to turn on the service. +1. Check the checkboxes corresponding to the GitLab events you want to receive. +1. Paste the **Webhook URL** that you copied from the Discord Notifications configuration step. +1. Configure the remaining options and click `Save changes`. + +Your Discord Notifications channel will now start receiving GitLab event notifications as configured. + +![Discord configuration](img/discord_notifications_configuration.png) diff --git a/doc/user/project/integrations/img/discord_notifications_configuration.png b/doc/user/project/integrations/img/discord_notifications_configuration.png new file mode 100644 index 00000000000..e1a023fd19b Binary files /dev/null and b/doc/user/project/integrations/img/discord_notifications_configuration.png differ diff --git a/doc/user/project/integrations/project_services.md b/doc/user/project/integrations/project_services.md index efb0381d7aa..be45ce46dfd 100644 --- a/doc/user/project/integrations/project_services.md +++ b/doc/user/project/integrations/project_services.md @@ -30,6 +30,7 @@ Click on the service links to see further configuration instructions and details | [Bugzilla](bugzilla.md) | Bugzilla issue tracker | | Campfire | Simple web-based real-time group chat | | Custom Issue Tracker | Custom issue tracker | +| [Discord Notifications](discord_notifications.md) | Receive event notifications in Discord | | Drone CI | Continuous Integration platform built on Docker, written in Go | | [Emails on push](emails_on_push.md) | Email the commits and diff of each push to a list of recipients | | External Wiki | Replaces the link to the internal wiki with a link to an external wiki | -- cgit v1.2.1 From 80d3fddc8840effa3b766c4d9f37c84e17c5c0ef Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Mon, 5 Nov 2018 13:19:40 +1100 Subject: Fix frozen strings --- spec/models/project_services/discord_service_spec.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/models/project_services/discord_service_spec.rb b/spec/models/project_services/discord_service_spec.rb index 967c6568583..695fa96d9c1 100644 --- a/spec/models/project_services/discord_service_spec.rb +++ b/spec/models/project_services/discord_service_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe DiscordService do -- cgit v1.2.1 From 0ba3d1411f976afd62fcd6735b62c427e9b24a86 Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Mon, 5 Nov 2018 13:55:56 +1100 Subject: Update Gemfile --- Gemfile | 2 +- Gemfile.lock | 11 +++-------- Gemfile.rails5.lock | 11 +++-------- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/Gemfile b/Gemfile index 1182fb7eded..54b204f1b07 100644 --- a/Gemfile +++ b/Gemfile @@ -205,7 +205,7 @@ gem 'redis', '~> 3.2' gem 'connection_pool', '~> 2.0' # Discord integration -gem 'discordrb-webhooks', '~> 3.3', github: 'blackst0ne/discordrb', require: false +gem 'discordrb-webhooks-blackst0ne', '~> 3.3', require: false # HipChat integration gem 'hipchat', '~> 1.5.0' diff --git a/Gemfile.lock b/Gemfile.lock index 0cc549b0b30..5c950c76b5b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,10 +1,3 @@ -GIT - remote: git://github.com/blackst0ne/discordrb.git - revision: 2de6ec4dda1e2ea2966f1ced063698d7c5fc5225 - specs: - discordrb-webhooks (3.3.0) - rest-client (~> 2.0) - GEM remote: https://rubygems.org/ specs: @@ -174,6 +167,8 @@ GEM rotp (~> 2.0) diff-lcs (1.3) diffy (3.1.0) + discordrb-webhooks-blackst0ne (3.3.0) + rest-client (~> 2.0) docile (1.1.5) domain_name (0.5.20180417) unf (>= 0.0.5, < 1.0.0) @@ -979,7 +974,7 @@ DEPENDENCIES devise (~> 4.4) devise-two-factor (~> 3.0.0) diffy (~> 3.1.0) - discordrb-webhooks (~> 3.3)! + discordrb-webhooks-blackst0ne (~> 3.3) doorkeeper (~> 4.3) doorkeeper-openid_connect (~> 1.5) ed25519 (~> 1.2) diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock index 22b46333aec..d3853b391f3 100644 --- a/Gemfile.rails5.lock +++ b/Gemfile.rails5.lock @@ -1,10 +1,3 @@ -GIT - remote: git://github.com/blackst0ne/discordrb.git - revision: 2de6ec4dda1e2ea2966f1ced063698d7c5fc5225 - specs: - discordrb-webhooks (3.3.0) - rest-client (~> 2.0) - GEM remote: https://rubygems.org/ specs: @@ -177,6 +170,8 @@ GEM rotp (~> 2.0) diff-lcs (1.3) diffy (3.1.0) + discordrb-webhooks-blackst0ne (3.3.0) + rest-client (~> 2.0) docile (1.1.5) domain_name (0.5.20180417) unf (>= 0.0.5, < 1.0.0) @@ -988,7 +983,7 @@ DEPENDENCIES devise (~> 4.4) devise-two-factor (~> 3.0.0) diffy (~> 3.1.0) - discordrb-webhooks (~> 3.3)! + discordrb-webhooks-blackst0ne (~> 3.3) doorkeeper (~> 4.3) doorkeeper-openid_connect (~> 1.5) ed25519 (~> 1.2) -- cgit v1.2.1 From 23d70b8e98982b82877314f4f923eddbe1b0c1eb Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Mon, 5 Nov 2018 14:47:23 +1100 Subject: Update docs after docs review --- .../project/integrations/discord_notifications.md | 27 +++++++++++----------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/doc/user/project/integrations/discord_notifications.md b/doc/user/project/integrations/discord_notifications.md index 99b52d7aa17..ed04a334058 100644 --- a/doc/user/project/integrations/discord_notifications.md +++ b/doc/user/project/integrations/discord_notifications.md @@ -2,29 +2,28 @@ > [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22684) in GitLab 11.5. -The Discord Notifications service sends notifications from GitLab to the channel for which the webhook was created. +The Discord Notifications service sends event notifications from GitLab to the channel for which the webhook was created. -## On Discord +## Create webhook -1. Open the channel in which you want to see the notifications. +1. Open the Discord channel you want to receive GitLab event notifications. 1. From the channel menu, select **Edit channel**. 1. Click on **Webhooks** menu item. -1. Click on **Create Webhook** and fill in the name of the bot that will post the messages. Optionally define avatar. -1. Copy the **WEBHOOK URL** of your webhook and click **Save**. +1. Click the **Create Webhook** button and fill in the name of the bot that will post the messages. Optionally, edit the avatar. +1. Note the URL from the **WEBHOOK URL** field. +1. Click the **Save** button. -See also [Intro to Webhooks](https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks) article. +## Configure created webhook in GitLab -## On GitLab +With the webhook URL created in the Discord channel, you can set up the Discord Notifications service in GitLab. -When you have the **Webhook URL** for your Discord Notifications channel webhook, you can set up the GitLab service. - -1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings, i.e. **Project > Settings > Integrations**. +1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings. That is, **Project > Settings > Integrations**. 1. Select the **Discord Notifications** project service to configure it. 1. Check the **Active** checkbox to turn on the service. -1. Check the checkboxes corresponding to the GitLab events you want to receive. -1. Paste the **Webhook URL** that you copied from the Discord Notifications configuration step. -1. Configure the remaining options and click `Save changes`. +1. Check the checkboxes corresponding to the GitLab events you want to send notifications for to Discord. +1. Paste the webhook URL that you copied from the create Discord webhook step. +1. Configure the remaining options and click the **Save changes** button. -Your Discord Notifications channel will now start receiving GitLab event notifications as configured. +The Discord channel you created the webhook for will now receive notification of the GitLab events as configured. ![Discord configuration](img/discord_notifications_configuration.png) -- cgit v1.2.1 From 2f6b785b44525e3760b2eb20fa18f332fa1c50e1 Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Mon, 5 Nov 2018 15:09:05 +1100 Subject: Updated docs and removed redundant screenshot --- doc/user/project/integrations/discord_notifications.md | 4 ++-- .../img/discord_notifications_configuration.png | Bin 110528 -> 0 bytes 2 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 doc/user/project/integrations/img/discord_notifications_configuration.png diff --git a/doc/user/project/integrations/discord_notifications.md b/doc/user/project/integrations/discord_notifications.md index ed04a334058..4c3e17d69d6 100644 --- a/doc/user/project/integrations/discord_notifications.md +++ b/doc/user/project/integrations/discord_notifications.md @@ -4,6 +4,8 @@ The Discord Notifications service sends event notifications from GitLab to the channel for which the webhook was created. +To send GitLab event notifications to a Discord channel, create a webhook in Discourse and configure it in GitLab. + ## Create webhook 1. Open the Discord channel you want to receive GitLab event notifications. @@ -25,5 +27,3 @@ With the webhook URL created in the Discord channel, you can set up the Discord 1. Configure the remaining options and click the **Save changes** button. The Discord channel you created the webhook for will now receive notification of the GitLab events as configured. - -![Discord configuration](img/discord_notifications_configuration.png) diff --git a/doc/user/project/integrations/img/discord_notifications_configuration.png b/doc/user/project/integrations/img/discord_notifications_configuration.png deleted file mode 100644 index e1a023fd19b..00000000000 Binary files a/doc/user/project/integrations/img/discord_notifications_configuration.png and /dev/null differ -- cgit v1.2.1 From a7439b4a90bf0401b60436991bbc9127ea5a6ae7 Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Mon, 5 Nov 2018 16:16:34 +1100 Subject: Update documentation after documentation review. --- doc/user/project/integrations/discord_notifications.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/user/project/integrations/discord_notifications.md b/doc/user/project/integrations/discord_notifications.md index 4c3e17d69d6..b65b897c442 100644 --- a/doc/user/project/integrations/discord_notifications.md +++ b/doc/user/project/integrations/discord_notifications.md @@ -22,8 +22,8 @@ With the webhook URL created in the Discord channel, you can set up the Discord 1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings. That is, **Project > Settings > Integrations**. 1. Select the **Discord Notifications** project service to configure it. 1. Check the **Active** checkbox to turn on the service. -1. Check the checkboxes corresponding to the GitLab events you want to send notifications for to Discord. +1. Check the checkboxes corresponding to the GitLab events for which you want to send notifications to Discord. 1. Paste the webhook URL that you copied from the create Discord webhook step. 1. Configure the remaining options and click the **Save changes** button. -The Discord channel you created the webhook for will now receive notification of the GitLab events as configured. +The Discord channel you created the webhook for will now receive notification of the GitLab events that were configured. -- cgit v1.2.1 From 762959465c36d6ff119676353ba21bb56fd1609c Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Tue, 6 Nov 2018 22:07:07 +1100 Subject: DRY specs, fix typos in docs --- app/models/project_services/discord_service.rb | 2 +- .../project/integrations/discord_notifications.md | 2 +- .../project_services/discord_service_spec.rb | 32 ++++++++------------ .../project_services/hangouts_chat_service_spec.rb | 35 ++++++++-------------- .../models/project_services_spec.rb | 9 ++++++ 5 files changed, 35 insertions(+), 45 deletions(-) create mode 100644 spec/support/shared_examples/models/project_services_spec.rb diff --git a/app/models/project_services/discord_service.rb b/app/models/project_services/discord_service.rb index 3718af3a6e6..ee7d737a68b 100644 --- a/app/models/project_services/discord_service.rb +++ b/app/models/project_services/discord_service.rb @@ -16,7 +16,7 @@ class DiscordService < ChatNotificationService end def help - "This service sends notifications about projects events to Discord channels.
+ "This service sends notifications about project events to Discord channels.
To set up this service:
  1. Setup a custom Incoming Webhook.
  2. diff --git a/doc/user/project/integrations/discord_notifications.md b/doc/user/project/integrations/discord_notifications.md index b65b897c442..e157f5cc106 100644 --- a/doc/user/project/integrations/discord_notifications.md +++ b/doc/user/project/integrations/discord_notifications.md @@ -4,7 +4,7 @@ The Discord Notifications service sends event notifications from GitLab to the channel for which the webhook was created. -To send GitLab event notifications to a Discord channel, create a webhook in Discourse and configure it in GitLab. +To send GitLab event notifications to a Discord channel, create a webhook in Discord and configure it in GitLab. ## Create webhook diff --git a/spec/models/project_services/discord_service_spec.rb b/spec/models/project_services/discord_service_spec.rb index 695fa96d9c1..99c2ada7ad8 100644 --- a/spec/models/project_services/discord_service_spec.rb +++ b/spec/models/project_services/discord_service_spec.rb @@ -43,20 +43,12 @@ describe DiscordService do WebMock.stub_request(:post, webhook_url) end - shared_examples "Discord service" do - it "calls Discord Webhooks API" do - subject.execute(sample_data) - - expect(WebMock).to have_requested(:post, webhook_url).with { |req| req.body =~ /\A{"content":.+}\Z/ }.once - end - end - context "with push events" do let(:sample_data) do Gitlab::DataBuilder::Push.build_sample(project, user) end - it_behaves_like "Discord service" + it_behaves_like "Interacts with external service", "Discord", content_key: :content it "specifies the webhook when it is configured" do expect(Discordrb::Webhooks::Client).to receive(:new).with(url: webhook_url).and_return(double(:discord_service).as_null_object) @@ -86,7 +78,7 @@ describe DiscordService do subject.notify_only_default_branch = false end - it_behaves_like "Discord service" + it_behaves_like "Interacts with external service", "Discord", content_key: :content end end end @@ -99,7 +91,7 @@ describe DiscordService do service.hook_data(issue, "open") end - it_behaves_like "Discord service" + it_behaves_like "Interacts with external service", "Discord", content_key: :content end context "with merge events" do @@ -122,7 +114,7 @@ describe DiscordService do project.add_developer(user) end - it_behaves_like "Discord service" + it_behaves_like "Interacts with external service", "Discord", content_key: :content end context "with wiki page events" do @@ -137,7 +129,7 @@ describe DiscordService do let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) } let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, "create") } - it_behaves_like "Discord service" + it_behaves_like "Interacts with external service", "Discord", content_key: :content end context "with note events" do @@ -152,7 +144,7 @@ describe DiscordService do note: "a comment on a commit") end - it_behaves_like "Discord service" + it_behaves_like "Interacts with external service", "Discord", content_key: :content end context "with merge request comment" do @@ -160,7 +152,7 @@ describe DiscordService do create(:note_on_merge_request, project: project, note: "merge request note") end - it_behaves_like "Discord service" + it_behaves_like "Interacts with external service", "Discord", content_key: :content end context "with issue comment" do @@ -168,7 +160,7 @@ describe DiscordService do create(:note_on_issue, project: project, note: "issue note") end - it_behaves_like "Discord service" + it_behaves_like "Interacts with external service", "Discord", content_key: :content end context "with snippet comment" do @@ -176,7 +168,7 @@ describe DiscordService do create(:note_on_project_snippet, project: project, note: "snippet note") end - it_behaves_like "Discord service" + it_behaves_like "Interacts with external service", "Discord", content_key: :content end end @@ -191,7 +183,7 @@ describe DiscordService do context "with failed pipeline" do let(:status) { "failed" } - it_behaves_like "Discord service" + it_behaves_like "Interacts with external service", "Discord", content_key: :content end context "with succeeded pipeline" do @@ -210,7 +202,7 @@ describe DiscordService do subject.notify_only_broken_pipelines = false end - it_behaves_like "Discord service" + it_behaves_like "Interacts with external service", "Discord", content_key: :content end end @@ -236,7 +228,7 @@ describe DiscordService do subject.notify_only_default_branch = false end - it_behaves_like "Discord service" + it_behaves_like "Interacts with external service", "Discord", content_key: :content end end end diff --git a/spec/models/project_services/hangouts_chat_service_spec.rb b/spec/models/project_services/hangouts_chat_service_spec.rb index cfa55188a64..3557f62fde2 100644 --- a/spec/models/project_services/hangouts_chat_service_spec.rb +++ b/spec/models/project_services/hangouts_chat_service_spec.rb @@ -41,23 +41,12 @@ describe HangoutsChatService do WebMock.stub_request(:post, webhook_url) end - shared_examples 'Hangouts Chat service' do - it 'calls Hangouts Chat API' do - subject.execute(sample_data) - - expect(WebMock) - .to have_requested(:post, webhook_url) - .with { |req| req.body =~ /\A{"text":.+}\Z/ } - .once - end - end - context 'with push events' do let(:sample_data) do Gitlab::DataBuilder::Push.build_sample(project, user) end - it_behaves_like 'Hangouts Chat service' + it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text it 'specifies the webhook when it is configured' do expect(HangoutsChat::Sender).to receive(:new).with(webhook_url).and_return(double(:hangouts_chat_service).as_null_object) @@ -87,7 +76,7 @@ describe HangoutsChatService do subject.notify_only_default_branch = false end - it_behaves_like 'Hangouts Chat service' + it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text end end end @@ -100,7 +89,7 @@ describe HangoutsChatService do service.hook_data(issue, 'open') end - it_behaves_like 'Hangouts Chat service' + it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text end context 'with merge events' do @@ -123,7 +112,7 @@ describe HangoutsChatService do project.add_developer(user) end - it_behaves_like 'Hangouts Chat service' + it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text end context 'with wiki page events' do @@ -138,7 +127,7 @@ describe HangoutsChatService do let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) } let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') } - it_behaves_like 'Hangouts Chat service' + it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text end context 'with note events' do @@ -152,7 +141,7 @@ describe HangoutsChatService do note: 'a comment on a commit') end - it_behaves_like 'Hangouts Chat service' + it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text end context 'with merge request comment' do @@ -161,7 +150,7 @@ describe HangoutsChatService do note: 'merge request note') end - it_behaves_like 'Hangouts Chat service' + it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text end context 'with issue comment' do @@ -169,7 +158,7 @@ describe HangoutsChatService do create(:note_on_issue, project: project, note: 'issue note') end - it_behaves_like 'Hangouts Chat service' + it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text end context 'with snippet comment' do @@ -178,7 +167,7 @@ describe HangoutsChatService do note: 'snippet note') end - it_behaves_like 'Hangouts Chat service' + it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text end end @@ -193,7 +182,7 @@ describe HangoutsChatService do context 'with failed pipeline' do let(:status) { 'failed' } - it_behaves_like 'Hangouts Chat service' + it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text end context 'with succeeded pipeline' do @@ -212,7 +201,7 @@ describe HangoutsChatService do subject.notify_only_broken_pipelines = false end - it_behaves_like 'Hangouts Chat service' + it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text end end @@ -238,7 +227,7 @@ describe HangoutsChatService do subject.notify_only_default_branch = false end - it_behaves_like 'Hangouts Chat service' + it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text end end end diff --git a/spec/support/shared_examples/models/project_services_spec.rb b/spec/support/shared_examples/models/project_services_spec.rb new file mode 100644 index 00000000000..4eec52a2d52 --- /dev/null +++ b/spec/support/shared_examples/models/project_services_spec.rb @@ -0,0 +1,9 @@ +require "spec_helper" + +shared_examples_for "Interacts with external service" do |service_name, content_key:| + it "calls #{service_name} Webhooks API" do + subject.execute(sample_data) + + expect(WebMock).to have_requested(:post, webhook_url).with { |req| req.body =~ /\A{"#{content_key}":.+}\Z/ }.once + end +end -- cgit v1.2.1 From 079a75088e482c5c32cbe8b4606584256284316b Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Wed, 7 Nov 2018 09:12:02 +1100 Subject: Refactor specs --- .../project_services/discord_service_spec.rb | 233 +------------------- .../project_services/hangouts_chat_service_spec.rb | 238 +------------------- .../shared_examples/models/chat_service_spec.rb | 242 +++++++++++++++++++++ .../models/project_services_spec.rb | 9 - 4 files changed, 253 insertions(+), 469 deletions(-) create mode 100644 spec/support/shared_examples/models/chat_service_spec.rb delete mode 100644 spec/support/shared_examples/models/project_services_spec.rb diff --git a/spec/models/project_services/discord_service_spec.rb b/spec/models/project_services/discord_service_spec.rb index 99c2ada7ad8..52e2314b080 100644 --- a/spec/models/project_services/discord_service_spec.rb +++ b/spec/models/project_services/discord_service_spec.rb @@ -3,234 +3,9 @@ require "spec_helper" describe DiscordService do - describe "Associations" do - it { is_expected.to belong_to :project } - it { is_expected.to have_one :service_hook } - end - - describe "Validations" do - context "when service is active" do - before do - subject.active = true - end - - it { is_expected.to validate_presence_of(:webhook) } - it_behaves_like "issue tracker service URL attribute", :webhook - end - - context "when service is inactive" do - before do - subject.active = false - end - - it { is_expected.not_to validate_presence_of(:webhook) } - end - end - - describe "#execute" do - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } - let(:webhook_url) { "https://example.gitlab.com/" } - - before do - allow(subject).to receive_messages( - project: project, - project_id: project.id, - service_hook: true, - webhook: webhook_url - ) - - WebMock.stub_request(:post, webhook_url) - end - - context "with push events" do - let(:sample_data) do - Gitlab::DataBuilder::Push.build_sample(project, user) - end - - it_behaves_like "Interacts with external service", "Discord", content_key: :content - - it "specifies the webhook when it is configured" do - expect(Discordrb::Webhooks::Client).to receive(:new).with(url: webhook_url).and_return(double(:discord_service).as_null_object) - - subject.execute(sample_data) - end - - context "with not default branch" do - let(:sample_data) do - Gitlab::DataBuilder::Push.build(project, user, nil, nil, "not-the-default-branch") - end - - context "when notify_only_default_branch enabled" do - before do - subject.notify_only_default_branch = true - end - - it "does not call the Discord Webhooks API" do - result = subject.execute(sample_data) - - expect(result).to be_falsy - end - end - - context "when notify_only_default_branch disabled" do - before do - subject.notify_only_default_branch = false - end - - it_behaves_like "Interacts with external service", "Discord", content_key: :content - end - end - end - - context "with issue events" do - let(:opts) { { title: "Awesome issue", description: "please fix" } } - let(:sample_data) do - service = Issues::CreateService.new(project, user, opts) - issue = service.execute - service.hook_data(issue, "open") - end - - it_behaves_like "Interacts with external service", "Discord", content_key: :content - end - - context "with merge events" do - let(:opts) do - { - title: "Awesome merge_request", - description: "please fix", - source_branch: "feature", - target_branch: "master" - } - end - - let(:sample_data) do - service = MergeRequests::CreateService.new(project, user, opts) - merge_request = service.execute - service.hook_data(merge_request, "open") - end - - before do - project.add_developer(user) - end - - it_behaves_like "Interacts with external service", "Discord", content_key: :content - end - - context "with wiki page events" do - let(:opts) do - { - title: "Awesome wiki_page", - content: "Some text describing some thing or another", - format: "md", - message: "user created page: Awesome wiki_page" - } - end - let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) } - let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, "create") } - - it_behaves_like "Interacts with external service", "Discord", content_key: :content - end - - context "with note events" do - let(:sample_data) { Gitlab::DataBuilder::Note.build(note, user) } - - context "with commit comment" do - let(:note) do - create(:note_on_commit, - author: user, - project: project, - commit_id: project.repository.commit.id, - note: "a comment on a commit") - end - - it_behaves_like "Interacts with external service", "Discord", content_key: :content - end - - context "with merge request comment" do - let(:note) do - create(:note_on_merge_request, project: project, note: "merge request note") - end - - it_behaves_like "Interacts with external service", "Discord", content_key: :content - end - - context "with issue comment" do - let(:note) do - create(:note_on_issue, project: project, note: "issue note") - end - - it_behaves_like "Interacts with external service", "Discord", content_key: :content - end - - context "with snippet comment" do - let(:note) do - create(:note_on_project_snippet, project: project, note: "snippet note") - end - - it_behaves_like "Interacts with external service", "Discord", content_key: :content - end - end - - context "with pipeline events" do - let(:pipeline) do - create(:ci_pipeline, - project: project, status: status, - sha: project.commit.sha, ref: project.default_branch) - end - let(:sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) } - - context "with failed pipeline" do - let(:status) { "failed" } - - it_behaves_like "Interacts with external service", "Discord", content_key: :content - end - - context "with succeeded pipeline" do - let(:status) { "success" } - - context "with default notify_only_broken_pipelines" do - it "does not call Discord Webhooks API" do - result = subject.execute(sample_data) - - expect(result).to be_falsy - end - end - - context "when notify_only_broken_pipelines is false" do - before do - subject.notify_only_broken_pipelines = false - end - - it_behaves_like "Interacts with external service", "Discord", content_key: :content - end - end - - context "with not default branch" do - let(:pipeline) do - create(:ci_pipeline, project: project, status: "failed", ref: "not-the-default-branch") - end - - context "when notify_only_default_branch enabled" do - before do - subject.notify_only_default_branch = true - end - - it "does not call the Discord Webhooks API" do - result = subject.execute(sample_data) - - expect(result).to be_falsy - end - end - - context "when notify_only_default_branch disabled" do - before do - subject.notify_only_default_branch = false - end - - it_behaves_like "Interacts with external service", "Discord", content_key: :content - end - end - end + it_behaves_like "chat service", "Hangouts Chat" do + let(:client) { Discordrb::Webhooks::Client } + let(:client_arguments) { { url: webhook_url } } + let(:content_key) { :content } end end diff --git a/spec/models/project_services/hangouts_chat_service_spec.rb b/spec/models/project_services/hangouts_chat_service_spec.rb index 3557f62fde2..0505ac9b49c 100644 --- a/spec/models/project_services/hangouts_chat_service_spec.rb +++ b/spec/models/project_services/hangouts_chat_service_spec.rb @@ -1,235 +1,11 @@ -require 'spec_helper' +# frozen_string_literal: true -describe HangoutsChatService do - describe 'Associations' do - it { is_expected.to belong_to :project } - it { is_expected.to have_one :service_hook } - end - - describe 'Validations' do - context 'when service is active' do - before do - subject.active = true - end - - it { is_expected.to validate_presence_of(:webhook) } - it_behaves_like 'issue tracker service URL attribute', :webhook - end - - context 'when service is inactive' do - before do - subject.active = false - end - - it { is_expected.not_to validate_presence_of(:webhook) } - end - end - - describe '#execute' do - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } - let(:webhook_url) { 'https://example.gitlab.com/' } - - before do - allow(subject).to receive_messages( - project: project, - project_id: project.id, - service_hook: true, - webhook: webhook_url - ) - - WebMock.stub_request(:post, webhook_url) - end - - context 'with push events' do - let(:sample_data) do - Gitlab::DataBuilder::Push.build_sample(project, user) - end - - it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text - - it 'specifies the webhook when it is configured' do - expect(HangoutsChat::Sender).to receive(:new).with(webhook_url).and_return(double(:hangouts_chat_service).as_null_object) - - subject.execute(sample_data) - end - - context 'with not default branch' do - let(:sample_data) do - Gitlab::DataBuilder::Push.build(project, user, nil, nil, 'not-the-default-branch') - end - - context 'when notify_only_default_branch enabled' do - before do - subject.notify_only_default_branch = true - end - - it 'does not call the Hangouts Chat API' do - result = subject.execute(sample_data) - - expect(result).to be_falsy - end - end - - context 'when notify_only_default_branch disabled' do - before do - subject.notify_only_default_branch = false - end - - it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text - end - end - end - - context 'with issue events' do - let(:opts) { { title: 'Awesome issue', description: 'please fix' } } - let(:sample_data) do - service = Issues::CreateService.new(project, user, opts) - issue = service.execute - service.hook_data(issue, 'open') - end - - it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text - end - - context 'with merge events' do - let(:opts) do - { - title: 'Awesome merge_request', - description: 'please fix', - source_branch: 'feature', - target_branch: 'master' - } - end - - let(:sample_data) do - service = MergeRequests::CreateService.new(project, user, opts) - merge_request = service.execute - service.hook_data(merge_request, 'open') - end - - before do - project.add_developer(user) - end - - it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text - end +require "spec_helper" - context 'with wiki page events' do - let(:opts) do - { - title: 'Awesome wiki_page', - content: 'Some text describing some thing or another', - format: 'md', - message: 'user created page: Awesome wiki_page' - } - end - let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) } - let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') } - - it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text - end - - context 'with note events' do - let(:sample_data) { Gitlab::DataBuilder::Note.build(note, user) } - - context 'with commit comment' do - let(:note) do - create(:note_on_commit, author: user, - project: project, - commit_id: project.repository.commit.id, - note: 'a comment on a commit') - end - - it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text - end - - context 'with merge request comment' do - let(:note) do - create(:note_on_merge_request, project: project, - note: 'merge request note') - end - - it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text - end - - context 'with issue comment' do - let(:note) do - create(:note_on_issue, project: project, note: 'issue note') - end - - it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text - end - - context 'with snippet comment' do - let(:note) do - create(:note_on_project_snippet, project: project, - note: 'snippet note') - end - - it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text - end - end - - context 'with pipeline events' do - let(:pipeline) do - create(:ci_pipeline, - project: project, status: status, - sha: project.commit.sha, ref: project.default_branch) - end - let(:sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) } - - context 'with failed pipeline' do - let(:status) { 'failed' } - - it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text - end - - context 'with succeeded pipeline' do - let(:status) { 'success' } - - context 'with default notify_only_broken_pipelines' do - it 'does not call Hangouts Chat API' do - result = subject.execute(sample_data) - - expect(result).to be_falsy - end - end - - context 'when notify_only_broken_pipelines is false' do - before do - subject.notify_only_broken_pipelines = false - end - - it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text - end - end - - context 'with not default branch' do - let(:pipeline) do - create(:ci_pipeline, project: project, status: 'failed', ref: 'not-the-default-branch') - end - - context 'when notify_only_default_branch enabled' do - before do - subject.notify_only_default_branch = true - end - - it 'does not call the Hangouts Chat API' do - result = subject.execute(sample_data) - - expect(result).to be_falsy - end - end - - context 'when notify_only_default_branch disabled' do - before do - subject.notify_only_default_branch = false - end - - it_behaves_like "Interacts with external service", "Hangouts Chat", content_key: :text - end - end - end +describe HangoutsChatService do + it_behaves_like "chat service", "Hangouts Chat" do + let(:client) { HangoutsChat::Sender } + let(:client_arguments) { webhook_url } + let(:content_key) { :text } end end diff --git a/spec/support/shared_examples/models/chat_service_spec.rb b/spec/support/shared_examples/models/chat_service_spec.rb new file mode 100644 index 00000000000..cf1d52a9616 --- /dev/null +++ b/spec/support/shared_examples/models/chat_service_spec.rb @@ -0,0 +1,242 @@ +require "spec_helper" + +shared_examples_for "chat service" do |service_name| + describe "Associations" do + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } + end + + describe "Validations" do + context "when service is active" do + before do + subject.active = true + end + + it { is_expected.to validate_presence_of(:webhook) } + it_behaves_like "issue tracker service URL attribute", :webhook + end + + context "when service is inactive" do + before do + subject.active = false + end + + it { is_expected.not_to validate_presence_of(:webhook) } + end + end + + describe "#execute" do + let(:user) { create(:user) } + let(:project) { create(:project, :repository) } + let(:webhook_url) { "https://example.gitlab.com/" } + + before do + allow(subject).to receive_messages( + project: project, + project_id: project.id, + service_hook: true, + webhook: webhook_url + ) + + WebMock.stub_request(:post, webhook_url) + end + + shared_examples "#{service_name} service" do + it "calls #{service_name} API" do + subject.execute(sample_data) + + expect(WebMock).to have_requested(:post, webhook_url).with { |req| req.body =~ /\A{"#{content_key}":.+}\Z/ }.once + end + end + + context "with push events" do + let(:sample_data) do + Gitlab::DataBuilder::Push.build_sample(project, user) + end + + it_behaves_like "#{service_name} service" + + 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) + + subject.execute(sample_data) + end + + context "with not default branch" do + let(:sample_data) do + Gitlab::DataBuilder::Push.build(project, user, nil, nil, "not-the-default-branch") + end + + context "when notify_only_default_branch enabled" do + before do + subject.notify_only_default_branch = true + end + + it "does not call the Discord Webhooks API" do + result = subject.execute(sample_data) + + expect(result).to be_falsy + end + end + + context "when notify_only_default_branch disabled" do + before do + subject.notify_only_default_branch = false + end + + it_behaves_like "#{service_name} service" + end + end + end + + context "with issue events" do + let(:opts) { { title: "Awesome issue", description: "please fix" } } + let(:sample_data) do + service = Issues::CreateService.new(project, user, opts) + issue = service.execute + service.hook_data(issue, "open") + end + + it_behaves_like "#{service_name} service" + end + + context "with merge events" do + let(:opts) do + { + title: "Awesome merge_request", + description: "please fix", + source_branch: "feature", + target_branch: "master" + } + end + + let(:sample_data) do + service = MergeRequests::CreateService.new(project, user, opts) + merge_request = service.execute + service.hook_data(merge_request, "open") + end + + before do + project.add_developer(user) + end + + it_behaves_like "#{service_name} service" + end + + context "with wiki page events" do + let(:opts) do + { + title: "Awesome wiki_page", + content: "Some text describing some thing or another", + format: "md", + message: "user created page: Awesome wiki_page" + } + end + let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) } + let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, "create") } + + it_behaves_like "#{service_name} service" + end + + context "with note events" do + let(:sample_data) { Gitlab::DataBuilder::Note.build(note, user) } + + context "with commit comment" do + let(:note) do + create(:note_on_commit, + author: user, + project: project, + commit_id: project.repository.commit.id, + note: "a comment on a commit") + end + + it_behaves_like "#{service_name} service" + end + + context "with merge request comment" do + let(:note) do + create(:note_on_merge_request, project: project, note: "merge request note") + end + + it_behaves_like "#{service_name} service" + end + + context "with issue comment" do + let(:note) do + create(:note_on_issue, project: project, note: "issue note") + end + + it_behaves_like "#{service_name} service" + end + + context "with snippet comment" do + let(:note) do + create(:note_on_project_snippet, project: project, note: "snippet note") + end + + it_behaves_like "#{service_name} service" + end + end + + context "with pipeline events" do + let(:pipeline) do + create(:ci_pipeline, + project: project, status: status, + sha: project.commit.sha, ref: project.default_branch) + end + let(:sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) } + + context "with failed pipeline" do + let(:status) { "failed" } + + it_behaves_like "#{service_name} service" + end + + context "with succeeded pipeline" do + let(:status) { "success" } + + context "with default notify_only_broken_pipelines" do + it "does not call Discord Webhooks API" do + result = subject.execute(sample_data) + + expect(result).to be_falsy + end + end + + context "when notify_only_broken_pipelines is false" do + before do + subject.notify_only_broken_pipelines = false + end + + it_behaves_like "#{service_name} service" + end + end + + context "with not default branch" do + let(:pipeline) do + create(:ci_pipeline, project: project, status: "failed", ref: "not-the-default-branch") + end + + context "when notify_only_default_branch enabled" do + before do + subject.notify_only_default_branch = true + end + + it "does not call the Discord Webhooks API" do + result = subject.execute(sample_data) + + expect(result).to be_falsy + end + end + + context "when notify_only_default_branch disabled" do + before do + subject.notify_only_default_branch = false + end + + it_behaves_like "#{service_name} service" + end + end + end + end +end diff --git a/spec/support/shared_examples/models/project_services_spec.rb b/spec/support/shared_examples/models/project_services_spec.rb deleted file mode 100644 index 4eec52a2d52..00000000000 --- a/spec/support/shared_examples/models/project_services_spec.rb +++ /dev/null @@ -1,9 +0,0 @@ -require "spec_helper" - -shared_examples_for "Interacts with external service" do |service_name, content_key:| - it "calls #{service_name} Webhooks API" do - subject.execute(sample_data) - - expect(WebMock).to have_requested(:post, webhook_url).with { |req| req.body =~ /\A{"#{content_key}":.+}\Z/ }.once - end -end -- cgit v1.2.1 From e03ebd80bb610fb106e82c4ab517c050dbd7f6a7 Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Sat, 10 Nov 2018 09:50:37 +1100 Subject: Fix minor offenses --- app/models/project_services/discord_service.rb | 6 +----- spec/models/project_services/discord_service_spec.rb | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/models/project_services/discord_service.rb b/app/models/project_services/discord_service.rb index ee7d737a68b..21afd14dbff 100644 --- a/app/models/project_services/discord_service.rb +++ b/app/models/project_services/discord_service.rb @@ -25,10 +25,6 @@ class DiscordService < ChatNotificationService
" end - def webhook_placeholder - "https://discordapp.com/api/webhooks/..." - end - def event_field(event) # No-op. end @@ -39,7 +35,7 @@ class DiscordService < ChatNotificationService def default_fields [ - { type: "text", name: "webhook", placeholder: "e.g. #{webhook_placeholder}" }, + { type: "text", name: "webhook", placeholder: "e.g. https://discordapp.com/api/webhooks/…" }, { type: "checkbox", name: "notify_only_broken_pipelines" }, { type: "checkbox", name: "notify_only_default_branch" } ] diff --git a/spec/models/project_services/discord_service_spec.rb b/spec/models/project_services/discord_service_spec.rb index 52e2314b080..be82f223478 100644 --- a/spec/models/project_services/discord_service_spec.rb +++ b/spec/models/project_services/discord_service_spec.rb @@ -3,7 +3,7 @@ require "spec_helper" describe DiscordService do - it_behaves_like "chat service", "Hangouts Chat" do + it_behaves_like "chat service", "Discord notifications" do let(:client) { Discordrb::Webhooks::Client } let(:client_arguments) { { url: webhook_url } } let(:content_key) { :content } -- cgit v1.2.1