Commit 37eef3ee authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch 'support-annotation-template' into 'master'

Support an alert template field to allow for incident customization

See merge request gitlab-org/gitlab-ee!14710
parents 1711be3b cc7a585e
...@@ -323,8 +323,9 @@ Once enabled, an issue will be opened automatically when an alert is triggered w ...@@ -323,8 +323,9 @@ Once enabled, an issue will be opened automatically when an alert is triggered w
- `starts_at`: Alert start time via `startsAt` - `starts_at`: Alert start time via `startsAt`
- `full_query`: Alert query extracted from `generatorURL` - `full_query`: Alert query extracted from `generatorURL`
- Optional list of attached annotations extracted from `annotations/*` - Optional list of attached annotations extracted from `annotations/*`
- Alert [GFM](https://docs.gitlab.com/ee/user/markdown.html#gitlab-flavored-markdown-gfm): GitLab Flavored Markdown from `annotations/gitlab_incident_markdown`
To further customize the issue, you can add labels, mentions, or any other supported [quick action](../quick_actions.md) in the selected issue template. 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.
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. 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.
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
module Projects module Projects
module Prometheus module Prometheus
class AlertPresenter < Gitlab::View::Presenter::Delegated class AlertPresenter < Gitlab::View::Presenter::Delegated
RESERVED_ANNOTATIONS = %w(gitlab_incident_markdown).freeze
def full_title def full_title
[environment_name, alert_title].compact.join(': ') [environment_name, alert_title].compact.join(': ')
end end
...@@ -64,6 +66,7 @@ module Projects ...@@ -64,6 +66,7 @@ module Projects
def annotation_list def annotation_list
strong_memoize(:annotation_list) do strong_memoize(:annotation_list) do
annotations annotations
.reject { |annotation| RESERVED_ANNOTATIONS.include?(annotation.label) }
.map { |annotation| bullet(annotation.label, annotation.value) } .map { |annotation| bullet(annotation.label, annotation.value) }
.join("\n") .join("\n")
end end
......
...@@ -33,17 +33,23 @@ module IncidentManagement ...@@ -33,17 +33,23 @@ module IncidentManagement
end end
def issue_description def issue_description
return alert_summary unless issue_template_content
horizontal_line = "\n---\n\n" horizontal_line = "\n---\n\n"
alert_summary + horizontal_line + issue_template_content [
alert_summary,
alert_markdown,
issue_template_content
].compact.join(horizontal_line)
end end
def alert_summary def alert_summary
alert.issue_summary_markdown alert.issue_summary_markdown
end end
def alert_markdown
alert.alert_markdown
end
def alert def alert
strong_memoize(:alert) do strong_memoize(:alert) do
Gitlab::Alerting::Alert.new(project: project, payload: params).present Gitlab::Alerting::Alert.new(project: project, payload: params).present
......
---
title: Support an alert template field to allow for incident customization
merge_request: 14710
author:
type: added
...@@ -49,6 +49,12 @@ module Gitlab ...@@ -49,6 +49,12 @@ module Gitlab
end end
end end
def alert_markdown
strong_memoize(:alert_markdown) do
parse_alert_markdown_from_payload
end
end
def valid? def valid?
project && title && starts_at project && title && starts_at
end end
...@@ -105,6 +111,10 @@ module Gitlab ...@@ -105,6 +111,10 @@ module Gitlab
Rack::Utils.parse_query(uri.query).fetch('g0.expr') Rack::Utils.parse_query(uri.query).fetch('g0.expr')
rescue URI::InvalidURIError, KeyError rescue URI::InvalidURIError, KeyError
end end
def parse_alert_markdown_from_payload
payload&.dig('annotations', 'gitlab_incident_markdown')
end
end end
end end
end end
...@@ -189,6 +189,12 @@ describe Gitlab::Alerting::Alert do ...@@ -189,6 +189,12 @@ describe Gitlab::Alerting::Alert do
end end
end end
describe '#alert_markdown' do
subject { alert.alert_markdown }
it_behaves_like 'parse payload', 'annotations/gitlab_incident_markdown'
end
describe '#valid?' do describe '#valid?' do
before do before do
payload.update( payload.update(
......
...@@ -28,7 +28,7 @@ describe IncidentManagement::CreateIssueService do ...@@ -28,7 +28,7 @@ describe IncidentManagement::CreateIssueService do
context 'when create_issue enabled' do context 'when create_issue enabled' do
let(:issue) { subject[:issue] } let(:issue) { subject[:issue] }
let(:summary_separator) { "---\n\n" } let(:summary_separator) { "\n---\n\n" }
before do before do
setting.update!(create_issue: true) setting.update!(create_issue: true)
...@@ -41,25 +41,20 @@ describe IncidentManagement::CreateIssueService do ...@@ -41,25 +41,20 @@ describe IncidentManagement::CreateIssueService do
expect(issue.author).to eq(User.alert_bot) expect(issue.author).to eq(User.alert_bot)
expect(issue.title).to eq(alert_title) expect(issue.title).to eq(alert_title)
expect(issue.description).to include(alert_presenter.issue_summary_markdown) expect(issue.description).to include(alert_presenter.issue_summary_markdown)
expect(issue.description).not_to include(summary_separator) expect(separator_count(issue.description)).to eq 0
end end
end end
context 'with issue_template_content' do shared_examples 'GFM template' do
before do
create_issue_template('bug', issue_template_content)
setting.update!(issue_template_key: 'bug')
end
context 'plain content' do context 'plain content' do
let(:issue_template_content) { 'some content' } let(:template_content) { 'some content' }
it 'creates an issue appending issue template' do it 'creates an issue appending issue template' do
expect(subject).to include(status: :success) expect(subject).to include(status: :success)
expect(issue.description).to include(alert_presenter.issue_summary_markdown) expect(issue.description).to include(alert_presenter.issue_summary_markdown)
expect(issue.description).to include(summary_separator) expect(separator_count(issue.description)).to eq 1
expect(issue.description).to include(issue_template_content) expect(issue.description).to include(template_content)
end end
end end
...@@ -67,7 +62,7 @@ describe IncidentManagement::CreateIssueService do ...@@ -67,7 +62,7 @@ describe IncidentManagement::CreateIssueService do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:plain_text) { 'some content' } let(:plain_text) { 'some content' }
let(:issue_template_content) do let(:template_content) do
<<~CONTENT <<~CONTENT
#{plain_text} #{plain_text}
/due tomorrow /due tomorrow
...@@ -87,6 +82,40 @@ describe IncidentManagement::CreateIssueService do ...@@ -87,6 +82,40 @@ describe IncidentManagement::CreateIssueService do
expect(issue.assignees).to eq([user]) expect(issue.assignees).to eq([user])
end end
end end
end
context 'with gitlab_incident_markdown' do
let(:alert_annotations) do
{ title: alert_title, gitlab_incident_markdown: template_content }
end
it_behaves_like 'GFM template'
end
context 'with issue_template_content' do
before do
create_issue_template('bug', template_content)
setting.update!(issue_template_key: 'bug')
end
it_behaves_like 'GFM template'
context 'and gitlab_incident_markdown' do
let(:template_content) { 'plain text'}
let(:alt_template) { 'alternate text' }
let(:alert_annotations) do
{ title: alert_title, gitlab_incident_markdown: alt_template }
end
it 'includes both templates' do
expect(subject).to include(status: :success)
expect(issue.description).to include(alert_presenter.issue_summary_markdown)
expect(issue.description).to include(template_content)
expect(issue.description).to include(alt_template)
expect(separator_count(issue.description)).to eq 2
end
end
private private
...@@ -121,7 +150,7 @@ describe IncidentManagement::CreateIssueService do ...@@ -121,7 +150,7 @@ describe IncidentManagement::CreateIssueService do
expect(issue.title).to include(query_title) expect(issue.title).to include(query_title)
expect(issue.title).to include('for 5 minutes') expect(issue.title).to include('for 5 minutes')
expect(issue.description).to include(alert_presenter.issue_summary_markdown) expect(issue.description).to include(alert_presenter.issue_summary_markdown)
expect(issue.description).not_to include(summary_separator) expect(separator_count(issue.description)).to eq 0
end end
end end
...@@ -177,4 +206,8 @@ describe IncidentManagement::CreateIssueService do ...@@ -177,4 +206,8 @@ describe IncidentManagement::CreateIssueService do
def error_message(message) def error_message(message)
%{Cannot create incident issue for "#{project.full_name}": #{message}} %{Cannot create incident issue for "#{project.full_name}": #{message}}
end end
def separator_count(text)
text.scan(summary_separator).size
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