Commit 0b38a141 authored by Mayra Cabrera's avatar Mayra Cabrera

Merge branch '353352-prevent-automatic-iteration-deletion' into 'master'

Disallow deleting iterations that belong to an automatic cadence

See merge request gitlab-org/gitlab!84111
parents 33b71d04 ab19c516
...@@ -5,6 +5,10 @@ module Mutations ...@@ -5,6 +5,10 @@ module Mutations
class Delete < BaseMutation class Delete < BaseMutation
graphql_name 'IterationDelete' graphql_name 'IterationDelete'
AUTOMATIC_CADENCE_ERROR = 'Deleting iterations from automatic iteration cadences is not allowed.' \
' This mutation will be removed in 16.0 when manual iteration management' \
' is removed.'
authorize :admin_iteration authorize :admin_iteration
argument :id, ::Types::GlobalIDType[::Iteration], required: true, argument :id, ::Types::GlobalIDType[::Iteration], required: true,
...@@ -15,6 +19,8 @@ module Mutations ...@@ -15,6 +19,8 @@ module Mutations
def resolve(id:) def resolve(id:)
iteration = authorized_find!(id: id) iteration = authorized_find!(id: id)
reject_if_automatic_cadence!(iteration)
response = ::Iterations::DeleteService.new(iteration, current_user).execute response = ::Iterations::DeleteService.new(iteration, current_user).execute
{ {
...@@ -25,6 +31,12 @@ module Mutations ...@@ -25,6 +31,12 @@ module Mutations
private private
def reject_if_automatic_cadence!(iteration)
return unless iteration.iterations_cadence.automatic?
raise Gitlab::Graphql::Errors::MutationError, AUTOMATIC_CADENCE_ERROR
end
def find_object(id:) def find_object(id:)
# TODO: Remove coercion when working on https://gitlab.com/gitlab-org/gitlab/-/issues/257883 # TODO: Remove coercion when working on https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id = ::Types::GlobalIDType[::Iteration].coerce_isolated_input(id) id = ::Types::GlobalIDType[::Iteration].coerce_isolated_input(id)
......
...@@ -10,7 +10,8 @@ RSpec.describe 'User views iteration' do ...@@ -10,7 +10,8 @@ RSpec.describe 'User views iteration' do
let_it_be(:sub_project) { create(:project, group: sub_group) } let_it_be(:sub_project) { create(:project, group: sub_group) }
let_it_be(:user) { create(:group_member, :maintainer, user: create(:user), group: group).user } let_it_be(:user) { create(:group_member, :maintainer, user: create(:user), group: group).user }
let_it_be(:guest_user) { create(:group_member, :guest, user: create(:user), group: group).user } let_it_be(:guest_user) { create(:group_member, :guest, user: create(:user), group: group).user }
let_it_be(:iteration) { create(:iteration, :skip_future_date_validation, iid: 1, id: 2, group: group, title: 'Correct Iteration', description: 'iteration description', start_date: now - 1.day, due_date: now) } let_it_be(:manual_cadence) { build(:iterations_cadence, group: group, automatic: false).tap { |cadence| cadence.save!(validate: false) } }
let_it_be(:iteration) { create(:iteration, :skip_future_date_validation, iterations_cadence: manual_cadence, iid: 1, id: 2, group: group, title: 'Correct Iteration', description: 'iteration description', start_date: now - 1.day, due_date: now) }
let_it_be(:other_iteration) { create(:iteration, :skip_future_date_validation, iid: 2, id: 1, group: group, title: 'Wrong Iteration', start_date: now - 4.days, due_date: now - 3.days) } let_it_be(:other_iteration) { create(:iteration, :skip_future_date_validation, iid: 2, id: 1, group: group, title: 'Wrong Iteration', start_date: now - 4.days, due_date: now - 3.days) }
let_it_be(:sub_group_iteration) { create(:iteration, id: 3, group: sub_group) } let_it_be(:sub_group_iteration) { create(:iteration, id: 3, group: sub_group) }
let_it_be(:label1) { create(:label, project: project) } let_it_be(:label1) { create(:label, project: project) }
......
...@@ -7,7 +7,13 @@ RSpec.describe 'Deleting an iteration' do ...@@ -7,7 +7,13 @@ RSpec.describe 'Deleting an iteration' do
let_it_be(:current_user) { create(:user) } let_it_be(:current_user) { create(:user) }
let_it_be(:group) { create(:group) } let_it_be(:group) { create(:group) }
let_it_be(:iteration, refind: true) { create(:iteration, group: group) } let_it_be(:cadence) do
build(:iterations_cadence, group: group, automatic: false).tap { |cadence| cadence.save!(validate: false) }
end
let_it_be(:manual_iteration, refind: true) { create(:iteration, group: group, iterations_cadence: cadence) }
let(:iteration) { manual_iteration }
let(:params) do let(:params) do
{ id: iteration.to_global_id.to_s } { id: iteration.to_global_id.to_s }
...@@ -50,12 +56,24 @@ RSpec.describe 'Deleting an iteration' do ...@@ -50,12 +56,24 @@ RSpec.describe 'Deleting an iteration' do
stub_licensed_features(iterations: true) stub_licensed_features(iterations: true)
end end
it 'deletes the iteration', :aggregate_failures do context 'when iteration belongs to a manual cadence' do
expect do it 'deletes the iteration', :aggregate_failures do
post_graphql_mutation(mutation, current_user: current_user) expect do
end.to change(Iteration, :count).by(-1) post_graphql_mutation(mutation, current_user: current_user)
end.to change(Iteration, :count).by(-1)
expect(mutation_response).to include('group' => hash_including('id' => group.to_global_id.to_s))
end
end
context 'when iteration belongs to an automatic cadence' do
let(:automatic_cadence) { create(:iterations_cadence, group: group) }
let(:iteration) { create(:iteration, group: group, iterations_cadence: automatic_cadence) }
expect(mutation_response).to include('group' => hash_including('id' => group.to_global_id.to_s)) it_behaves_like 'a mutation that returns top-level errors', errors: [
'Deleting iterations from automatic iteration cadences is not allowed. This mutation will be removed' \
' in 16.0 when manual iteration management is removed.'
]
end end
context 'when required arguments are missing' do context 'when required arguments are missing' do
......
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