gitlab-org--gitlab-foss/app/services/alert_management/create_alert_issue_service.rb

119 lines
2.7 KiB
Ruby

# frozen_string_literal: true
module AlertManagement
class CreateAlertIssueService
include Gitlab::Utils::StrongMemoize
INCIDENT_LABEL = ::IncidentManagement::CreateIssueService::INCIDENT_LABEL
# @param alert [AlertManagement::Alert]
# @param user [User]
def initialize(alert, user)
@alert = alert
@user = user
end
def execute
return error_no_permissions unless allowed?
return error_issue_already_exists if alert.issue
result = create_issue
@issue = result.payload[:issue]
return error(result.message) if result.error?
return error(alert.errors.full_messages.to_sentence) unless update_alert_issue_id
success
end
private
attr_reader :alert, :user, :issue
delegate :project, to: :alert
def allowed?
user.can?(:create_issue, project)
end
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
return error(issue_errors(issue)) unless issue.valid?
@issue = issue
success
end
def update_alert_issue_id
alert.update(issue_id: issue.id)
end
def success
ServiceResponse.success(payload: { issue: issue })
end
def error(message)
ServiceResponse.error(payload: { issue: issue }, message: message)
end
def error_issue_already_exists
error(_('An issue already exists'))
end
def error_no_permissions
error(_('You have no permissions'))
end
def do_create_issue(**params)
Issues::CreateService.new(
project,
user,
title: alert_presenter.title,
description: alert_presenter.issue_description,
**params
).execute
end
def alert_presenter
strong_memoize(:alert_presenter) do
alert.present
end
end
def issue_label_ids
[
find_or_create_label(**INCIDENT_LABEL)
].compact.map(&:id)
end
def find_or_create_label(**params)
Labels::FindOrCreateService
.new(user, project, **params)
.execute
end
def issue_errors(issue)
issue.errors.full_messages.to_sentence
end
def log_label_error(issue)
Gitlab::AppLogger.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
end
end