Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-12-09 06:07:18 +00:00
parent 8e7172c40e
commit eba9cac2e8
20 changed files with 513 additions and 35 deletions

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
module Mutations
module Issues
class LinkAlerts < Base
graphql_name 'IssueLinkAlerts'
argument :alert_references, [GraphQL::Types::String],
required: true,
description: 'Alerts references to be linked to the incident.'
authorize :admin_issue
def resolve(project_path:, iid:, alert_references:)
issue = authorized_find!(project_path: project_path, iid: iid)
::IncidentManagement::LinkAlerts::CreateService.new(issue, current_user, alert_references).execute
{
issue: issue,
errors: errors_on_object(issue)
}
end
end
end
end

View File

@ -63,6 +63,7 @@ module Types
mount_mutation Mutations::Issues::SetEscalationStatus
mount_mutation Mutations::Issues::Update
mount_mutation Mutations::Issues::Move
mount_mutation Mutations::Issues::LinkAlerts
mount_mutation Mutations::Labels::Create
mount_mutation Mutations::MergeRequests::Accept
mount_mutation Mutations::MergeRequests::Create

View File

@ -0,0 +1,58 @@
# frozen_string_literal: true
module IncidentManagement
module LinkAlerts
class CreateService < ::BaseProjectService
# @param incident [Issue] an incident to link alerts
# @param current_user [User]
# @param alert_references [[String]] a list of alert references. Can be either a short reference or URL
# Examples:
# "^alert#IID"
# "https://gitlab.com/company/project/-/alert_management/IID/details"
def initialize(incident, current_user, alert_references)
@incident = incident
@current_user = current_user
@alert_references = alert_references
super(project: incident.project, current_user: current_user)
end
def execute
return error_no_permissions unless allowed?
references = extract_alerts_from_references
incident.alert_management_alerts << references if references.present?
success
end
private
attr_reader :incident, :current_user, :alert_references
def extract_alerts_from_references
text = alert_references.join(' ')
extractor = Gitlab::ReferenceExtractor.new(project, current_user)
extractor.analyze(text, {})
extractor.alerts
end
def allowed?
current_user&.can?(:admin_issue, project)
end
def success
ServiceResponse.success(payload: { incident: incident })
end
def error(message)
ServiceResponse.error(message: message)
end
def error_no_permissions
error(_('You have insufficient permissions to manage alerts for this project'))
end
end
end
end

View File

@ -1,8 +0,0 @@
---
name: usage_data_ci_i_testing_coverage_report_uploaded
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/102371
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339721
milestone: '15.6'
type: development
group: group::pipeline insights
default_enabled: false

View File

@ -39,6 +39,8 @@ metadata:
description: Operations related to dashboard annotations
- name: debian_distribution
description: Operations related to Debian Linux distributions
- name: debian_packages
description: Operations related to Debian Linux packages
- name: dependency_proxy
description: Operations to manage dependency proxy for a groups
- name: deploy_keys

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
class SetIndexForIssuesHealthStatusOrdering < Gitlab::Database::Migration[2.1]
disable_ddl_transaction!
INDEX_NAME_DESC = 'index_on_issues_health_status_desc_order'
INDEX_NAME_ASC = 'index_on_issues_health_status_asc_order'
def up
add_concurrent_index :issues,
[:project_id, :health_status, :id, :state_id, :issue_type],
order: { health_status: 'DESC NULLS LAST', id: :desc },
name: INDEX_NAME_DESC
add_concurrent_index :issues,
[:project_id, :health_status, :id, :state_id, :issue_type],
order: { health_status: 'ASC NULLS LAST', id: :desc },
name: INDEX_NAME_ASC
end
def down
remove_concurrent_index_by_name :issues, INDEX_NAME_DESC
remove_concurrent_index_by_name :issues, INDEX_NAME_ASC
end
end

View File

@ -0,0 +1 @@
95adff6092ae61752ee817560e2ba98bf697660a38ae78e07317e1634436c778

View File

@ -30103,6 +30103,10 @@ CREATE UNIQUE INDEX index_on_instance_statistics_recorded_at_and_identifier ON a
CREATE INDEX index_on_issues_closed_incidents_by_project_id_and_closed_at ON issues USING btree (project_id, closed_at) WHERE ((issue_type = 1) AND (state_id = 2));
CREATE INDEX index_on_issues_health_status_asc_order ON issues USING btree (project_id, health_status, id DESC, state_id, issue_type);
CREATE INDEX index_on_issues_health_status_desc_order ON issues USING btree (project_id, health_status DESC NULLS LAST, id DESC, state_id, issue_type);
CREATE INDEX index_on_label_links_all_columns ON label_links USING btree (target_id, label_id, target_type);
CREATE INDEX index_on_merge_request_reviewers_user_id_and_state ON merge_request_reviewers USING btree (user_id, state) WHERE (state = 2);

View File

@ -3151,6 +3151,27 @@ Input type: `IssuableResourceLinkDestroyInput`
| <a id="mutationissuableresourcelinkdestroyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationissuableresourcelinkdestroyissuableresourcelink"></a>`issuableResourceLink` | [`IssuableResourceLink`](#issuableresourcelink) | Issuable resource link. |
### `Mutation.issueLinkAlerts`
Input type: `IssueLinkAlertsInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationissuelinkalertsalertreferences"></a>`alertReferences` | [`[String!]!`](#string) | Alerts references to be linked to the incident. |
| <a id="mutationissuelinkalertsclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationissuelinkalertsiid"></a>`iid` | [`String!`](#string) | IID of the issue to mutate. |
| <a id="mutationissuelinkalertsprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the issue to mutate is in. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationissuelinkalertsclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationissuelinkalertserrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationissuelinkalertsissue"></a>`issue` | [`Issue`](#issue) | Issue after mutation. |
### `Mutation.issueMove`
Input type: `IssueMoveInput`

View File

@ -203,6 +203,8 @@ module API
mount ::API::ConanProjectPackages
mount ::API::ContainerRegistryEvent
mount ::API::ContainerRepositories
mount ::API::DebianGroupPackages
mount ::API::DebianProjectPackages
mount ::API::DependencyProxy
mount ::API::DeployKeys
mount ::API::DeployTokens
@ -306,8 +308,6 @@ module API
mount ::API::Ci::Pipelines
mount ::API::Ci::PipelineSchedules
mount ::API::Ci::SecureFiles
mount ::API::DebianGroupPackages
mount ::API::DebianProjectPackages
mount ::API::Discussions
mount ::API::ErrorTracking::Collector
mount ::API::GroupBoards

View File

@ -24,11 +24,11 @@ module API
helpers do
params :shared_package_file_params do
requires :distribution, type: String, desc: 'The Debian Codename or Suite', regexp: Gitlab::Regex.debian_distribution_regex
requires :letter, type: String, desc: 'The Debian Classification (first-letter or lib-first-letter)'
requires :package_name, type: String, desc: 'The Debian Source Package Name', regexp: Gitlab::Regex.debian_package_name_regex
requires :package_version, type: String, desc: 'The Debian Source Package Version', regexp: Gitlab::Regex.debian_version_regex
requires :file_name, type: String, desc: 'The Debian File Name'
requires :distribution, type: String, desc: 'The Debian Codename or Suite', regexp: Gitlab::Regex.debian_distribution_regex, documentation: { example: 'my-distro' }
requires :letter, type: String, desc: 'The Debian Classification (first-letter or lib-first-letter)', documentation: { example: 'a' }
requires :package_name, type: String, desc: 'The Debian Source Package Name', regexp: Gitlab::Regex.debian_package_name_regex, documentation: { example: 'my-pkg' }
requires :package_version, type: String, desc: 'The Debian Source Package Version', regexp: Gitlab::Regex.debian_version_regex, documentation: { example: '1.0.0' }
requires :file_name, type: String, desc: 'The Debian File Name', documentation: { example: 'example_1.0.0~alpha2_amd64.deb' }
end
def distribution_from!(container)
@ -79,7 +79,7 @@ module API
content_type :txt, 'text/plain'
params do
requires :distribution, type: String, desc: 'The Debian Codename or Suite', regexp: Gitlab::Regex.debian_distribution_regex
requires :distribution, type: String, desc: 'The Debian Codename or Suite', regexp: Gitlab::Regex.debian_distribution_regex, documentation: { example: 'my-distro' }
end
namespace 'dists/*distribution', requirements: DISTRIBUTION_REQUIREMENTS do
@ -87,6 +87,14 @@ module API
# https://wiki.debian.org/DebianRepository/Format#A.22Release.22_files
desc 'The Release file signature' do
detail 'This feature was introduced in GitLab 13.5'
success code: 200
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[debian_packages]
end
route_setting :authentication, authenticate_non_public: true
@ -98,6 +106,14 @@ module API
# https://wiki.debian.org/DebianRepository/Format#A.22Release.22_files
desc 'The unsigned Release file' do
detail 'This feature was introduced in GitLab 13.5'
success code: 200
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[debian_packages]
end
route_setting :authentication, authenticate_non_public: true
@ -109,6 +125,14 @@ module API
# https://wiki.debian.org/DebianRepository/Format#A.22Release.22_files
desc 'The signed Release file' do
detail 'This feature was introduced in GitLab 13.5'
success code: 200
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[debian_packages]
end
route_setting :authentication, authenticate_non_public: true
@ -117,12 +141,12 @@ module API
end
params do
requires :component, type: String, desc: 'The Debian Component', regexp: Gitlab::Regex.debian_component_regex
requires :component, type: String, desc: 'The Debian Component', regexp: Gitlab::Regex.debian_component_regex, documentation: { example: 'main' }
end
namespace ':component', requirements: COMPONENT_ARCHITECTURE_REQUIREMENTS do
params do
requires :architecture, type: String, desc: 'The Debian Architecture', regexp: Gitlab::Regex.debian_architecture_regex
requires :architecture, type: String, desc: 'The Debian Architecture', regexp: Gitlab::Regex.debian_architecture_regex, documentation: { example: 'binary-amd64' }
end
namespace 'debian-installer/binary-:architecture' do
@ -130,6 +154,14 @@ module API
# https://wiki.debian.org/DebianRepository/Format#A.22Packages.22_Indices
desc 'The installer (udeb) binary files index' do
detail 'This feature was introduced in GitLab 15.4'
success code: 200
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[debian_packages]
end
route_setting :authentication, authenticate_non_public: true
@ -141,6 +173,14 @@ module API
# https://wiki.debian.org/DebianRepository/Format?action=show&redirect=RepositoryFormat#indices_acquisition_via_hashsums_.28by-hash.29
desc 'The installer (udeb) binary files index by hash' do
detail 'This feature was introduced in GitLab 15.4'
success code: 200
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[debian_packages]
end
route_setting :authentication, authenticate_non_public: true
@ -154,6 +194,14 @@ module API
# https://wiki.debian.org/DebianRepository/Format#A.22Sources.22_Indices
desc 'The source files index' do
detail 'This feature was introduced in GitLab 15.4'
success code: 200
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[debian_packages]
end
route_setting :authentication, authenticate_non_public: true
@ -165,6 +213,14 @@ module API
# https://wiki.debian.org/DebianRepository/Format?action=show&redirect=RepositoryFormat#indices_acquisition_via_hashsums_.28by-hash.29
desc 'The source files index by hash' do
detail 'This feature was introduced in GitLab 15.4'
success code: 200
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[debian_packages]
end
route_setting :authentication, authenticate_non_public: true
@ -174,7 +230,7 @@ module API
end
params do
requires :architecture, type: String, desc: 'The Debian Architecture', regexp: Gitlab::Regex.debian_architecture_regex
requires :architecture, type: String, desc: 'The Debian Architecture', regexp: Gitlab::Regex.debian_architecture_regex, documentation: { example: 'binary-amd64' }
end
namespace 'binary-:architecture', requirements: COMPONENT_ARCHITECTURE_REQUIREMENTS do
@ -182,6 +238,14 @@ module API
# https://wiki.debian.org/DebianRepository/Format#A.22Packages.22_Indices
desc 'The binary files index' do
detail 'This feature was introduced in GitLab 13.5'
success code: 200
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[debian_packages]
end
route_setting :authentication, authenticate_non_public: true
@ -193,6 +257,14 @@ module API
# https://wiki.debian.org/DebianRepository/Format?action=show&redirect=RepositoryFormat#indices_acquisition_via_hashsums_.28by-hash.29
desc 'The binary files index by hash' do
detail 'This feature was introduced in GitLab 15.4'
success code: 200
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[debian_packages]
end
route_setting :authentication, authenticate_non_public: true

View File

@ -30,7 +30,7 @@ module API
end
params do
requires :id, type: String, desc: 'The ID of a group'
requires :id, types: [String, Integer], desc: 'The group ID or full group path.'
end
namespace ':id/-/packages/debian' do
@ -42,8 +42,15 @@ module API
use :shared_package_file_params
end
desc 'The package' do
desc 'Download Debian package' do
detail 'This feature was introduced in GitLab 14.2'
success code: 200
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[debian_packages]
end
route_setting :authentication, authenticate_non_public: true

View File

@ -45,8 +45,15 @@ module API
use :shared_package_file_params
end
desc 'The package' do
desc 'Download Debian package' do
detail 'This feature was introduced in GitLab 14.2'
success code: 200
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[debian_packages]
end
route_setting :authentication, authenticate_non_public: true
@ -55,13 +62,25 @@ module API
end
params do
requires :file_name, type: String, desc: 'The file name'
requires :file_name, type: String, desc: 'The file name', documentation: { example: 'example_1.0.0~alpha2_amd64.deb' }
end
namespace ':file_name', requirements: FILE_NAME_REQUIREMENTS do
format :txt
content_type :json, Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE
desc 'Upload Debian package' do
detail 'This feature was introduced in GitLab 14.0'
success code: 201
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[debian_packages]
end
# PUT {projects|groups}/:id/packages/debian/:file_name
params do
requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)', documentation: { type: 'file' }
@ -91,6 +110,16 @@ module API
end
# PUT {projects|groups}/:id/packages/debian/:file_name/authorize
desc 'Authorize Debian package upload' do
detail 'This feature was introduced in GitLab 13.5'
success code: 200
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[debian_packages]
end
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
put 'authorize' do
authorize_workhorse!(

View File

@ -15,8 +15,8 @@ module Banzai
private
def can_read_reference?(user, alert, node)
can?(user, :read_alert_management_alert, alert)
def can_read_reference?(user, project, node)
can?(user, :read_alert_management_alert, project)
end
end
end

View File

@ -131,7 +131,6 @@
category: testing
redis_slot: testing
aggregation: weekly
feature_flag: usage_data_ci_i_testing_coverage_report_uploaded
# Project Management group
- name: g_project_management_issue_title_changed
category: issues_edit

View File

@ -47449,6 +47449,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
msgid "You have insufficient permissions to manage alerts for this project"
msgstr ""
msgid "You have insufficient permissions to manage resource links for this incident"
msgstr ""

View File

@ -0,0 +1,84 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Mutations::Issues::LinkAlerts, feature_category: :incident_management do
let_it_be(:project) { create(:project) }
let_it_be(:guest) { create(:user) }
let_it_be(:developer) { create(:user) }
let_it_be(:issue) { create(:incident, project: project) }
let_it_be(:alert1) { create(:alert_management_alert, project: project) }
let_it_be(:alert2) { create(:alert_management_alert, project: project) }
let(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
specify { expect(described_class).to require_graphql_authorizations(:update_issue, :admin_issue) }
before_all do
project.add_guest(guest)
project.add_developer(developer)
end
describe '#resolve' do
let(:alert_references) { [alert1.to_reference, alert2.details_url, 'invalid-reference'] }
subject(:resolve) do
mutation.resolve(
project_path: issue.project.full_path,
iid: issue.iid,
alert_references: alert_references
)
end
context 'when the user is a guest' do
let(:user) { guest }
it 'raises an error' do
expect { resolve }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
context 'when a user is also an author' do
let!(:issue) { create(:incident, project: project, author: user) }
it 'raises an error' do
expect { resolve }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context 'when a user is also an assignee' do
let!(:issue) { create(:incident, project: project, assignee_ids: [user.id]) }
it 'raises an error' do
expect { resolve }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
end
context 'when the user is a developer' do
let(:user) { developer }
context 'when issue type is an incident' do
it 'calls LinkAlerts::CreateService with correct arguments' do
expect(::IncidentManagement::LinkAlerts::CreateService)
.to receive(:new)
.with(issue, user, alert_references)
.and_call_original
resolve
end
it 'returns no errors' do
expect(resolve[:errors]).to be_empty
end
end
context 'when issue type is not an incident' do
let!(:issue) { create(:issue, project: project) }
it 'does not update alert_management_alerts' do
expect { resolve }.not_to change { issue.alert_management_alerts }
end
end
end
end
end

View File

@ -0,0 +1,65 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Link alerts to an incident', feature_category: :incident_management do
include GraphqlHelpers
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:linked_alert) { create(:alert_management_alert, project: project) }
let_it_be(:alert1) { create(:alert_management_alert, project: project) }
let_it_be(:alert2) { create(:alert_management_alert, project: project) }
let_it_be(:incident) { create(:incident, project: project, alert_management_alerts: [linked_alert]) }
let(:mutation) do
variables = {
project_path: project.full_path,
iid: incident.iid.to_s,
alert_references: [alert1.to_reference, alert2.details_url]
}
graphql_mutation(:issue_link_alerts, variables,
<<-QL.strip_heredoc
clientMutationId
errors
issue {
iid
alertManagementAlerts {
nodes {
iid
}
}
}
QL
)
end
def mutation_response
graphql_mutation_response(:issue_link_alerts)
end
context 'when the user is not allowed to update the incident' do
it 'returns an error' do
error = Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR
post_graphql_mutation(mutation, current_user: user)
expect(response).to have_gitlab_http_status(:success)
expect(graphql_errors).to include(a_hash_including('message' => error))
end
end
context 'when the user is allowed to update the incident' do
before do
project.add_developer(user)
end
it 'links alerts to the incident' do
post_graphql_mutation(mutation, current_user: user)
expect(response).to have_gitlab_http_status(:success)
expected_response = [linked_alert, alert1, alert2].map { |a| { 'iid' => a.iid.to_s } }
expect(mutation_response.dig('issue', 'alertManagementAlerts', 'nodes')).to match_array(expected_response)
end
end
end

View File

@ -0,0 +1,98 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe IncidentManagement::LinkAlerts::CreateService, feature_category: :incident_management do
let_it_be(:project) { create(:project) }
let_it_be(:another_project) { create(:project) }
let_it_be(:linked_alert) { create(:alert_management_alert, project: project) }
let_it_be(:alert1) { create(:alert_management_alert, project: project) }
let_it_be(:alert2) { create(:alert_management_alert, project: project) }
let_it_be(:external_alert) { create(:alert_management_alert, project: another_project) }
let_it_be(:incident) { create(:incident, project: project, alert_management_alerts: [linked_alert]) }
let_it_be(:guest) { create(:user) }
let_it_be(:developer) { create(:user) }
let_it_be(:another_developer) { create(:user) }
before_all do
project.add_guest(guest)
project.add_developer(developer)
project.add_developer(another_developer)
another_project.add_guest(guest)
another_project.add_developer(developer)
end
describe '#execute' do
subject(:execute) { described_class.new(incident, current_user, alert_references).execute }
let(:alert_references) { [alert1.to_reference, alert2.details_url] }
context 'when current user is a guest' do
let(:current_user) { guest }
it 'responds with error', :aggregate_failures do
response = execute
expect(response).to be_error
expect(response.message).to eq('You have insufficient permissions to manage alerts for this project')
end
it 'does not link alerts to the incident' do
expect { execute }.not_to change { incident.reload.alert_management_alerts.to_a }
end
end
context 'when current user is a developer' do
let(:current_user) { developer }
it 'responds with success', :aggregate_failures do
response = execute
expect(response).to be_success
expect(response.payload[:incident]).to eq(incident)
end
it 'links alerts to the incident' do
expect { execute }
.to change { incident.reload.alert_management_alerts.to_a }
.from([linked_alert])
.to([linked_alert, alert1, alert2])
end
context 'when linking an already linked alert' do
let(:alert_references) { [linked_alert.details_url] }
it 'does not change incident alerts list' do
expect { execute }.not_to change { incident.reload.alert_management_alerts.to_a }
end
end
context 'when linking an alert from another project' do
let(:alert_references) { [external_alert.details_url] }
it 'links an external alert to the incident' do
expect { execute }
.to change { incident.reload.alert_management_alerts.to_a }
.from([linked_alert])
.to([linked_alert, external_alert])
end
end
end
context 'when current user does not have permission to read alerts on external project' do
let(:current_user) { another_developer }
context 'when linking alerts from current and external projects' do
let(:alert_references) { [alert1.details_url, external_alert.details_url] }
it 'links only alerts the current user can read' do
expect { execute }
.to change { incident.reload.alert_management_alerts.to_a }
.from([linked_alert])
.to([linked_alert, alert1])
end
end
end
end
end

View File

@ -1,9 +0,0 @@
# frozen_string_literal: true
module CountriesControllerTestHelper
def world_deny_list
::World::DENYLIST + ::World::JH_MARKET
end
end
CountriesControllerTestHelper.prepend_mod