Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
8e7172c40e
commit
eba9cac2e8
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -0,0 +1 @@
|
|||
95adff6092ae61752ee817560e2ba98bf697660a38ae78e07317e1634436c778
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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!(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ""
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module CountriesControllerTestHelper
|
||||
def world_deny_list
|
||||
::World::DENYLIST + ::World::JH_MARKET
|
||||
end
|
||||
end
|
||||
|
||||
CountriesControllerTestHelper.prepend_mod
|
||||
Loading…
Reference in New Issue