Skip to content
Snippets Groups Projects
Commit bcc77054 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 05b5c609
No related branches found
No related tags found
No related merge requests found
# frozen_string_literal: true
require 'spec_helper'
describe IncidentManagement::ProjectIncidentManagementSetting do
let_it_be(:project) { create(:project, :repository, create_templates: :issue) }
describe 'Associations' do
it { is_expected.to belong_to(:project) }
end
describe 'Validations' do
describe 'validate issue_template_exists' do
subject { build(:project_incident_management_setting, project: project) }
context 'with create_issue enabled' do
before do
subject.create_issue = true
end
context 'with valid issue_template_key' do
before do
subject.issue_template_key = 'bug'
end
it { is_expected.to be_valid }
end
context 'with empty issue_template_key' do
before do
subject.issue_template_key = ''
end
it { is_expected.to be_valid }
end
context 'with nil issue_template_key' do
before do
subject.issue_template_key = nil
end
it { is_expected.to be_valid }
end
context 'with invalid issue_template_key' do
before do
subject.issue_template_key = 'unknown'
end
it { is_expected.to be_invalid }
it 'returns error' do
subject.valid?
expect(subject.errors[:issue_template_key]).to eq(['not found'])
end
end
end
context 'with create_issue disabled' do
before do
subject.create_issue = false
end
context 'with unknown issue_template_key' do
before do
subject.issue_template_key = 'unknown'
end
it { is_expected.to be_valid }
end
end
end
end
describe '#issue_template_content' do
subject { build(:project_incident_management_setting, project: project) }
shared_examples 'no content' do
it 'returns no content' do
expect(subject.issue_template_content).to be_nil
end
end
context 'with valid issue_template_key' do
before do
subject.issue_template_key = 'bug'
end
it 'returns issue content' do
expect(subject.issue_template_content).to eq('something valid')
end
end
context 'with unknown issue_template_key' do
before do
subject.issue_template_key = 'unknown'
end
it_behaves_like 'no content'
end
context 'without issue_template_key' do
before do
subject.issue_template_key = nil
end
it_behaves_like 'no content'
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe IncidentManagement::CreateIssueService do
let(:project) { create(:project, :repository, :private) }
let(:user) { User.alert_bot }
let(:service) { described_class.new(project, alert_payload) }
let(:alert_starts_at) { Time.now }
let(:alert_title) { 'TITLE' }
let(:alert_annotations) { { title: alert_title } }
let(:alert_payload) do
build_alert_payload(
annotations: alert_annotations,
starts_at: alert_starts_at
)
end
let(:alert_presenter) do
Gitlab::Alerting::Alert.new(project: project, payload: alert_payload).present
end
let!(:setting) do
create(:project_incident_management_setting, project: project)
end
subject { service.execute }
context 'when create_issue enabled' do
let(:issue) { subject[:issue] }
let(:summary_separator) { "\n---\n\n" }
before do
setting.update!(create_issue: true)
end
context 'without issue_template_content' do
it 'creates an issue with alert summary only' do
expect(subject).to include(status: :success)
expect(issue.author).to eq(user)
expect(issue.title).to eq(alert_title)
expect(issue.description).to include(alert_presenter.issue_summary_markdown.strip)
expect(separator_count(issue.description)).to eq 0
end
end
context 'with erroneous issue service' do
let(:invalid_issue) do
build(:issue, project: project, title: nil).tap(&:valid?)
end
let(:issue_error) { invalid_issue.errors.full_messages.to_sentence }
it 'returns and logs the issue error' do
expect_next_instance_of(Issues::CreateService) do |issue_service|
expect(issue_service).to receive(:execute).and_return(invalid_issue)
end
expect(service)
.to receive(:log_error)
.with(error_message(issue_error))
expect(subject).to include(status: :error, message: issue_error)
end
end
shared_examples 'GFM template' do
context 'plain content' do
let(:template_content) { 'some content' }
it 'creates an issue appending issue template' do
expect(subject).to include(status: :success)
expect(issue.description).to include(alert_presenter.issue_summary_markdown)
expect(separator_count(issue.description)).to eq 1
expect(issue.description).to include(template_content)
end
end
context 'quick actions' do
let(:user) { create(:user) }
let(:plain_text) { 'some content' }
let(:template_content) do
<<~CONTENT
#{plain_text}
/due tomorrow
/assign @#{user.username}
CONTENT
end
before do
project.add_maintainer(user)
end
it 'creates an issue interpreting quick actions' do
expect(subject).to include(status: :success)
expect(issue.description).to include(plain_text)
expect(issue.due_date).to be_present
expect(issue.assignees).to eq([user])
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
def create_issue_template(name, content)
project.repository.create_file(
project.creator,
".gitlab/issue_templates/#{name}.md",
content,
message: 'message',
branch_name: 'master'
)
end
end
context 'with gitlab alert' do
let(:gitlab_alert) { create(:prometheus_alert, project: project) }
before do
alert_payload['labels'] = {
'gitlab_alert_id' => gitlab_alert.prometheus_metric_id.to_s
}
end
it 'creates an issue' do
query_title = "#{gitlab_alert.title} #{gitlab_alert.computed_operator} #{gitlab_alert.threshold}"
expect(subject).to include(status: :success)
expect(issue.author).to eq(user)
expect(issue.title).to eq(alert_presenter.full_title)
expect(issue.title).to include(gitlab_alert.environment.name)
expect(issue.title).to include(query_title)
expect(issue.title).to include('for 5 minutes')
expect(issue.description).to include(alert_presenter.issue_summary_markdown.strip)
expect(separator_count(issue.description)).to eq 0
end
end
describe 'with invalid alert payload' do
shared_examples 'invalid alert' do
it 'does not create an issue' do
expect(service)
.to receive(:log_error)
.with(error_message('invalid alert'))
expect(subject).to eq(status: :error, message: 'invalid alert')
end
end
context 'without title' do
let(:alert_annotations) { {} }
it_behaves_like 'invalid alert'
end
context 'without startsAt' do
let(:alert_starts_at) { nil }
it_behaves_like 'invalid alert'
end
end
describe "label `incident`" do
let(:title) { 'incident' }
let(:color) { '#CC0033' }
let(:description) do
<<~DESCRIPTION.chomp
Denotes a disruption to IT services and \
the associated issues require immediate attention
DESCRIPTION
end
shared_examples 'existing label' do
it 'adds the existing label' do
expect { subject }.not_to change(Label, :count)
expect(issue.labels).to eq([label])
end
end
shared_examples 'new label' do
it 'adds newly created label' do
expect { subject }.to change(Label, :count).by(1)
label = project.reload.labels.last
expect(issue.labels).to eq([label])
expect(label.title).to eq(title)
expect(label.color).to eq(color)
expect(label.description).to eq(description)
end
end
context 'with predefined project label' do
it_behaves_like 'existing label' do
let!(:label) { create(:label, project: project, title: title) }
end
end
context 'with predefined group label' do
let(:project) { create(:project, group: group) }
let(:group) { create(:group) }
it_behaves_like 'existing label' do
let!(:label) { create(:group_label, group: group, title: title) }
end
end
context 'without label' do
it_behaves_like 'new label'
end
context 'with duplicate labels', issue: 'https://gitlab.com/gitlab-org/gitlab-foss/issues/65042' do
before do
# Replicate race condition to create duplicates
build(:label, project: project, title: title).save!(validate: false)
build(:label, project: project, title: title).save!(validate: false)
end
it 'create an issue without labels' do
# Verify we have duplicates
expect(project.labels.size).to eq(2)
expect(project.labels.map(&:title)).to all(eq(title))
message = <<~MESSAGE.chomp
Cannot create incident issue with labels ["#{title}"] for \
"#{project.full_name}": Labels is invalid.
Retrying without labels.
MESSAGE
expect(service)
.to receive(:log_info)
.with(message)
expect(subject).to include(status: :success)
expect(issue.labels).to be_empty
end
end
end
end
context 'when create_issue disabled' do
before do
setting.update!(create_issue: false)
end
it 'returns an error' do
expect(service)
.to receive(:log_error)
.with(error_message('setting disabled'))
expect(subject).to eq(status: :error, message: 'setting disabled')
end
end
private
def build_alert_payload(annotations: {}, starts_at: Time.now)
{
'annotations' => annotations.stringify_keys
}.tap do |payload|
payload['startsAt'] = starts_at.rfc3339 if starts_at
end
end
def error_message(message)
%{Cannot create incident issue for "#{project.full_name}": #{message}}
end
def separator_count(text)
text.scan(summary_separator).size
end
end
Loading
Loading
@@ -106,5 +106,15 @@ describe WorkerContext do
expect(Labkit::Context.current.to_h).to include('meta.user' => 'jane-doe')
end
end
it 'yields the arguments to the block' do
a_user = build_stubbed(:user)
a_project = build_stubbed(:project)
worker.new.with_context(user: a_user, project: a_project) do |user:, project:|
expect(user).to eq(a_user)
expect(project).to eq(a_project)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe IncidentManagement::ProcessAlertWorker do
let_it_be(:project) { create(:project) }
describe '#perform' do
let(:alert) { :alert }
let(:create_issue_service) { spy(:create_issue_service) }
subject { described_class.new.perform(project.id, alert) }
it 'calls create issue service' do
expect(Project).to receive(:find_by_id).and_call_original
expect(IncidentManagement::CreateIssueService)
.to receive(:new).with(project, :alert)
.and_return(create_issue_service)
expect(create_issue_service).to receive(:execute)
subject
end
context 'with invalid project' do
let(:invalid_project_id) { 0 }
subject { described_class.new.perform(invalid_project_id, alert) }
it 'does not create issues' do
expect(Project).to receive(:find_by_id).and_call_original
expect(IncidentManagement::CreateIssueService).not_to receive(:new)
subject
end
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment