Commit 7f37c03d authored by Alex Pooley's avatar Alex Pooley

Merge branch '356069-deprecate-manual-iteration-management' into 'master'

Deprecate manual iteration creation

See merge request gitlab-org/gitlab!83046
parents 0df91e78 3e9f9a9c
...@@ -1458,7 +1458,7 @@ Input type: `CreateIssueInput` ...@@ -1458,7 +1458,7 @@ Input type: `CreateIssueInput`
WARNING: WARNING:
**Deprecated** in 14.0. **Deprecated** in 14.0.
Use iterationCreate. Manual iteration management is deprecated. Only automatic iteration cadences will be supported in the future.
Input type: `CreateIterationInput` Input type: `CreateIterationInput`
...@@ -1470,7 +1470,7 @@ Input type: `CreateIterationInput` ...@@ -1470,7 +1470,7 @@ Input type: `CreateIterationInput`
| <a id="mutationcreateiterationdescription"></a>`description` | [`String`](#string) | Description of the iteration. | | <a id="mutationcreateiterationdescription"></a>`description` | [`String`](#string) | Description of the iteration. |
| <a id="mutationcreateiterationduedate"></a>`dueDate` | [`String`](#string) | End date of the iteration. | | <a id="mutationcreateiterationduedate"></a>`dueDate` | [`String`](#string) | End date of the iteration. |
| <a id="mutationcreateiterationgrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. | | <a id="mutationcreateiterationgrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
| <a id="mutationcreateiterationiterationscadenceid"></a>`iterationsCadenceId` | [`IterationsCadenceID`](#iterationscadenceid) | Global ID of the iterations cadence to be assigned to newly created iteration. | | <a id="mutationcreateiterationiterationscadenceid"></a>`iterationsCadenceId` **{warning-solid}** | [`IterationsCadenceID`](#iterationscadenceid) | **Deprecated:** `iterationCadenceId` is deprecated and will be removed in the future. This argument is ignored, because you can't create an iteration in a specific cadence. In the future only automatic iteration cadences will be allowed. Deprecated in 14.10. |
| <a id="mutationcreateiterationprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. | | <a id="mutationcreateiterationprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. |
| <a id="mutationcreateiterationstartdate"></a>`startDate` | [`String`](#string) | Start date of the iteration. | | <a id="mutationcreateiterationstartdate"></a>`startDate` | [`String`](#string) | Start date of the iteration. |
| <a id="mutationcreateiterationtitle"></a>`title` | [`String`](#string) | Title of the iteration. | | <a id="mutationcreateiterationtitle"></a>`title` | [`String`](#string) | Title of the iteration. |
...@@ -3213,6 +3213,10 @@ Input type: `IterationCadenceUpdateInput` ...@@ -3213,6 +3213,10 @@ Input type: `IterationCadenceUpdateInput`
### `Mutation.iterationCreate` ### `Mutation.iterationCreate`
WARNING:
**Deprecated** in 14.10.
Manual iteration management is deprecated. Only automatic iteration cadences will be supported in the future.
Input type: `iterationCreateInput` Input type: `iterationCreateInput`
#### Arguments #### Arguments
...@@ -3223,7 +3227,7 @@ Input type: `iterationCreateInput` ...@@ -3223,7 +3227,7 @@ Input type: `iterationCreateInput`
| <a id="mutationiterationcreatedescription"></a>`description` | [`String`](#string) | Description of the iteration. | | <a id="mutationiterationcreatedescription"></a>`description` | [`String`](#string) | Description of the iteration. |
| <a id="mutationiterationcreateduedate"></a>`dueDate` | [`String`](#string) | End date of the iteration. | | <a id="mutationiterationcreateduedate"></a>`dueDate` | [`String`](#string) | End date of the iteration. |
| <a id="mutationiterationcreategrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. | | <a id="mutationiterationcreategrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
| <a id="mutationiterationcreateiterationscadenceid"></a>`iterationsCadenceId` | [`IterationsCadenceID`](#iterationscadenceid) | Global ID of the iterations cadence to be assigned to newly created iteration. | | <a id="mutationiterationcreateiterationscadenceid"></a>`iterationsCadenceId` **{warning-solid}** | [`IterationsCadenceID`](#iterationscadenceid) | **Deprecated:** `iterationCadenceId` is deprecated and will be removed in the future. This argument is ignored, because you can't create an iteration in a specific cadence. In the future only automatic iteration cadences will be allowed. Deprecated in 14.10. |
| <a id="mutationiterationcreateprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. | | <a id="mutationiterationcreateprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. |
| <a id="mutationiterationcreatestartdate"></a>`startDate` | [`String`](#string) | Start date of the iteration. | | <a id="mutationiterationcreatestartdate"></a>`startDate` | [`String`](#string) | Start date of the iteration. |
| <a id="mutationiterationcreatetitle"></a>`title` | [`String`](#string) | Title of the iteration. | | <a id="mutationiterationcreatetitle"></a>`title` | [`String`](#string) | Title of the iteration. |
...@@ -8,10 +8,12 @@ module EE ...@@ -8,10 +8,12 @@ module EE
ITERATION_DEPRECATION_MESSAGE = 'Manual iteration management is deprecated. Only automatic iteration cadences will be supported in the future' ITERATION_DEPRECATION_MESSAGE = 'Manual iteration management is deprecated. Only automatic iteration cadences will be supported in the future'
prepended do prepended do
mount_mutation ::Mutations::Iterations::Create,
deprecated: { reason: ITERATION_DEPRECATION_MESSAGE, milestone: '14.10' }
mount_mutation ::Mutations::Iterations::Delete, mount_mutation ::Mutations::Iterations::Delete,
deprecated: { reason: ITERATION_DEPRECATION_MESSAGE, milestone: '14.10' } deprecated: { reason: ITERATION_DEPRECATION_MESSAGE, milestone: '14.10' }
mount_aliased_mutation 'CreateIteration', ::Mutations::Iterations::Create, mount_aliased_mutation 'CreateIteration', ::Mutations::Iterations::Create,
deprecated: { reason: 'Use iterationCreate', milestone: '14.0' } deprecated: { reason: ITERATION_DEPRECATION_MESSAGE, milestone: '14.0' }
end end
end end
end end
......
...@@ -21,7 +21,6 @@ module EE ...@@ -21,7 +21,6 @@ module EE
mount_mutation ::Mutations::Epics::AddIssue mount_mutation ::Mutations::Epics::AddIssue
mount_mutation ::Mutations::GitlabSubscriptions::Activate mount_mutation ::Mutations::GitlabSubscriptions::Activate
mount_mutation ::Mutations::Projects::SetLocked mount_mutation ::Mutations::Projects::SetLocked
mount_mutation ::Mutations::Iterations::Create
mount_mutation ::Mutations::Iterations::Update mount_mutation ::Mutations::Iterations::Update
mount_mutation ::Mutations::Iterations::Cadences::Create mount_mutation ::Mutations::Iterations::Cadences::Create
mount_mutation ::Mutations::Iterations::Cadences::Update mount_mutation ::Mutations::Iterations::Cadences::Update
......
...@@ -5,6 +5,10 @@ module Mutations ...@@ -5,6 +5,10 @@ module Mutations
class Create < BaseMutation class Create < BaseMutation
graphql_name 'iterationCreate' graphql_name 'iterationCreate'
CADENCE_ID_DEPRECATION_MESSAGE = '`iterationCadenceId` is deprecated and will be removed in the future.' \
' This argument is ignored, because you can\'t create an iteration in a specific cadence.' \
' In the future only automatic iteration cadences will be allowed'
include Mutations::ResolvesResourceParent include Mutations::ResolvesResourceParent
authorize :create_iteration authorize :create_iteration
...@@ -16,9 +20,10 @@ module Mutations ...@@ -16,9 +20,10 @@ module Mutations
argument :iterations_cadence_id, argument :iterations_cadence_id,
::Types::GlobalIDType[::Iterations::Cadence], ::Types::GlobalIDType[::Iterations::Cadence],
loads: ::Types::Iterations::CadenceType,
required: false, required: false,
description: 'Global ID of the iterations cadence to be assigned to newly created iteration.' deprecated: { reason: CADENCE_ID_DEPRECATION_MESSAGE, milestone: '14.10' },
description: 'Global ID of the iteration cadence to be assigned to the new iteration.' \
'Argument is ignored as it was only used behind the `iteration_cadences` feature flag.'
argument :title, argument :title,
GraphQL::Types::String, GraphQL::Types::String,
...@@ -59,6 +64,11 @@ module Mutations ...@@ -59,6 +64,11 @@ module Mutations
private private
def validate_arguments!(parent, args) def validate_arguments!(parent, args)
# Ignoring argument as it's not necessary for the legacy iteration creation feature.
# Iteration will always be created in the first manual cadence for the group and create one
# if it doesn't exist yet.
args.delete(:iterations_cadence_id)
if args.except(:group_path, :project_path).empty? if args.except(:group_path, :project_path).empty?
raise Gitlab::Graphql::Errors::ArgumentError, 'The list of iteration attributes is empty' raise Gitlab::Graphql::Errors::ArgumentError, 'The list of iteration attributes is empty'
end end
...@@ -66,15 +76,6 @@ module Mutations ...@@ -66,15 +76,6 @@ module Mutations
if !parent.iteration_cadences_feature_flag_enabled? && args[:title].blank? if !parent.iteration_cadences_feature_flag_enabled? && args[:title].blank?
raise Gitlab::Graphql::Errors::ArgumentError, "Title can't be blank" raise Gitlab::Graphql::Errors::ArgumentError, "Title can't be blank"
end end
# Currently there is a single iteration cadence per group, so if `iterations_cadence_id` argument is not provided
# we assign iteration to the only cadence in the group(see `Iteration#set_iterations_cadence`).
# Once we introduce cadence CRUD support we need to specify to which iteration cadence a given iteration
# belongs if there are more than once cadence in the group. Eventually `iterations_cadence_id` argument should
# become required and there should be no need for group_path argument for iteration.
if args[:iterations_cadence].blank? && parent.iterations_cadences.count > 1 && parent.iteration_cadences_feature_flag_enabled?
raise Gitlab::Graphql::Errors::ArgumentError, 'Please provide iterations_cadence_id argument to assign iteration to respective cadence'
end
end end
end end
end end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Types::MutationType do
describe 'deprecated mutations' do
describe 'iterationCreate' do
let(:field) { get_field('iterationCreate') }
it { expect(field.deprecation_reason).to eq('Manual iteration management is deprecated. Only automatic iteration cadences will be supported in the future. Deprecated in 14.10.') }
end
describe 'createIteration' do
let(:field) { get_field('createIteration') }
it { expect(field.deprecation_reason).to eq('Manual iteration management is deprecated. Only automatic iteration cadences will be supported in the future. Deprecated in 14.0.') }
end
end
def get_field(name)
described_class.fields[GraphqlHelpers.fieldnamerize(name)]
end
end
...@@ -34,113 +34,88 @@ RSpec.describe 'Creating an Iteration' do ...@@ -34,113 +34,88 @@ RSpec.describe 'Creating an Iteration' do
graphql_mutation_response(:create_iteration) graphql_mutation_response(:create_iteration)
end end
context 'when the user does not have permission' do shared_examples 'legacy iteration creation request' do
before do it 'creates a new iteration in the default manual cadence' do
stub_licensed_features(iterations: true) post_graphql_mutation(mutation, current_user: current_user)
end
it_behaves_like 'a mutation that returns a top-level access error'
it 'does not create iteration' do iteration_hash = mutation_response['iteration']
expect { post_graphql_mutation(mutation, current_user: current_user) }.not_to change(Iteration, :count) aggregate_failures do
expect(iteration_hash['title']).to eq('title')
expect(iteration_hash['iterationCadence']['id']).to eq(cadence.to_global_id.to_s)
end end
end end
context 'when the user has permission' do
before do
group.add_developer(current_user)
end end
context 'when iterations are disabled' do shared_examples 'iteration create request' do
before do context 'when there are several iteration cadences in the group' do
stub_licensed_features(iterations: false) let_it_be(:extra_cadence) { create(:iterations_cadence, group: group) }
end
it_behaves_like 'a mutation that returns top-level errors', context 'when iteration cadence id is not provided' do
errors: ['The resource that you are attempting to access does not '\ it_behaves_like 'legacy iteration creation request'
'exist or you don\'t have permission to perform this action']
end end
context 'when iterations are enabled' do context 'when iteration cadence id is provided' do
before do before do
stub_licensed_features(iterations: true) attributes[:iterations_cadence_id] = extra_cadence.to_global_id.to_s
end end
context 'when iteration cadence id is not provided' do it_behaves_like 'legacy iteration creation request'
context 'and there is only one iteration cadence in the group' do
it 'creates the iteration for a group' do
post_graphql_mutation(mutation, current_user: current_user)
iteration_hash = mutation_response['iteration']
aggregate_failures do
expect(iteration_hash['title']).to eq('title')
expect(iteration_hash['description']).to eq('some description')
expect(iteration_hash['startDate']).to eq(start_date)
expect(iteration_hash['dueDate']).to eq(end_date)
expect(iteration_hash['iterationCadence']['id']).to eq(group.iterations_cadences.first.to_global_id.to_s)
end
end end
end end
context 'and there are several iteration cadences in the group' do context 'when there is only one iteration cadence in the group' do
let_it_be(:extra_cadence) { create(:iterations_cadence, group: group)} context 'when iteration cadence id is not provided' do
it_behaves_like 'legacy iteration creation request'
it_behaves_like 'a mutation that returns top-level errors', end
errors: ['Please provide iterations_cadence_id argument to assign iteration to respective cadence']
context 'when iteration_cadences FF is disabled' do context 'when iteration cadence id is provided' do
before do before do
stub_feature_flags(iteration_cadences: false) attributes[:iterations_cadence_id] = cadence.to_global_id.to_s
end end
it 'creates a new iteration in the default cadence' do it_behaves_like 'legacy iteration creation request'
post_graphql_mutation(mutation, current_user: current_user)
iteration_hash = mutation_response['iteration']
aggregate_failures do
expect(iteration_hash['title']).to eq('title')
expect(iteration_hash['iterationCadence']['id']).to eq(group.iterations_cadences.first.to_global_id.to_s)
end end
end end
end end
end
end
context 'when cadence provided' do
context 'with correct cadence' do
let_it_be(:extra_cadence) { create(:iterations_cadence, group: group)}
context 'when the user does not have permission' do
before do before do
attributes.merge!(iterations_cadence_id: extra_cadence.to_global_id.to_s) stub_licensed_features(iterations: true)
end end
it 'creates the iteration for the cadence' do it_behaves_like 'a mutation that returns a top-level access error'
post_graphql_mutation(mutation, current_user: current_user)
iteration_hash = mutation_response['iteration'] it 'does not create iteration' do
aggregate_failures do expect { post_graphql_mutation(mutation, current_user: current_user) }.not_to change(Iteration, :count)
expect(iteration_hash['title']).to eq('title')
expect(iteration_hash['description']).to eq('some description')
expect(iteration_hash['startDate']).to eq(start_date)
expect(iteration_hash['dueDate']).to eq(end_date)
expect(iteration_hash['iterationCadence']['id']).to eq(extra_cadence.to_global_id.to_s)
end
end end
end end
context 'with non-existing cadence and a signle cadence in the group' do context 'when the user has permission' do
let(:non_existing_cadence_id) { "gid://gitlab/Iterations::Cadence/#{non_existing_record_id}" } before do
group.add_developer(current_user)
end
context 'when iterations are disabled' do
before do before do
attributes.merge!(iterations_cadence_id: non_existing_cadence_id) stub_licensed_features(iterations: false)
end end
it_behaves_like 'a mutation that returns top-level errors' do it_behaves_like 'a mutation that returns top-level errors',
let(:match_errors) do errors: ['The resource that you are attempting to access does not '\
contain_exactly(include("No object found for `iterationsCadenceId: ")) 'exist or you don\'t have permission to perform this action']
end end
context 'when iterations are enabled' do
before do
stub_licensed_features(iterations: true)
end end
context 'with iterations_cadences FF disabled' do
before do
stub_feature_flags(iteration_cadences: false)
end end
it_behaves_like 'iteration create request'
end end
context 'with iterations_cadences FF enabled' do context 'with iterations_cadences FF enabled' do
...@@ -148,6 +123,8 @@ RSpec.describe 'Creating an Iteration' do ...@@ -148,6 +123,8 @@ RSpec.describe 'Creating an Iteration' do
stub_feature_flags(iteration_cadences: true) stub_feature_flags(iteration_cadences: true)
end end
it_behaves_like 'iteration create request'
context 'when title is not given' do context 'when title is not given' do
let(:attributes) { { start_date: start_date, due_date: end_date } } let(:attributes) { { start_date: start_date, due_date: end_date } }
......
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