Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-02-11 18:08:44 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-11 18:08:44 +0300
commitbcc77054ee9aefd1e332e04a4189390fd5a3112e (patch)
treee6e1908c310e4733038794e932196cae0d66ba9a /spec/services/incident_management
parent05b5c609cb8c260b10c2eb1b92b711dc82d32c3f (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/services/incident_management')
-rw-r--r--spec/services/incident_management/create_issue_service_spec.rb311
1 files changed, 311 insertions, 0 deletions
diff --git a/spec/services/incident_management/create_issue_service_spec.rb b/spec/services/incident_management/create_issue_service_spec.rb
new file mode 100644
index 00000000000..e720aafb897
--- /dev/null
+++ b/spec/services/incident_management/create_issue_service_spec.rb
@@ -0,0 +1,311 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe IncidentManagement::CreateIssueService do
+ let(:project) { create(:project, :repository, :private) }
+ let(:user) { User.alert_bot }
+ let(:service) { described_class.new(project, alert_payload) }
+ let(:alert_starts_at) { Time.now }
+ 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] }
+ let(:summary_separator) { "\n---\n\n" }
+
+ 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
+ let(:title) { 'incident' }
+ let(:color) { '#CC0033' }
+ let(:description) do
+ <<~DESCRIPTION.chomp
+ Denotes a disruption to IT services and \
+ the associated issues require immediate attention
+ DESCRIPTION
+ end
+
+ shared_examples 'existing label' do
+ it 'adds the existing label' do
+ expect { subject }.not_to change(Label, :count)
+
+ expect(issue.labels).to eq([label])
+ end
+ end
+
+ shared_examples 'new label' do
+ it 'adds newly created label' do
+ expect { subject }.to change(Label, :count).by(1)
+
+ label = project.reload.labels.last
+ expect(issue.labels).to eq([label])
+ expect(label.title).to eq(title)
+ expect(label.color).to eq(color)
+ expect(label.description).to eq(description)
+ end
+ end
+
+ context 'with predefined project label' do
+ it_behaves_like 'existing label' do
+ let!(:label) { create(:label, project: project, title: title) }
+ end
+ end
+
+ context 'with predefined group label' do
+ let(:project) { create(:project, group: group) }
+ let(:group) { create(:group) }
+
+ it_behaves_like 'existing label' do
+ let!(:label) { create(:group_label, group: group, title: title) }
+ end
+ end
+
+ context 'without label' do
+ it_behaves_like 'new label'
+ end
+
+ context 'with duplicate labels', issue: 'https://gitlab.com/gitlab-org/gitlab-foss/issues/65042' do
+ before do
+ # Replicate race condition to create duplicates
+ build(:label, project: project, title: title).save!(validate: false)
+ build(:label, project: project, title: title).save!(validate: false)
+ end
+
+ it 'create an issue without labels' do
+ # Verify we have duplicates
+ expect(project.labels.size).to eq(2)
+ expect(project.labels.map(&:title)).to all(eq(title))
+
+ message = <<~MESSAGE.chomp
+ Cannot create incident issue with labels ["#{title}"] for \
+ "#{project.full_name}": Labels is invalid.
+ Retrying without labels.
+ MESSAGE
+
+ expect(service)
+ .to receive(:log_info)
+ .with(message)
+
+ expect(subject).to include(status: :success)
+ expect(issue.labels).to be_empty
+ end
+ end
+ 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.now)
+ {
+ '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)
+ text.scan(summary_separator).size
+ end
+end