Commit de2f1195 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch '330281-create-issue-escalation-status' into 'master'

Handle syncing alert escalation status to incident

See merge request gitlab-org/gitlab!75176
parents 61cd96ec 06efa9fa
......@@ -102,3 +102,5 @@ module IncidentManagement
end
end
end
::IncidentManagement::Escalatable.prepend_mod
......@@ -188,6 +188,10 @@ module Issuable
incident?
end
def supports_escalation?
incident?
end
def incident?
is_a?(Issue) && super
end
......
......@@ -7,8 +7,11 @@ module IncidentManagement
self.table_name = 'incident_management_issuable_escalation_statuses'
belongs_to :issue
has_one :project, through: :issue, inverse_of: :incident_management_issuable_escalation_status
validates :issue, presence: true, uniqueness: true
delegate :project, to: :issue
end
end
......
# frozen_string_literal: true
module IncidentManagement
module IssuableEscalationStatuses
class CreateService < BaseService
def initialize(issue)
@issue = issue
@alert = issue.alert_management_alert
end
def execute
escalation_status = ::IncidentManagement::IssuableEscalationStatus.new(issue: issue, **alert_params)
if escalation_status.save
ServiceResponse.success(payload: { escalation_status: escalation_status })
else
ServiceResponse.error(message: escalation_status.errors&.full_messages)
end
end
private
attr_reader :issue, :alert
def alert_params
return {} unless alert
{
status_event: alert.status_event_for(alert.status_name)
}
end
end
end
end
IncidentManagement::IssuableEscalationStatuses::CreateService.prepend_mod
......@@ -50,6 +50,7 @@ module Issues
def after_create(issue)
user_agent_detail_service.create
resolve_discussions_with_issue(issue)
create_escalation_status(issue)
super
end
......@@ -80,6 +81,10 @@ module Issues
attr_reader :spam_params
def create_escalation_status(issue)
::IncidentManagement::IssuableEscalationStatuses::CreateService.new(issue).execute if issue.supports_escalation?
end
def user_agent_detail_service
UserAgentDetailService.new(spammable: @issue, spam_params: spam_params)
end
......
# frozen_string_literal: true
module EE
module IncidentManagement
module Escalatable
extend ActiveSupport::Concern
def escalation_policy
project.incident_management_escalation_policies.first
end
end
end
end
......@@ -48,10 +48,6 @@ module EE
incident?
end
def supports_escalation?
incident?
end
def supports_iterations?
false
end
......
# frozen_string_literal: true
module EE
module IncidentManagement
module IssuableEscalationStatuses
module CreateService
extend ::Gitlab::Utils::Override
override :alert_params
def alert_params
return super unless issue.escalation_policies_available?
return super unless alert&.escalation_policy
super.merge(
policy: alert.escalation_policy,
escalations_started_at: alert.created_at
)
end
end
end
end
end
......@@ -80,4 +80,20 @@ RSpec.describe AlertManagement::Alert do
end
end
end
describe '#escalation_policy' do
let(:alert) { create(:alert_management_alert, project: project) }
subject { alert.escalation_policy }
it { is_expected.to eq(nil) }
context 'when escalation policy exists on the project' do
it 'returns the projects first (only) escalation policy' do
policy = create(:incident_management_escalation_policy, project: project)
expect(subject).to eq(policy)
end
end
end
end
......@@ -67,4 +67,20 @@ RSpec.describe IncidentManagement::IssuableEscalationStatus do
end
end
end
describe '#escalation_policy' do
let_it_be(:escalation_status, reload: true) { create(:incident_management_issuable_escalation_status) }
subject { escalation_status.escalation_policy }
it { is_expected.to eq(nil) }
context 'when escalation policy exists on the project' do
it 'returns the projects first (only) escalation policy' do
policy = create(:incident_management_escalation_policy, project: escalation_status.issue.project)
expect(subject).to eq(policy)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe IncidentManagement::IssuableEscalationStatuses::CreateService do
let_it_be(:project) { create(:project) }
let(:incident) { create(:incident, project: project) }
let(:service) { described_class.new(incident) }
let(:alert_status_name) { :triggered }
subject(:execute) { service.execute }
before do
stub_licensed_features(oncall_schedules: true, escalation_policies: true)
stub_feature_flags(incident_escalations: true)
end
shared_examples 'creates an escalation status for the incident with no policy set' do
specify do
expect { execute }.to change { incident.reload.incident_management_issuable_escalation_status }.from(nil)
status = incident.incident_management_issuable_escalation_status
expect(status.policy).to eq(nil)
expect(status.escalations_started_at).to eq(nil)
expect(status.status_name).to eq(alert_status_name)
end
end
it_behaves_like 'creates an escalation status for the incident with no policy set'
context 'when incident is associated to an alert' do
let(:alert) { create(:alert_management_alert, :acknowledged, project: project) }
let(:incident) { create(:incident, alert_management_alert: alert, project: project) }
let(:alert_status_name) { alert.status_name }
context 'when no policy exists' do
it_behaves_like 'creates an escalation status for the incident with no policy set'
end
context 'when policy exists' do
let_it_be(:policy) { create(:incident_management_escalation_policy, project: project) }
it 'creates an escalation status with the policy info' do
expect { execute }.to change { incident.reload.incident_management_issuable_escalation_status }
status = incident.incident_management_issuable_escalation_status
expect(status.policy).to eq(policy)
expect(status.escalations_started_at).to be_like_time(alert.created_at)
expect(status.status_name).to eq(alert.status_name)
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(incident_escalations: false)
end
it_behaves_like 'creates an escalation status for the incident with no policy set'
end
end
end
end
......@@ -32,7 +32,7 @@ RSpec.shared_examples 'IncidentManagement::PendingEscalation model' do
let_it_be(:three_days_ago_escalation) { create_escalation(rule: rule, process_at: 3.days.ago) }
let_it_be(:future_escalation) { create_escalation(rule: rule, process_at: 5.minutes.from_now) }
it { is_expected.to eq [three_weeks_ago_escalation, three_days_ago_escalation] }
it { is_expected.to match_array [three_weeks_ago_escalation, three_days_ago_escalation] }
end
end
......
......@@ -11,6 +11,7 @@ RSpec.describe IncidentManagement::IssuableEscalationStatus do
describe 'associations' do
it { is_expected.to belong_to(:issue) }
it { is_expected.to have_one(:project).through(:issue) }
end
describe 'validatons' do
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe IncidentManagement::IssuableEscalationStatuses::CreateService do
let_it_be(:project) { create(:project) }
let(:incident) { create(:incident, project: project) }
let(:service) { described_class.new(incident) }
subject(:execute) { service.execute}
it 'creates an escalation status for the incident with no policy set' do
expect { execute }.to change { incident.reload.incident_management_issuable_escalation_status }.from(nil)
status = incident.incident_management_issuable_escalation_status
expect(status.policy_id).to eq(nil)
expect(status.escalations_started_at).to eq(nil)
expect(status.status_name).to eq(:triggered)
end
context 'existing escalation status' do
let!(:existing_status) { create(:incident_management_issuable_escalation_status, issue: incident) }
it 'exits without changing anything' do
expect { execute }.not_to change { incident.reload.incident_management_issuable_escalation_status }
end
end
end
......@@ -108,6 +108,13 @@ RSpec.describe Issues::CreateService do
.to change { Label.where(incident_label_attributes).count }.by(1)
end
it 'calls IncidentManagement::Incidents::CreateEscalationStatusService' do
expect_next(::IncidentManagement::IssuableEscalationStatuses::CreateService, a_kind_of(Issue))
.to receive(:execute)
issue
end
context 'when invalid' do
before do
opts.merge!(title: '')
......
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