summaryrefslogtreecommitdiff
path: root/spec/services/incident_management
diff options
context:
space:
mode:
Diffstat (limited to 'spec/services/incident_management')
-rw-r--r--spec/services/incident_management/create_incident_label_service_spec.rb10
-rw-r--r--spec/services/incident_management/create_issue_service_spec.rb239
-rw-r--r--spec/services/incident_management/incidents/create_service_spec.rb69
-rw-r--r--spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb99
-rw-r--r--spec/services/incident_management/pager_duty/process_webhook_service_spec.rb127
5 files changed, 170 insertions, 374 deletions
diff --git a/spec/services/incident_management/create_incident_label_service_spec.rb b/spec/services/incident_management/create_incident_label_service_spec.rb
index 2f11bcf397e..18a7c019497 100644
--- a/spec/services/incident_management/create_incident_label_service_spec.rb
+++ b/spec/services/incident_management/create_incident_label_service_spec.rb
@@ -52,7 +52,15 @@ RSpec.describe IncidentManagement::CreateIncidentLabelService do
end
context 'without label' do
- it_behaves_like 'new label'
+ context 'when user has permissions to create labels' do
+ it_behaves_like 'new label'
+ end
+
+ context 'when user has no permissions to create labels' do
+ let_it_be(:user) { create(:user) }
+
+ it_behaves_like 'new label'
+ end
end
end
end
diff --git a/spec/services/incident_management/create_issue_service_spec.rb b/spec/services/incident_management/create_issue_service_spec.rb
deleted file mode 100644
index dab9a149458..00000000000
--- a/spec/services/incident_management/create_issue_service_spec.rb
+++ /dev/null
@@ -1,239 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe IncidentManagement::CreateIssueService do
- let(:project) { create(:project, :repository, :private) }
- let_it_be(:user) { User.alert_bot }
- let(:service) { described_class.new(project, alert_payload) }
- let(:alert_starts_at) { Time.current }
- let(:alert_title) { 'TITLE' }
- let(:alert_annotations) { { title: alert_title } }
-
- let(:alert_payload) do
- build_alert_payload(
- annotations: alert_annotations,
- starts_at: alert_starts_at
- )
- end
-
- let(:alert_presenter) do
- Gitlab::Alerting::Alert.new(project: project, payload: alert_payload).present
- end
-
- let!(:setting) do
- create(:project_incident_management_setting, project: project)
- end
-
- subject { service.execute }
-
- context 'when create_issue enabled' do
- let(:issue) { subject[:issue] }
-
- before do
- setting.update!(create_issue: true)
- end
-
- context 'without issue_template_content' do
- it 'creates an issue with alert summary only' do
- expect(subject).to include(status: :success)
-
- expect(issue.author).to eq(user)
- expect(issue.title).to eq(alert_title)
- expect(issue.description).to include(alert_presenter.issue_summary_markdown.strip)
- expect(separator_count(issue.description)).to eq(0)
- end
- end
-
- context 'with erroneous issue service' do
- let(:invalid_issue) do
- build(:issue, project: project, title: nil).tap(&:valid?)
- end
-
- let(:issue_error) { invalid_issue.errors.full_messages.to_sentence }
-
- it 'returns and logs the issue error' do
- expect_next_instance_of(Issues::CreateService) do |issue_service|
- expect(issue_service).to receive(:execute).and_return(invalid_issue)
- end
-
- expect(service)
- .to receive(:log_error)
- .with(error_message(issue_error))
-
- expect(subject).to include(status: :error, message: issue_error)
- end
- end
-
- shared_examples 'GFM template' do
- context 'plain content' do
- let(:template_content) { 'some content' }
-
- it 'creates an issue appending issue template' do
- expect(subject).to include(status: :success)
-
- expect(issue.description).to include(alert_presenter.issue_summary_markdown)
- expect(separator_count(issue.description)).to eq(1)
- expect(issue.description).to include(template_content)
- end
- end
-
- context 'quick actions' do
- let(:user) { create(:user) }
- let(:plain_text) { 'some content' }
-
- let(:template_content) do
- <<~CONTENT
- #{plain_text}
- /due tomorrow
- /assign @#{user.username}
- CONTENT
- end
-
- before do
- project.add_maintainer(user)
- end
-
- it 'creates an issue interpreting quick actions' do
- expect(subject).to include(status: :success)
-
- expect(issue.description).to include(plain_text)
- expect(issue.due_date).to be_present
- expect(issue.assignees).to eq([user])
- end
- end
- end
-
- context 'with gitlab_incident_markdown' do
- let(:alert_annotations) do
- { title: alert_title, gitlab_incident_markdown: template_content }
- end
-
- it_behaves_like 'GFM template'
- end
-
- context 'with issue_template_content' do
- before do
- create_issue_template('bug', template_content)
- setting.update!(issue_template_key: 'bug')
- end
-
- it_behaves_like 'GFM template'
-
- context 'and gitlab_incident_markdown' do
- let(:template_content) { 'plain text'}
- let(:alt_template) { 'alternate text' }
- let(:alert_annotations) do
- { title: alert_title, gitlab_incident_markdown: alt_template }
- end
-
- it 'includes both templates' do
- expect(subject).to include(status: :success)
-
- expect(issue.description).to include(alert_presenter.issue_summary_markdown)
- expect(issue.description).to include(template_content)
- expect(issue.description).to include(alt_template)
- expect(separator_count(issue.description)).to eq(2)
- end
- end
-
- private
-
- def create_issue_template(name, content)
- project.repository.create_file(
- project.creator,
- ".gitlab/issue_templates/#{name}.md",
- content,
- message: 'message',
- branch_name: 'master'
- )
- end
- end
-
- context 'with gitlab alert' do
- let(:gitlab_alert) { create(:prometheus_alert, project: project) }
-
- before do
- alert_payload['labels'] = {
- 'gitlab_alert_id' => gitlab_alert.prometheus_metric_id.to_s
- }
- end
-
- it 'creates an issue' do
- query_title = "#{gitlab_alert.title} #{gitlab_alert.computed_operator} #{gitlab_alert.threshold}"
-
- expect(subject).to include(status: :success)
-
- expect(issue.author).to eq(user)
- expect(issue.title).to eq(alert_presenter.full_title)
- expect(issue.title).to include(gitlab_alert.environment.name)
- expect(issue.title).to include(query_title)
- expect(issue.title).to include('for 5 minutes')
- expect(issue.description).to include(alert_presenter.issue_summary_markdown.strip)
- expect(separator_count(issue.description)).to eq(0)
- end
- end
-
- describe 'with invalid alert payload' do
- shared_examples 'invalid alert' do
- it 'does not create an issue' do
- expect(service)
- .to receive(:log_error)
- .with(error_message('invalid alert'))
-
- expect(subject).to eq(status: :error, message: 'invalid alert')
- end
- end
-
- context 'without title' do
- let(:alert_annotations) { {} }
-
- it_behaves_like 'invalid alert'
- end
-
- context 'without startsAt' do
- let(:alert_starts_at) { nil }
-
- it_behaves_like 'invalid alert'
- end
- end
-
- describe "label `incident`" do
- it_behaves_like 'create alert issue sets issue labels'
- end
- end
-
- context 'when create_issue disabled' do
- before do
- setting.update!(create_issue: false)
- end
-
- it 'returns an error' do
- expect(service)
- .to receive(:log_error)
- .with(error_message('setting disabled'))
-
- expect(subject).to eq(status: :error, message: 'setting disabled')
- end
- end
-
- private
-
- def build_alert_payload(annotations: {}, starts_at: Time.current)
- {
- 'annotations' => annotations.stringify_keys
- }.tap do |payload|
- payload['startsAt'] = starts_at.rfc3339 if starts_at
- end
- end
-
- def error_message(message)
- %{Cannot create incident issue for "#{project.full_name}": #{message}}
- end
-
- def separator_count(text)
- summary_separator = "\n\n---\n\n"
-
- text.scan(summary_separator).size
- end
-end
diff --git a/spec/services/incident_management/incidents/create_service_spec.rb b/spec/services/incident_management/incidents/create_service_spec.rb
new file mode 100644
index 00000000000..404c428cd94
--- /dev/null
+++ b/spec/services/incident_management/incidents/create_service_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IncidentManagement::Incidents::CreateService do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { User.alert_bot }
+ let(:description) { 'Incident description' }
+
+ describe '#execute' do
+ subject(:create_incident) { described_class.new(project, user, title: title, description: description).execute }
+
+ context 'when incident has title and description' do
+ let(:title) { 'Incident title' }
+ let(:new_issue) { Issue.last! }
+ let(:label_title) { IncidentManagement::CreateIncidentLabelService::LABEL_PROPERTIES[:title] }
+
+ it 'responds with success' do
+ expect(create_incident).to be_success
+ end
+
+ it 'creates an incident issue' do
+ expect { create_incident }.to change(Issue, :count).by(1)
+ end
+
+ it 'created issue has correct attributes' do
+ create_incident
+ aggregate_failures do
+ expect(new_issue.title).to eq(title)
+ expect(new_issue.description).to eq(description)
+ expect(new_issue.author).to eq(user)
+ expect(new_issue.issue_type).to eq('incident')
+ expect(new_issue.labels.map(&:title)).to eq([label_title])
+ end
+ end
+
+ context 'when incident label does not exists' do
+ it 'creates incident label' do
+ expect { create_incident }.to change { project.labels.where(title: label_title).count }.by(1)
+ end
+ end
+
+ context 'when incident label already exists' do
+ let!(:label) { create(:label, project: project, title: label_title) }
+
+ it 'does not create new labels' do
+ expect { create_incident }.not_to change(Label, :count)
+ end
+ end
+ end
+
+ context 'when incident has no title' do
+ let(:title) { '' }
+
+ it 'does not create an issue' do
+ expect { create_incident }.not_to change(Issue, :count)
+ end
+
+ it 'responds with errors' do
+ expect(create_incident).to be_error
+ expect(create_incident.message).to eq("Title can't be blank")
+ end
+
+ it 'result payload contains an Issue object' do
+ expect(create_incident.payload[:issue]).to be_kind_of(Issue)
+ end
+ end
+ end
+end
diff --git a/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb b/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb
index cf43ed2411d..73ad0532e07 100644
--- a/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb
+++ b/spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb
@@ -12,84 +12,63 @@ RSpec.describe IncidentManagement::PagerDuty::CreateIncidentIssueService do
subject(:execute) { described_class.new(project, incident_payload).execute }
describe '#execute' do
- context 'when pagerduty_webhook feature enabled' do
- before do
- stub_feature_flags(pagerduty_webhook: project)
- end
+ context 'when PagerDuty webhook setting is active' do
+ let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: true) }
- context 'when PagerDuty webhook setting is active' do
- let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: true) }
-
- context 'when issue can be created' do
- it 'creates a new issue' do
- expect { execute }.to change(Issue, :count).by(1)
- end
-
- it 'responds with success' do
- response = execute
-
- expect(response).to be_success
- expect(response.payload[:issue]).to be_kind_of(Issue)
- end
-
- it 'the issue author is Alert bot' do
- expect(execute.payload[:issue].author).to eq(User.alert_bot)
- end
-
- it 'issue has a correct title' do
- expect(execute.payload[:issue].title).to eq(incident_payload['title'])
- end
-
- it 'issue has a correct description' do
- markdown_line_break = ' '
-
- expect(execute.payload[:issue].description).to eq(
- <<~MARKDOWN.chomp
- **Incident:** [My new incident](https://webdemo.pagerduty.com/incidents/PRORDTY)#{markdown_line_break}
- **Incident number:** 33#{markdown_line_break}
- **Urgency:** high#{markdown_line_break}
- **Status:** triggered#{markdown_line_break}
- **Incident key:** #{markdown_line_break}
- **Created at:** 26 September 2017, 3:14PM (UTC)#{markdown_line_break}
- **Assignees:** [Laura Haley](https://webdemo.pagerduty.com/users/P553OPV)#{markdown_line_break}
- **Impacted services:** [Production XDB Cluster](https://webdemo.pagerduty.com/services/PN49J75)
- MARKDOWN
- )
- end
+ context 'when issue can be created' do
+ it 'creates a new issue' do
+ expect { execute }.to change(Issue, :count).by(1)
end
- context 'when the payload does not contain a title' do
- let(:incident_payload) { {} }
+ it 'responds with success' do
+ response = execute
+
+ expect(response).to be_success
+ expect(response.payload[:issue]).to be_kind_of(Issue)
+ end
- it 'does not create a GitLab issue' do
- expect { execute }.not_to change(Issue, :count)
- end
+ it 'the issue author is Alert bot' do
+ expect(execute.payload[:issue].author).to eq(User.alert_bot)
+ end
- it 'responds with error' do
- expect(execute).to be_error
- expect(execute.message).to eq("Title can't be blank")
- end
+ it 'issue has a correct title' do
+ expect(execute.payload[:issue].title).to eq(incident_payload['title'])
+ end
+
+ it 'issue has a correct description' do
+ markdown_line_break = ' '
+
+ expect(execute.payload[:issue].description).to eq(
+ <<~MARKDOWN.chomp
+ **Incident:** [My new incident](https://webdemo.pagerduty.com/incidents/PRORDTY)#{markdown_line_break}
+ **Incident number:** 33#{markdown_line_break}
+ **Urgency:** high#{markdown_line_break}
+ **Status:** triggered#{markdown_line_break}
+ **Incident key:** #{markdown_line_break}
+ **Created at:** 26 September 2017, 3:14PM (UTC)#{markdown_line_break}
+ **Assignees:** [Laura Haley](https://webdemo.pagerduty.com/users/P553OPV)#{markdown_line_break}
+ **Impacted services:** [Production XDB Cluster](https://webdemo.pagerduty.com/services/PN49J75)
+ MARKDOWN
+ )
end
end
- context 'when PagerDuty webhook setting is not active' do
- let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }
+ context 'when the payload does not contain a title' do
+ let(:incident_payload) { {} }
it 'does not create a GitLab issue' do
expect { execute }.not_to change(Issue, :count)
end
- it 'responds with forbidden' do
+ it 'responds with error' do
expect(execute).to be_error
- expect(execute.http_status).to eq(:forbidden)
+ expect(execute.message).to eq("Title can't be blank")
end
end
end
- context 'when pagerduty_webhook feature disabled' do
- before do
- stub_feature_flags(pagerduty_webhook: false)
- end
+ context 'when PagerDuty webhook setting is not active' do
+ let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }
it 'does not create a GitLab issue' do
expect { execute }.not_to change(Issue, :count)
diff --git a/spec/services/incident_management/pager_duty/process_webhook_service_spec.rb b/spec/services/incident_management/pager_duty/process_webhook_service_spec.rb
index 11ce8388427..4c8aebe5fe2 100644
--- a/spec/services/incident_management/pager_duty/process_webhook_service_spec.rb
+++ b/spec/services/incident_management/pager_duty/process_webhook_service_spec.rb
@@ -19,92 +19,68 @@ RSpec.describe IncidentManagement::PagerDuty::ProcessWebhookService do
subject(:execute) { described_class.new(project, nil, webhook_payload).execute(token) }
- context 'when pagerduty_webhook feature is enabled' do
- before do
- stub_feature_flags(pagerduty_webhook: project)
- end
-
- context 'when PagerDuty webhook setting is active' do
- let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: true) }
-
- context 'when token is valid' do
- let(:token) { incident_management_setting.pagerduty_token }
+ context 'when PagerDuty webhook setting is active' do
+ let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: true) }
- context 'when webhook payload has acceptable size' do
- it 'responds with Accepted' do
- result = execute
+ context 'when token is valid' do
+ let(:token) { incident_management_setting.pagerduty_token }
- expect(result).to be_success
- expect(result.http_status).to eq(:accepted)
- end
-
- it 'processes issues' do
- incident_payload = ::PagerDuty::WebhookPayloadParser.call(webhook_payload).first['incident']
-
- expect(::IncidentManagement::PagerDuty::ProcessIncidentWorker)
- .to receive(:perform_async)
- .with(project.id, incident_payload)
- .once
+ context 'when webhook payload has acceptable size' do
+ it 'responds with Accepted' do
+ result = execute
- execute
- end
+ expect(result).to be_success
+ expect(result.http_status).to eq(:accepted)
end
- context 'when webhook payload is too big' do
- let(:deep_size) { instance_double(Gitlab::Utils::DeepSize, valid?: false) }
-
- before do
- allow(Gitlab::Utils::DeepSize)
- .to receive(:new)
- .with(webhook_payload, max_size: described_class::PAGER_DUTY_PAYLOAD_SIZE_LIMIT)
- .and_return(deep_size)
- end
+ it 'processes issues' do
+ incident_payload = ::PagerDuty::WebhookPayloadParser.call(webhook_payload).first['incident']
- it 'responds with Bad Request' do
- result = execute
+ expect(::IncidentManagement::PagerDuty::ProcessIncidentWorker)
+ .to receive(:perform_async)
+ .with(project.id, incident_payload)
+ .once
- expect(result).to be_error
- expect(result.http_status).to eq(:bad_request)
- end
-
- it_behaves_like 'does not process incidents'
+ execute
end
+ end
- context 'when webhook payload is blank' do
- let(:webhook_payload) { nil }
+ context 'when webhook payload is too big' do
+ let(:deep_size) { instance_double(Gitlab::Utils::DeepSize, valid?: false) }
- it 'responds with Accepted' do
- result = execute
+ before do
+ allow(Gitlab::Utils::DeepSize)
+ .to receive(:new)
+ .with(webhook_payload, max_size: described_class::PAGER_DUTY_PAYLOAD_SIZE_LIMIT)
+ .and_return(deep_size)
+ end
- expect(result).to be_success
- expect(result.http_status).to eq(:accepted)
- end
+ it 'responds with Bad Request' do
+ result = execute
- it_behaves_like 'does not process incidents'
+ expect(result).to be_error
+ expect(result.http_status).to eq(:bad_request)
end
+
+ it_behaves_like 'does not process incidents'
end
- context 'when token is invalid' do
- let(:token) { 'invalid-token' }
+ context 'when webhook payload is blank' do
+ let(:webhook_payload) { nil }
- it 'responds with Unauthorized' do
+ it 'responds with Accepted' do
result = execute
- expect(result).to be_error
- expect(result.http_status).to eq(:unauthorized)
+ expect(result).to be_success
+ expect(result.http_status).to eq(:accepted)
end
it_behaves_like 'does not process incidents'
end
end
- context 'when both tokens are nil' do
- let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }
- let(:token) { nil }
-
- before do
- incident_management_setting.update_column(:pagerduty_active, true)
- end
+ context 'when token is invalid' do
+ let(:token) { 'invalid-token' }
it 'responds with Unauthorized' do
result = execute
@@ -115,25 +91,28 @@ RSpec.describe IncidentManagement::PagerDuty::ProcessWebhookService do
it_behaves_like 'does not process incidents'
end
+ end
- context 'when PagerDuty webhook setting is not active' do
- let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }
+ context 'when both tokens are nil' do
+ let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }
+ let(:token) { nil }
- it 'responds with Forbidden' do
- result = execute
+ before do
+ incident_management_setting.update_column(:pagerduty_active, true)
+ end
- expect(result).to be_error
- expect(result.http_status).to eq(:forbidden)
- end
+ it 'responds with Unauthorized' do
+ result = execute
- it_behaves_like 'does not process incidents'
+ expect(result).to be_error
+ expect(result.http_status).to eq(:unauthorized)
end
+
+ it_behaves_like 'does not process incidents'
end
- context 'when pagerduty_webhook feature is disabled' do
- before do
- stub_feature_flags(pagerduty_webhook: false)
- end
+ context 'when PagerDuty webhook setting is not active' do
+ let_it_be(:incident_management_setting) { create(:project_incident_management_setting, project: project, pagerduty_active: false) }
it 'responds with Forbidden' do
result = execute