126 lines
3 KiB
Ruby
126 lines
3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
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 initialize(project, params, user = User.alert_bot)
|
|
super(project, user, params)
|
|
end
|
|
|
|
def execute(skip_settings_check: false)
|
|
return error_with('setting disabled') unless skip_settings_check || incident_management_setting.create_issue?
|
|
return error_with('invalid alert') unless alert.valid?
|
|
|
|
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-foss/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,
|
|
current_user,
|
|
title: issue_title,
|
|
description: issue_description,
|
|
**params
|
|
).execute
|
|
end
|
|
|
|
def issue_title
|
|
alert.full_title
|
|
end
|
|
|
|
def issue_description
|
|
horizontal_line = "\n\n---\n\n"
|
|
|
|
[
|
|
alert_summary,
|
|
alert_markdown,
|
|
issue_template_content
|
|
].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(current_user, project, **params)
|
|
.execute
|
|
end
|
|
|
|
def alert_summary
|
|
alert.issue_summary_markdown
|
|
end
|
|
|
|
def alert_markdown
|
|
alert.alert_markdown
|
|
end
|
|
|
|
def alert
|
|
strong_memoize(:alert) do
|
|
Gitlab::Alerting::Alert.new(project: project, payload: params).present
|
|
end
|
|
end
|
|
|
|
def issue_template_content
|
|
incident_management_setting.issue_template_content
|
|
end
|
|
|
|
def incident_management_setting
|
|
strong_memoize(:incident_management_setting) do
|
|
project.incident_management_setting ||
|
|
project.build_incident_management_setting
|
|
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}})
|
|
|
|
error(message)
|
|
end
|
|
end
|
|
end
|