Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
b520023279
commit
67d19cc004
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Mutations
|
||||||
|
module Ci
|
||||||
|
module PipelineSchedule
|
||||||
|
class Base < BaseMutation
|
||||||
|
PipelineScheduleID = ::Types::GlobalIDType[::Ci::PipelineSchedule]
|
||||||
|
|
||||||
|
argument :id, PipelineScheduleID,
|
||||||
|
required: true,
|
||||||
|
description: 'ID of the pipeline schedule to mutate.'
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def find_object(id:)
|
||||||
|
GlobalID::Locator.locate(id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,27 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Mutations
|
||||||
|
module Ci
|
||||||
|
module PipelineSchedule
|
||||||
|
class Delete < Base
|
||||||
|
graphql_name 'PipelineScheduleDelete'
|
||||||
|
|
||||||
|
authorize :admin_pipeline_schedule
|
||||||
|
|
||||||
|
def resolve(id:)
|
||||||
|
schedule = authorized_find!(id: id)
|
||||||
|
|
||||||
|
if schedule.destroy
|
||||||
|
{
|
||||||
|
errors: []
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errors: ['Failed to remove the pipeline schedule']
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -114,6 +114,7 @@ module Types
|
||||||
mount_mutation Mutations::Ci::Pipeline::Cancel
|
mount_mutation Mutations::Ci::Pipeline::Cancel
|
||||||
mount_mutation Mutations::Ci::Pipeline::Destroy
|
mount_mutation Mutations::Ci::Pipeline::Destroy
|
||||||
mount_mutation Mutations::Ci::Pipeline::Retry
|
mount_mutation Mutations::Ci::Pipeline::Retry
|
||||||
|
mount_mutation Mutations::Ci::PipelineSchedule::Delete
|
||||||
mount_mutation Mutations::Ci::CiCdSettingsUpdate, deprecated: {
|
mount_mutation Mutations::Ci::CiCdSettingsUpdate, deprecated: {
|
||||||
reason: :renamed,
|
reason: :renamed,
|
||||||
replacement: 'ProjectCiCdSettingsUpdate',
|
replacement: 'ProjectCiCdSettingsUpdate',
|
||||||
|
|
|
@ -1738,7 +1738,7 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorized_project_mirrors(level)
|
def authorized_project_mirrors(level)
|
||||||
projects = Ci::ProjectMirror.by_project_id(ci_project_mirrors_for_project_members(level))
|
projects = Ci::ProjectMirror.by_project_id(ci_project_ids_for_project_members(level))
|
||||||
|
|
||||||
namespace_projects = Ci::ProjectMirror.by_namespace_id(ci_namespace_mirrors_for_group_members(level).select(:namespace_id))
|
namespace_projects = Ci::ProjectMirror.by_namespace_id(ci_namespace_mirrors_for_group_members(level).select(:namespace_id))
|
||||||
|
|
||||||
|
@ -2210,7 +2210,7 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
# rubocop: enable CodeReuse/ServiceClass
|
# rubocop: enable CodeReuse/ServiceClass
|
||||||
|
|
||||||
def ci_project_mirrors_for_project_members(level)
|
def ci_project_ids_for_project_members(level)
|
||||||
project_members.where('access_level >= ?', level).pluck(:source_id)
|
project_members.where('access_level >= ?', level).pluck(:source_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2364,7 +2364,7 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def ci_owned_project_runners_from_project_members
|
def ci_owned_project_runners_from_project_members
|
||||||
project_ids = ci_project_mirrors_for_project_members(Gitlab::Access::MAINTAINER)
|
project_ids = ci_project_ids_for_project_members(Gitlab::Access::MAINTAINER)
|
||||||
|
|
||||||
Ci::Runner
|
Ci::Runner
|
||||||
.joins(:runner_projects)
|
.joins(:runner_projects)
|
||||||
|
|
|
@ -26,7 +26,6 @@ module Gitlab
|
||||||
RefreshImportJidWorker.perform_in_the_future(project.id, jid)
|
RefreshImportJidWorker.perform_in_the_future(project.id, jid)
|
||||||
|
|
||||||
info(project.id, message: "starting importer", importer: 'Importer::RepositoryImporter')
|
info(project.id, message: "starting importer", importer: 'Importer::RepositoryImporter')
|
||||||
|
|
||||||
importer = Importer::RepositoryImporter.new(project, client)
|
importer = Importer::RepositoryImporter.new(project, client)
|
||||||
|
|
||||||
importer.execute
|
importer.execute
|
||||||
|
|
|
@ -18,9 +18,13 @@ class MergeRequests::DeleteSourceBranchWorker
|
||||||
# Source branch changed while it's being removed
|
# Source branch changed while it's being removed
|
||||||
return if merge_request.source_branch_sha != source_branch_sha
|
return if merge_request.source_branch_sha != source_branch_sha
|
||||||
|
|
||||||
::Branches::DeleteService.new(merge_request.source_project, user)
|
delete_service_result = ::Branches::DeleteService.new(merge_request.source_project, user)
|
||||||
.execute(merge_request.source_branch)
|
.execute(merge_request.source_branch)
|
||||||
|
|
||||||
|
if Feature.enabled?(:track_delete_source_errors, merge_request.source_project)
|
||||||
|
delete_service_result.track_exception if delete_service_result&.error?
|
||||||
|
end
|
||||||
|
|
||||||
::MergeRequests::RetargetChainService.new(project: merge_request.source_project, current_user: user)
|
::MergeRequests::RetargetChainService.new(project: merge_request.source_project, current_user: user)
|
||||||
.execute(merge_request)
|
.execute(merge_request)
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
name: track_delete_source_errors
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99028
|
||||||
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/377258
|
||||||
|
milestone: '15.5'
|
||||||
|
type: development
|
||||||
|
group: group::code review
|
||||||
|
default_enabled: false
|
|
@ -4158,6 +4158,24 @@ Input type: `PipelineRetryInput`
|
||||||
| <a id="mutationpipelineretryerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
| <a id="mutationpipelineretryerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||||
| <a id="mutationpipelineretrypipeline"></a>`pipeline` | [`Pipeline`](#pipeline) | Pipeline after mutation. |
|
| <a id="mutationpipelineretrypipeline"></a>`pipeline` | [`Pipeline`](#pipeline) | Pipeline after mutation. |
|
||||||
|
|
||||||
|
### `Mutation.pipelineScheduleDelete`
|
||||||
|
|
||||||
|
Input type: `PipelineScheduleDeleteInput`
|
||||||
|
|
||||||
|
#### Arguments
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | ---- | ----------- |
|
||||||
|
| <a id="mutationpipelinescheduledeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||||
|
| <a id="mutationpipelinescheduledeleteid"></a>`id` | [`CiPipelineScheduleID!`](#cipipelinescheduleid) | ID of the pipeline schedule to mutate. |
|
||||||
|
|
||||||
|
#### Fields
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | ---- | ----------- |
|
||||||
|
| <a id="mutationpipelinescheduledeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||||
|
| <a id="mutationpipelinescheduledeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||||
|
|
||||||
### `Mutation.projectCiCdSettingsUpdate`
|
### `Mutation.projectCiCdSettingsUpdate`
|
||||||
|
|
||||||
Input type: `ProjectCiCdSettingsUpdateInput`
|
Input type: `ProjectCiCdSettingsUpdateInput`
|
||||||
|
@ -21810,6 +21828,12 @@ A `CiPipelineID` is a global ID. It is encoded as a string.
|
||||||
|
|
||||||
An example `CiPipelineID` is: `"gid://gitlab/Ci::Pipeline/1"`.
|
An example `CiPipelineID` is: `"gid://gitlab/Ci::Pipeline/1"`.
|
||||||
|
|
||||||
|
### `CiPipelineScheduleID`
|
||||||
|
|
||||||
|
A `CiPipelineScheduleID` is a global ID. It is encoded as a string.
|
||||||
|
|
||||||
|
An example `CiPipelineScheduleID` is: `"gid://gitlab/Ci::PipelineSchedule/1"`.
|
||||||
|
|
||||||
### `CiRunnerID`
|
### `CiRunnerID`
|
||||||
|
|
||||||
A `CiRunnerID` is a global ID. It is encoded as a string.
|
A `CiRunnerID` is a global ID. It is encoded as a string.
|
||||||
|
|
|
@ -158,6 +158,10 @@ You can sort members by **Account**, **Access granted**, **Max role**, or **Last
|
||||||
|
|
||||||
You can give a user access to all projects in a group.
|
You can give a user access to all projects in a group.
|
||||||
|
|
||||||
|
Prerequisite:
|
||||||
|
|
||||||
|
- You must have the Owner role.
|
||||||
|
|
||||||
1. On the top bar, select **Main menu > Groups** and find your group.
|
1. On the top bar, select **Main menu > Groups** and find your group.
|
||||||
1. On the left sidebar, select **Group information > Members**.
|
1. On the left sidebar, select **Group information > Members**.
|
||||||
1. Select **Invite members**.
|
1. Select **Invite members**.
|
||||||
|
|
|
@ -60,10 +60,6 @@ module Gitlab
|
||||||
work_item_type_id: issue.work_item_type_id
|
work_item_type_id: issue.work_item_type_id
|
||||||
}
|
}
|
||||||
|
|
||||||
Issue.with_project_iid_supply(project) do |supply|
|
|
||||||
attributes[:iid] = supply.next_value
|
|
||||||
end
|
|
||||||
|
|
||||||
insert_and_return_id(attributes, project.issues)
|
insert_and_return_id(attributes, project.issues)
|
||||||
rescue ActiveRecord::InvalidForeignKey
|
rescue ActiveRecord::InvalidForeignKey
|
||||||
# It's possible the project has been deleted since scheduling this
|
# It's possible the project has been deleted since scheduling this
|
||||||
|
|
|
@ -48,7 +48,7 @@ module Gitlab
|
||||||
end
|
end
|
||||||
|
|
||||||
def schedule_issue_import_workers(issues)
|
def schedule_issue_import_workers(issues)
|
||||||
next_iid = project.issues.maximum(:iid).to_i + 1
|
next_iid = Issue.with_project_iid_supply(project, &:next_value)
|
||||||
|
|
||||||
issues.each do |jira_issue|
|
issues.each do |jira_issue|
|
||||||
# Technically it's possible that the same work is performed multiple
|
# Technically it's possible that the same work is performed multiple
|
||||||
|
@ -70,7 +70,8 @@ module Gitlab
|
||||||
Gitlab::JiraImport::ImportIssueWorker.perform_async(project.id, jira_issue.id, issue_attrs, job_waiter.key)
|
Gitlab::JiraImport::ImportIssueWorker.perform_async(project.id, jira_issue.id, issue_attrs, job_waiter.key)
|
||||||
|
|
||||||
job_waiter.jobs_remaining += 1
|
job_waiter.jobs_remaining += 1
|
||||||
next_iid += 1
|
|
||||||
|
next_iid = Issue.with_project_iid_supply(project, &:next_value)
|
||||||
|
|
||||||
# Mark the issue as imported immediately so we don't end up
|
# Mark the issue as imported immediately so we don't end up
|
||||||
# importing it multiple times within same import.
|
# importing it multiple times within same import.
|
||||||
|
|
|
@ -19,7 +19,6 @@ module Gitlab
|
||||||
ALLOWED_AGGREGATIONS = %i(daily weekly).freeze
|
ALLOWED_AGGREGATIONS = %i(daily weekly).freeze
|
||||||
|
|
||||||
CATEGORIES_FOR_TOTALS = %w[
|
CATEGORIES_FOR_TOTALS = %w[
|
||||||
analytics
|
|
||||||
compliance
|
compliance
|
||||||
error_tracking
|
error_tracking
|
||||||
ide_edit
|
ide_edit
|
||||||
|
@ -27,6 +26,7 @@ module Gitlab
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS = %w[
|
CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS = %w[
|
||||||
|
analytics
|
||||||
ci_users
|
ci_users
|
||||||
deploy_token_packages
|
deploy_token_packages
|
||||||
code_review
|
code_review
|
||||||
|
|
|
@ -10,54 +10,18 @@
|
||||||
category: analytics
|
category: analytics
|
||||||
redis_slot: analytics
|
redis_slot: analytics
|
||||||
aggregation: weekly
|
aggregation: weekly
|
||||||
- name: p_analytics_merge_request
|
|
||||||
category: analytics
|
|
||||||
redis_slot: analytics
|
|
||||||
aggregation: weekly
|
|
||||||
- name: i_analytics_instance_statistics
|
- name: i_analytics_instance_statistics
|
||||||
category: analytics
|
category: analytics
|
||||||
redis_slot: analytics
|
redis_slot: analytics
|
||||||
aggregation: weekly
|
aggregation: weekly
|
||||||
- name: g_analytics_contribution
|
|
||||||
category: analytics
|
|
||||||
redis_slot: analytics
|
|
||||||
aggregation: weekly
|
|
||||||
- name: g_analytics_insights
|
|
||||||
category: analytics
|
|
||||||
redis_slot: analytics
|
|
||||||
aggregation: weekly
|
|
||||||
- name: g_analytics_issues
|
|
||||||
category: analytics
|
|
||||||
redis_slot: analytics
|
|
||||||
aggregation: weekly
|
|
||||||
- name: g_analytics_productivity
|
|
||||||
category: analytics
|
|
||||||
redis_slot: analytics
|
|
||||||
aggregation: weekly
|
|
||||||
- name: g_analytics_valuestream
|
|
||||||
category: analytics
|
|
||||||
redis_slot: analytics
|
|
||||||
aggregation: weekly
|
|
||||||
- name: p_analytics_pipelines
|
- name: p_analytics_pipelines
|
||||||
category: analytics
|
category: analytics
|
||||||
redis_slot: analytics
|
redis_slot: analytics
|
||||||
aggregation: weekly
|
aggregation: weekly
|
||||||
- name: p_analytics_code_reviews
|
|
||||||
category: analytics
|
|
||||||
redis_slot: analytics
|
|
||||||
aggregation: weekly
|
|
||||||
- name: p_analytics_valuestream
|
- name: p_analytics_valuestream
|
||||||
category: analytics
|
category: analytics
|
||||||
redis_slot: analytics
|
redis_slot: analytics
|
||||||
aggregation: weekly
|
aggregation: weekly
|
||||||
- name: p_analytics_insights
|
|
||||||
category: analytics
|
|
||||||
redis_slot: analytics
|
|
||||||
aggregation: weekly
|
|
||||||
- name: p_analytics_issues
|
|
||||||
category: analytics
|
|
||||||
redis_slot: analytics
|
|
||||||
aggregation: weekly
|
|
||||||
- name: p_analytics_repo
|
- name: p_analytics_repo
|
||||||
category: analytics
|
category: analytics
|
||||||
redis_slot: analytics
|
redis_slot: analytics
|
||||||
|
@ -86,23 +50,3 @@
|
||||||
category: analytics
|
category: analytics
|
||||||
redis_slot: analytics
|
redis_slot: analytics
|
||||||
aggregation: weekly
|
aggregation: weekly
|
||||||
- name: g_analytics_ci_cd_release_statistics
|
|
||||||
category: analytics
|
|
||||||
redis_slot: analytics
|
|
||||||
aggregation: weekly
|
|
||||||
- name: g_analytics_ci_cd_deployment_frequency
|
|
||||||
category: analytics
|
|
||||||
redis_slot: analytics
|
|
||||||
aggregation: weekly
|
|
||||||
- name: g_analytics_ci_cd_lead_time
|
|
||||||
category: analytics
|
|
||||||
redis_slot: analytics
|
|
||||||
aggregation: weekly
|
|
||||||
- name: g_analytics_ci_cd_time_to_restore_service
|
|
||||||
category: analytics
|
|
||||||
redis_slot: analytics
|
|
||||||
aggregation: weekly
|
|
||||||
- name: g_analytics_ci_cd_change_failure_rate
|
|
||||||
category: analytics
|
|
||||||
redis_slot: analytics
|
|
||||||
aggregation: weekly
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ require_relative 'shared'
|
||||||
# Factorybot factory methods to create persisted model objects with stable
|
# Factorybot factory methods to create persisted model objects with stable
|
||||||
# and consistent data values, to ensure consistent example snapshot HTML
|
# and consistent data values, to ensure consistent example snapshot HTML
|
||||||
# across various machines and environments. RSpec also makes it easy to invoke
|
# across various machines and environments. RSpec also makes it easy to invoke
|
||||||
# the API # and obtain the response.
|
# the API and obtain the response.
|
||||||
#
|
#
|
||||||
# It is intended to be invoked as a helper subprocess from the `update_example_snapshots.rb`
|
# It is intended to be invoked as a helper subprocess from the `update_example_snapshots.rb`
|
||||||
# script class. It's not intended to be run or used directly. This usage is also reinforced
|
# script class. It's not intended to be run or used directly. This usage is also reinforced
|
||||||
|
@ -32,7 +32,7 @@ RSpec.describe 'Render Static HTML', :api, type: :request do # rubocop:disable R
|
||||||
# noinspection RailsParamDefResolve (RubyMine can't find the shared context from this file location)
|
# noinspection RailsParamDefResolve (RubyMine can't find the shared context from this file location)
|
||||||
include_context 'with GLFM example snapshot fixtures'
|
include_context 'with GLFM example snapshot fixtures'
|
||||||
|
|
||||||
it 'can create a project dependency graph using factories' do
|
it do
|
||||||
markdown_hash = YAML.safe_load(File.open(ENV.fetch('INPUT_MARKDOWN_YML_PATH')), symbolize_names: true)
|
markdown_hash = YAML.safe_load(File.open(ENV.fetch('INPUT_MARKDOWN_YML_PATH')), symbolize_names: true)
|
||||||
metadata_hash = YAML.safe_load(File.open(ENV.fetch('INPUT_METADATA_YML_PATH')), symbolize_names: true) || {}
|
metadata_hash = YAML.safe_load(File.open(ENV.fetch('INPUT_METADATA_YML_PATH')), symbolize_names: true) || {}
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redi
|
||||||
.to receive(:insert_and_return_id)
|
.to receive(:insert_and_return_id)
|
||||||
.with(
|
.with(
|
||||||
{
|
{
|
||||||
iid: 1,
|
iid: 42,
|
||||||
title: 'My Issue',
|
title: 'My Issue',
|
||||||
author_id: user.id,
|
author_id: user.id,
|
||||||
project_id: project.id,
|
project_id: project.id,
|
||||||
|
@ -172,7 +172,7 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redi
|
||||||
.to receive(:insert_and_return_id)
|
.to receive(:insert_and_return_id)
|
||||||
.with(
|
.with(
|
||||||
{
|
{
|
||||||
iid: 1,
|
iid: 42,
|
||||||
title: 'My Issue',
|
title: 'My Issue',
|
||||||
author_id: project.creator_id,
|
author_id: project.creator_id,
|
||||||
project_id: project.id,
|
project_id: project.id,
|
||||||
|
|
|
@ -44,7 +44,7 @@ RSpec.describe Gitlab::JiraImport::IssuesImporter do
|
||||||
|
|
||||||
def mock_issue_serializer(count, raise_exception_on_even_mocks: false)
|
def mock_issue_serializer(count, raise_exception_on_even_mocks: false)
|
||||||
serializer = instance_double(Gitlab::JiraImport::IssueSerializer, execute: { key: 'data' })
|
serializer = instance_double(Gitlab::JiraImport::IssueSerializer, execute: { key: 'data' })
|
||||||
next_iid = project.issues.maximum(:iid).to_i
|
allow(Issue).to receive(:with_project_iid_supply).and_return('issue_iid')
|
||||||
|
|
||||||
count.times do |i|
|
count.times do |i|
|
||||||
if raise_exception_on_even_mocks && i.even?
|
if raise_exception_on_even_mocks && i.even?
|
||||||
|
@ -53,16 +53,15 @@ RSpec.describe Gitlab::JiraImport::IssuesImporter do
|
||||||
jira_issues[i],
|
jira_issues[i],
|
||||||
current_user.id,
|
current_user.id,
|
||||||
default_issue_type_id,
|
default_issue_type_id,
|
||||||
{ iid: next_iid + 1 }
|
{ iid: 'issue_iid' }
|
||||||
).and_raise('Some error')
|
).and_raise('Some error')
|
||||||
else
|
else
|
||||||
next_iid += 1
|
|
||||||
expect(Gitlab::JiraImport::IssueSerializer).to receive(:new).with(
|
expect(Gitlab::JiraImport::IssueSerializer).to receive(:new).with(
|
||||||
project,
|
project,
|
||||||
jira_issues[i],
|
jira_issues[i],
|
||||||
current_user.id,
|
current_user.id,
|
||||||
default_issue_type_id,
|
default_issue_type_id,
|
||||||
{ iid: next_iid }
|
{ iid: 'issue_iid' }
|
||||||
).and_return(serializer)
|
).and_return(serializer)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe 'PipelineScheduleDelete' do
|
||||||
|
include GraphqlHelpers
|
||||||
|
|
||||||
|
let_it_be(:user) { create(:user) }
|
||||||
|
let_it_be(:project) { create(:project) }
|
||||||
|
let_it_be(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: user) }
|
||||||
|
|
||||||
|
let(:mutation) do
|
||||||
|
graphql_mutation(
|
||||||
|
:pipeline_schedule_delete,
|
||||||
|
{ id: pipeline_schedule_id },
|
||||||
|
<<-QL
|
||||||
|
errors
|
||||||
|
QL
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:pipeline_schedule_id) { pipeline_schedule.to_global_id.to_s }
|
||||||
|
let(:mutation_response) { graphql_mutation_response(:pipeline_schedule_delete) }
|
||||||
|
|
||||||
|
context 'when unauthorized' do
|
||||||
|
it 'returns an error' do
|
||||||
|
post_graphql_mutation(mutation, current_user: create(:user))
|
||||||
|
|
||||||
|
expect(graphql_errors).not_to be_empty
|
||||||
|
expect(graphql_errors[0]['message'])
|
||||||
|
.to eq(
|
||||||
|
"The resource that you are attempting to access does not exist " \
|
||||||
|
"or you don't have permission to perform this action"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when authorized' do
|
||||||
|
before do
|
||||||
|
project.add_maintainer(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when success' do
|
||||||
|
it do
|
||||||
|
post_graphql_mutation(mutation, current_user: user)
|
||||||
|
|
||||||
|
expect(response).to have_gitlab_http_status(:success)
|
||||||
|
expect(mutation_response['errors']).to eq([])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when failure' do
|
||||||
|
context 'when destroy fails' do
|
||||||
|
before do
|
||||||
|
allow_next_found_instance_of(Ci::PipelineSchedule) do |pipeline_schedule|
|
||||||
|
allow(pipeline_schedule).to receive(:destroy).and_return(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it do
|
||||||
|
post_graphql_mutation(mutation, current_user: user)
|
||||||
|
|
||||||
|
expect(response).to have_gitlab_http_status(:success)
|
||||||
|
|
||||||
|
expect(mutation_response['errors']).to match_array(['Failed to remove the pipeline schedule'])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when pipeline schedule not found' do
|
||||||
|
let(:pipeline_schedule_id) { 'gid://gitlab/Ci::PipelineSchedule/0' }
|
||||||
|
|
||||||
|
it do
|
||||||
|
post_graphql_mutation(mutation, current_user: user)
|
||||||
|
|
||||||
|
expect(graphql_errors).not_to be_empty
|
||||||
|
expect(graphql_errors[0]['message'])
|
||||||
|
.to eq("Internal server error: Couldn't find Ci::PipelineSchedule with 'id'=0")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -53,6 +53,48 @@ RSpec.describe MergeRequests::DeleteSourceBranchWorker do
|
||||||
worker.perform(merge_request.id, 'new-source-branch-sha', user.id)
|
worker.perform(merge_request.id, 'new-source-branch-sha', user.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when delete service returns an error' do
|
||||||
|
let(:service_result) { ServiceResponse.error(message: 'placeholder') }
|
||||||
|
|
||||||
|
it 'tracks the exception' do
|
||||||
|
expect_next_instance_of(::Branches::DeleteService) do |instance|
|
||||||
|
expect(instance).to receive(:execute).with(merge_request.source_branch).and_return(service_result)
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(service_result).to receive(:track_exception).and_call_original
|
||||||
|
|
||||||
|
worker.perform(merge_request.id, sha, user.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when track_delete_source_errors is disabled' do
|
||||||
|
before do
|
||||||
|
stub_feature_flags(track_delete_source_errors: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not track the exception' do
|
||||||
|
expect_next_instance_of(::Branches::DeleteService) do |instance|
|
||||||
|
expect(instance).to receive(:execute).with(merge_request.source_branch).and_return(service_result)
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(service_result).not_to receive(:track_exception)
|
||||||
|
|
||||||
|
worker.perform(merge_request.id, sha, user.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'still retargets the merge request' do
|
||||||
|
expect_next_instance_of(::Branches::DeleteService) do |instance|
|
||||||
|
expect(instance).to receive(:execute).with(merge_request.source_branch).and_return(service_result)
|
||||||
|
end
|
||||||
|
|
||||||
|
expect_next_instance_of(::MergeRequests::RetargetChainService) do |instance|
|
||||||
|
expect(instance).to receive(:execute).with(merge_request)
|
||||||
|
end
|
||||||
|
|
||||||
|
worker.perform(merge_request.id, sha, user.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'an idempotent worker' do
|
it_behaves_like 'an idempotent worker' do
|
||||||
|
|
Loading…
Reference in New Issue