Commit b75fff51 authored by Douglas Barbosa Alexandre's avatar Douglas Barbosa Alexandre

Merge branch 'pl-label-incident-issues' into 'master'

Add `Incident` label to issues created by the Alert Bot

See merge request gitlab-org/gitlab-ee!14705
parents 0498422d df173db9
......@@ -327,6 +327,8 @@ Once enabled, an issue will be opened automatically when an alert is triggered w
To further customize the issue, you can add labels, mentions, or any other supported [quick action](../quick_actions.md) in the selected issue template, which will apply to all incidents. To limit quick actions or other information to only specific types of alerts, use the `annotations/gitlab_incident_markdown` field.
Since [version 12.2](https://gitlab.com/gitlab-org/gitlab-ce/issues/63373), GitLab will tag each incident issue with the `incident` label automatically. If the label does not yet exist, it will be created automatically as well.
If the metric exceeds the threshold of the alert for over 5 minutes, an email will be sent to all [Maintainers and Owners](../../permissions.md#project-members-permissions) of the project.
## Determining the performance impact of a merge
......
......@@ -4,21 +4,48 @@ module IncidentManagement
class CreateIssueService < BaseService
include Gitlab::Utils::StrongMemoize
INCIDENT_LABEL = {
title: 'incident',
color: '#CC0033',
description: <<~DESCRIPTION.chomp
Denotes a disruption to IT services and \
the associated issues require immediate attention
DESCRIPTION
}.freeze
def execute
return error_with('setting disabled') unless incident_management_setting.create_issue?
return error_with('invalid alert') unless alert.valid?
success(issue: create_issue)
issue = create_issue
return error_with(issue_errors(issue)) unless issue.valid?
success(issue: issue)
end
private
def create_issue
issue = do_create_issue(label_ids: issue_label_ids)
# Create an unlabelled issue if we couldn't create the issue
# due to labels errors.
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/65042
if issue.errors.include?(:labels)
log_label_error(issue)
issue = do_create_issue
end
issue
end
def do_create_issue(**params)
Issues::CreateService.new(
project,
issue_author,
title: issue_title,
description: issue_description
description: issue_description,
**params
).execute
end
......@@ -42,6 +69,18 @@ module IncidentManagement
].compact.join(horizontal_line)
end
def issue_label_ids
[
find_or_create_label(**INCIDENT_LABEL)
].compact.map(&:id)
end
def find_or_create_label(**params)
Labels::FindOrCreateService
.new(issue_author, project, **params)
.execute
end
def alert_summary
alert.issue_summary_markdown
end
......@@ -67,6 +106,19 @@ module IncidentManagement
end
end
def issue_errors(issue)
issue.errors.full_messages.to_sentence
end
def log_label_error(issue)
log_info <<~TEXT.chomp
Cannot create incident issue with labels \
#{issue.labels.map(&:title).inspect} \
for "#{project.full_name}": #{issue.errors.full_messages.to_sentence}.
Retrying without labels.
TEXT
end
def error_with(message)
log_error(%{Cannot create incident issue for "#{project.full_name}": #{message}})
......
---
title: Add `Incident` label to issues created by the Alert Bot
merge_request: 14705
author:
type: added
......@@ -3,7 +3,7 @@
require 'spec_helper'
describe IncidentManagement::CreateIssueService do
let(:project) { create(:project, :repository) }
let(:project) { create(:project, :repository, :private) }
let(:service) { described_class.new(project, nil, alert_payload) }
let(:alert_starts_at) { Time.now }
let(:alert_title) { 'TITLE' }
......@@ -45,6 +45,26 @@ describe IncidentManagement::CreateIssueService do
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' }
......@@ -177,6 +197,83 @@ describe IncidentManagement::CreateIssueService do
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-ce/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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment