diff options
author | Jason Goodman <jgoodman@gitlab.com> | 2019-04-26 21:08:41 +0000 |
---|---|---|
committer | Douglas Barbosa Alexandre <dbalexandre@gmail.com> | 2019-04-26 21:08:41 +0000 |
commit | fe86890b9d7a720648e7570d227c438d6ca7f25a (patch) | |
tree | 1c583b22cea6404de37ae6217f320d93cdf7cde9 /spec | |
parent | 265b789476479c29ea88db174aca1d80ddf24358 (diff) | |
download | gitlab-ce-fe86890b9d7a720648e7570d227c438d6ca7f25a.tar.gz |
Add deployment events to chat notification services
This enables sending a chat message to Slack or Mattermost
upon a successful, failed, or canceled deployment
Diffstat (limited to 'spec')
-rw-r--r-- | spec/factories/deployments.rb | 2 | ||||
-rw-r--r-- | spec/features/admin/admin_settings_spec.rb | 15 | ||||
-rw-r--r-- | spec/lib/gitlab/data_builder/deployment_spec.rb | 36 | ||||
-rw-r--r-- | spec/lib/gitlab/import_export/safe_model_attributes.yml | 1 | ||||
-rw-r--r-- | spec/models/ci/build_spec.rb | 4 | ||||
-rw-r--r-- | spec/models/deployment_spec.rb | 21 | ||||
-rw-r--r-- | spec/models/project_services/chat_message/deployment_message_spec.rb | 150 | ||||
-rw-r--r-- | spec/models/project_services/microsoft_teams_service_spec.rb | 6 | ||||
-rw-r--r-- | spec/services/update_deployment_service_spec.rb | 1 | ||||
-rw-r--r-- | spec/support/shared_examples/models/chat_service_spec.rb | 6 | ||||
-rw-r--r-- | spec/support/shared_examples/slack_mattermost_notifications_shared_examples.rb | 8 | ||||
-rw-r--r-- | spec/workers/build_success_worker_spec.rb | 1 | ||||
-rw-r--r-- | spec/workers/deployments/finished_worker_spec.rb | 39 |
13 files changed, 287 insertions, 3 deletions
diff --git a/spec/factories/deployments.rb b/spec/factories/deployments.rb index 011c98599a3..db438ad32d3 100644 --- a/spec/factories/deployments.rb +++ b/spec/factories/deployments.rb @@ -1,6 +1,6 @@ FactoryBot.define do factory :deployment, class: Deployment do - sha '97de212e80737a608d939f648d959671fb0a0142' + sha 'b83d6e391c22777fca1ed3012fce84f633d7fed0' ref 'master' tag false user nil diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index 04f39b807d7..3c9a9d61756 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -230,6 +230,13 @@ describe 'Admin updates settings' do expect(find_field('Username').value).to eq 'test_user' expect(find('#service_push_channel').value).to eq '#test_channel' end + + it 'defaults Deployment events to false for chat notification template settings' do + first(:link, 'Service Templates').click + click_link 'Slack notifications' + + expect(find_field('Deployment')).not_to be_checked + end end context 'CI/CD page' do @@ -373,10 +380,14 @@ describe 'Admin updates settings' do def check_all_events page.check('Active') page.check('Push') - page.check('Tag push') - page.check('Note') page.check('Issue') + page.check('Confidential issue') page.check('Merge request') + page.check('Note') + page.check('Confidential note') + page.check('Tag push') page.check('Pipeline') + page.check('Wiki page') + page.check('Deployment') end end diff --git a/spec/lib/gitlab/data_builder/deployment_spec.rb b/spec/lib/gitlab/data_builder/deployment_spec.rb new file mode 100644 index 00000000000..b89a44e178b --- /dev/null +++ b/spec/lib/gitlab/data_builder/deployment_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::DataBuilder::Deployment do + describe '.build' do + it 'returns the object kind for a deployment' do + deployment = build(:deployment) + + data = described_class.build(deployment) + + expect(data[:object_kind]).to eq('deployment') + end + + it 'returns data for the given build' do + environment = create(:environment, name: "somewhere") + project = create(:project, :repository, name: 'myproj') + commit = project.commit('HEAD') + deployment = create(:deployment, status: :failed, environment: environment, sha: commit.sha, project: project) + deployable = deployment.deployable + expected_deployable_url = Gitlab::Routing.url_helpers.project_job_url(deployable.project, deployable) + expected_commit_url = Gitlab::UrlBuilder.build(commit) + + data = described_class.build(deployment) + + expect(data[:status]).to eq('failed') + expect(data[:deployable_id]).to eq(deployable.id) + expect(data[:deployable_url]).to eq(expected_deployable_url) + expect(data[:environment]).to eq("somewhere") + expect(data[:project]).to eq(project.hook_attrs) + expect(data[:short_sha]).to eq(deployment.short_sha) + expect(data[:user]).to eq(deployment.user.hook_attrs) + expect(data[:commit_url]).to eq(expected_commit_url) + end + end +end diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 591a3d296c2..9093d21647a 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -423,6 +423,7 @@ Service: - wiki_page_events - confidential_issues_events - confidential_note_events +- deployment_events ProjectHook: - id - url diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 3a7d20a58c8..339483d4f7d 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -856,6 +856,10 @@ describe Ci::Build do let(:deployment) { build.deployment } let(:environment) { deployment.environment } + before do + allow(Deployments::FinishedWorker).to receive(:perform_async) + end + it 'has deployments record with created status' do expect(deployment).to be_created expect(environment.name).to eq('review/master') diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb index d9170d5fa07..0ca758429b8 100644 --- a/spec/models/deployment_spec.rb +++ b/spec/models/deployment_spec.rb @@ -102,6 +102,13 @@ describe Deployment do deployment.succeed! end + + it 'executes Deployments::FinishedWorker asynchronously' do + expect(Deployments::FinishedWorker) + .to receive(:perform_async).with(deployment.id) + + deployment.succeed! + end end context 'when deployment failed' do @@ -115,6 +122,13 @@ describe Deployment do expect(deployment.finished_at).to be_like_time(Time.now) end end + + it 'executes Deployments::FinishedWorker asynchronously' do + expect(Deployments::FinishedWorker) + .to receive(:perform_async).with(deployment.id) + + deployment.drop! + end end context 'when deployment was canceled' do @@ -128,6 +142,13 @@ describe Deployment do expect(deployment.finished_at).to be_like_time(Time.now) end end + + it 'executes Deployments::FinishedWorker asynchronously' do + expect(Deployments::FinishedWorker) + .to receive(:perform_async).with(deployment.id) + + deployment.cancel! + end end end diff --git a/spec/models/project_services/chat_message/deployment_message_spec.rb b/spec/models/project_services/chat_message/deployment_message_spec.rb new file mode 100644 index 00000000000..86565ce8b01 --- /dev/null +++ b/spec/models/project_services/chat_message/deployment_message_spec.rb @@ -0,0 +1,150 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe ChatMessage::DeploymentMessage do + describe '#pretext' do + it 'returns a message with the data returned by the deployment data builder' do + environment = create(:environment, name: "myenvironment") + project = create(:project, :repository) + commit = project.commit('HEAD') + deployment = create(:deployment, status: :success, environment: environment, project: project, sha: commit.sha) + data = Gitlab::DataBuilder::Deployment.build(deployment) + + message = described_class.new(data) + + expect(message.pretext).to eq("Deploy to myenvironment succeeded") + end + + it 'returns a message for a successful deployment' do + data = { + status: 'success', + environment: 'production' + } + + message = described_class.new(data) + + expect(message.pretext).to eq('Deploy to production succeeded') + end + + it 'returns a message for a failed deployment' do + data = { + status: 'failed', + environment: 'production' + } + + message = described_class.new(data) + + expect(message.pretext).to eq('Deploy to production failed') + end + + it 'returns a message for a canceled deployment' do + data = { + status: 'canceled', + environment: 'production' + } + + message = described_class.new(data) + + expect(message.pretext).to eq('Deploy to production canceled') + end + + it 'returns a message for a deployment to another environment' do + data = { + status: 'success', + environment: 'staging' + } + + message = described_class.new(data) + + expect(message.pretext).to eq('Deploy to staging succeeded') + end + + it 'returns a message for a deployment with any other status' do + data = { + status: 'unknown', + environment: 'staging' + } + + message = described_class.new(data) + + expect(message.pretext).to eq('Deploy to staging unknown') + end + end + + describe '#attachments' do + def deployment_data(params) + { + object_kind: "deployment", + status: "success", + deployable_id: 3, + deployable_url: "deployable_url", + environment: "sandbox", + project: { + name: "greatproject", + web_url: "project_web_url", + path_with_namespace: "project_path_with_namespace" + }, + user: { + name: "Jane Person", + username: "jane" + }, + short_sha: "12345678", + commit_url: "commit_url" + }.merge(params) + end + + it 'returns attachments with the data returned by the deployment data builder' do + user = create(:user, name: "John Smith", username: "smith") + namespace = create(:namespace, name: "myspace") + project = create(:project, :repository, namespace: namespace, name: "myproject") + commit = project.commit('HEAD') + environment = create(:environment, name: "myenvironment", project: project) + ci_build = create(:ci_build, project: project) + deployment = create(:deployment, :success, deployable: ci_build, environment: environment, project: project, user: user, sha: commit.sha) + job_url = Gitlab::Routing.url_helpers.project_job_url(project, ci_build) + commit_url = Gitlab::UrlBuilder.build(deployment.commit) + data = Gitlab::DataBuilder::Deployment.build(deployment) + + message = described_class.new(data) + + expect(message.attachments).to eq([{ + text: "[myspace/myproject](#{project.web_url})\n[Job ##{ci_build.id}](#{job_url}), SHA [#{deployment.short_sha}](#{commit_url}), by John Smith (smith)", + color: "good" + }]) + end + + it 'returns attachments for a failed deployment' do + data = deployment_data(status: 'failed') + + message = described_class.new(data) + + expect(message.attachments).to eq([{ + text: "[project_path_with_namespace](project_web_url)\n[Job #3](deployable_url), SHA [12345678](commit_url), by Jane Person (jane)", + color: "danger" + }]) + end + + it 'returns attachments for a canceled deployment' do + data = deployment_data(status: 'canceled') + + message = described_class.new(data) + + expect(message.attachments).to eq([{ + text: "[project_path_with_namespace](project_web_url)\n[Job #3](deployable_url), SHA [12345678](commit_url), by Jane Person (jane)", + color: "warning" + }]) + end + + it 'uses a neutral color for a deployment with any other status' do + data = deployment_data(status: 'some-new-status-we-make-in-the-future') + + message = described_class.new(data) + + expect(message.attachments).to eq([{ + text: "[project_path_with_namespace](project_web_url)\n[Job #3](deployable_url), SHA [12345678](commit_url), by Jane Person (jane)", + color: "#334455" + }]) + end + end +end diff --git a/spec/models/project_services/microsoft_teams_service_spec.rb b/spec/models/project_services/microsoft_teams_service_spec.rb index 521d5265753..c025d7c882e 100644 --- a/spec/models/project_services/microsoft_teams_service_spec.rb +++ b/spec/models/project_services/microsoft_teams_service_spec.rb @@ -30,6 +30,12 @@ describe MicrosoftTeamsService do end end + describe '.supported_events' do + it 'does not support deployment_events' do + expect(described_class.supported_events).not_to include('deployment') + end + end + describe "#execute" do let(:user) { create(:user) } set(:project) { create(:project, :repository, :wiki_repo) } diff --git a/spec/services/update_deployment_service_spec.rb b/spec/services/update_deployment_service_spec.rb index c664bac39fc..7dc52f6816a 100644 --- a/spec/services/update_deployment_service_spec.rb +++ b/spec/services/update_deployment_service_spec.rb @@ -22,6 +22,7 @@ describe UpdateDeploymentService do subject(:service) { described_class.new(deployment) } before do + allow(Deployments::FinishedWorker).to receive(:perform_async) job.success! # Create/Succeed deployment end diff --git a/spec/support/shared_examples/models/chat_service_spec.rb b/spec/support/shared_examples/models/chat_service_spec.rb index cf1d52a9616..9d3ce5e2be1 100644 --- a/spec/support/shared_examples/models/chat_service_spec.rb +++ b/spec/support/shared_examples/models/chat_service_spec.rb @@ -25,6 +25,12 @@ shared_examples_for "chat service" do |service_name| end end + describe '.supported_events' do + it 'does not support deployment_events' do + expect(described_class.supported_events).not_to include('deployment') + end + end + describe "#execute" do let(:user) { create(:user) } let(:project) { create(:project, :repository) } diff --git a/spec/support/shared_examples/slack_mattermost_notifications_shared_examples.rb b/spec/support/shared_examples/slack_mattermost_notifications_shared_examples.rb index 940c24c8d67..c31346374f4 100644 --- a/spec/support/shared_examples/slack_mattermost_notifications_shared_examples.rb +++ b/spec/support/shared_examples/slack_mattermost_notifications_shared_examples.rb @@ -106,6 +106,14 @@ RSpec.shared_examples 'slack or mattermost notifications' do expect(WebMock).to have_requested(:post, webhook_url).once end + it "calls Slack/Mattermost API for deployment events" do + deployment_event_data = { object_kind: 'deployment' } + + chat_service.execute(deployment_event_data) + + expect(WebMock).to have_requested(:post, webhook_url).once + end + it 'uses the username as an option for slack when configured' do allow(chat_service).to receive(:username).and_return(username) diff --git a/spec/workers/build_success_worker_spec.rb b/spec/workers/build_success_worker_spec.rb index 065aeaf2b65..ffe8796ded9 100644 --- a/spec/workers/build_success_worker_spec.rb +++ b/spec/workers/build_success_worker_spec.rb @@ -15,6 +15,7 @@ describe BuildSuccessWorker do let!(:build) { create(:ci_build, :deploy_to_production) } before do + allow(Deployments::FinishedWorker).to receive(:perform_async) Deployment.delete_all build.reload end diff --git a/spec/workers/deployments/finished_worker_spec.rb b/spec/workers/deployments/finished_worker_spec.rb new file mode 100644 index 00000000000..df62821e2cd --- /dev/null +++ b/spec/workers/deployments/finished_worker_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Deployments::FinishedWorker do + let(:worker) { described_class.new } + + describe '#perform' do + before do + allow(ProjectServiceWorker).to receive(:perform_async) + end + + it 'executes project services for deployment_hooks' do + deployment = create(:deployment) + project = deployment.project + service = create(:service, type: 'SlackService', project: project, deployment_events: true, active: true) + + worker.perform(deployment.id) + + expect(ProjectServiceWorker).to have_received(:perform_async).with(service.id, an_instance_of(Hash)) + end + + it 'does not execute an inactive service' do + deployment = create(:deployment) + project = deployment.project + create(:service, type: 'SlackService', project: project, deployment_events: true, active: false) + + worker.perform(deployment.id) + + expect(ProjectServiceWorker).not_to have_received(:perform_async) + end + + it 'does nothing if a deployment with the given id does not exist' do + worker.perform(0) + + expect(ProjectServiceWorker).not_to have_received(:perform_async) + end + end +end |