Commit 83b673e3 authored by Vitali Tatarintev's avatar Vitali Tatarintev

Add Create PagerDuty incident issue class

parent 007a6572
# frozen_string_literal: true
module IncidentManagement
module PagerDuty
class CreateIncidentIssueService < BaseService
def initialize(project, incident_payload)
super(project, User.alert_bot, incident_payload)
end
def execute
return forbidden unless webhook_available?
issue = create_issue
return error(issue.errors.full_messages.to_sentence, issue) unless issue.valid?
success(issue)
end
private
alias_method :incident_payload, :params
def create_issue
label_result = find_or_create_incident_label
# Create an unlabelled issue if we couldn't create the label
# due to a race condition.
# See https://gitlab.com/gitlab-org/gitlab-foss/issues/65042
extra_params = label_result.success? ? { label_ids: [label_result.payload[:label].id] } : {}
Issues::CreateService.new(
project,
current_user,
title: issue_title,
description: issue_description,
**extra_params
).execute
end
def webhook_available?
Feature.enabled?(:pagerduty_webhook, project)
end
def forbidden
ServiceResponse.error(message: 'Forbidden', http_status: :forbidden)
end
def find_or_create_incident_label
::IncidentManagement::CreateIncidentLabelService.new(project, current_user).execute
end
def issue_title
incident_payload['title']
end
def issue_description
markdown_line_break = ' '
<<~MARKDOWN.chomp
**Incident:** #{markdown_incident}#{markdown_line_break}
**Incident number:** #{incident_payload['incident_number']}#{markdown_line_break}
**Urgency:** #{incident_payload['urgency']}#{markdown_line_break}
**Status:** #{incident_payload['status']}#{markdown_line_break}
**Incident key:** #{incident_payload['incident_key']}#{markdown_line_break}
**Created at:** #{markdown_incident_created_at}#{markdown_line_break}
**Assignees:** #{markdown_assignees.join(', ')}#{markdown_line_break}
**Impacted services:** #{markdown_impacted_services.join(', ')}
MARKDOWN
end
def markdown_incident
"[#{incident_payload['title']}](#{incident_payload['url']})"
end
def incident_created_at
Time.parse(incident_payload['created_at'])
rescue
Time.current
end
def markdown_incident_created_at
incident_created_at.strftime('%d %B %Y, %-l:%M%p (%Z)')
end
def markdown_assignees
Array(incident_payload['assignees']).map do |assignee|
"[#{assignee['summary']}](#{assignee['url']})"
end
end
def markdown_impacted_services
Array(incident_payload['impacted_services']).map do |is|
"[#{is['summary']}](#{is['url']})"
end
end
def success(issue)
ServiceResponse.success(payload: { issue: issue })
end
def error(message, issue = nil)
ServiceResponse.error(payload: { issue: issue }, message: message)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe IncidentManagement::PagerDuty::CreateIncidentIssueService do
let_it_be(:project) { create(:project) }
let_it_be(:user) { User.alert_bot }
let(:webhook_payload) { Gitlab::Json.parse(fixture_file('pager_duty/webhook_incident_trigger.json')) }
let(:parsed_payload) { ::PagerDuty::WebhookPayloadParser.call(webhook_payload) }
let(:incident_payload) { parsed_payload.first['incident'] }
subject(:execute) { described_class.new(project, incident_payload).execute }
describe '#execute' do
context 'when pagerduty_webhook feature enabled' do
before do
stub_feature_flags(pagerduty_webhook: project)
end
context 'when issue can be created' do
it 'creates a new issue' do
expect { execute }.to change(Issue, :count).by(1)
end
it 'responds with success' do
response = execute
expect(response).to be_success
expect(response.payload[:issue]).to be_kind_of(Issue)
end
it 'the issue author is Alert bot' do
expect(execute.payload[:issue].author).to eq(User.alert_bot)
end
it 'issue has a correct title' do
expect(execute.payload[:issue].title).to eq(incident_payload['title'])
end
it 'issue has a correct description' do
markdown_line_break = ' '
expect(execute.payload[:issue].description).to eq(
<<~MARKDOWN.chomp
**Incident:** [My new incident](https://webdemo.pagerduty.com/incidents/PRORDTY)#{markdown_line_break}
**Incident number:** 33#{markdown_line_break}
**Urgency:** high#{markdown_line_break}
**Status:** triggered#{markdown_line_break}
**Incident key:** #{markdown_line_break}
**Created at:** 26 September 2017, 3:14PM (UTC)#{markdown_line_break}
**Assignees:** [Laura Haley](https://webdemo.pagerduty.com/users/P553OPV)#{markdown_line_break}
**Impacted services:** [Production XDB Cluster](https://webdemo.pagerduty.com/services/PN49J75)
MARKDOWN
)
end
end
context 'when issue cannot be created' do
let(:incident_payload) { {} }
it 'responds with error' do
expect(execute).to be_error
expect(execute.message).to eq("Title can't be blank")
end
end
end
context 'when pagerduty_webhook feature disabled' do
before do
stub_feature_flags(pagerduty_webhook: false)
end
it 'does not create a GitLab issue' do
expect { execute }.not_to change(Issue, :count)
end
it 'responds with forbidden' do
expect(execute).to be_error
expect(execute.http_status).to eq(:forbidden)
end
end
end
end
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