diff --git a/app/graphql/mutations/ci/project_ci_cd_settings_update.rb b/app/graphql/mutations/ci/project_ci_cd_settings_update.rb index 082c345adf6d5e7980761d3e9fc7a4fe2eb89f11..7df277641bf32e412f9b8ce407ec0890f181a176 100644 --- a/app/graphql/mutations/ci/project_ci_cd_settings_update.rb +++ b/app/graphql/mutations/ci/project_ci_cd_settings_update.rb @@ -6,6 +6,7 @@ class ProjectCiCdSettingsUpdate < BaseMutation graphql_name 'ProjectCiCdSettingsUpdate' include FindsProject + include Gitlab::Utils::StrongMemoize authorize :admin_project @@ -37,13 +38,11 @@ class ProjectCiCdSettingsUpdate < BaseMutation description: 'CI/CD settings after mutation.' def resolve(full_path:, **args) - project = authorized_find!(full_path) - if args[:job_token_scope_enabled] raise Gitlab::Graphql::Errors::ArgumentError, 'job_token_scope_enabled can only be set to false' end - settings = project.ci_cd_settings + settings = project(full_path).ci_cd_settings settings.update(args) { @@ -51,6 +50,14 @@ def resolve(full_path:, **args) errors: errors_on_object(settings) } end + + private + + def project(full_path) + strong_memoize_with(:project, full_path) do + authorized_find!(full_path) + end + end end end end diff --git a/app/graphql/types/ci/ci_cd_setting_type.rb b/app/graphql/types/ci/ci_cd_setting_type.rb index 45ecbf5c084a2f24bb57ccfcc9e70e8a786749cb..8a49c5a6a951d08637b09bb9eaca33be6a66aaf7 100644 --- a/app/graphql/types/ci/ci_cd_setting_type.rb +++ b/app/graphql/types/ci/ci_cd_setting_type.rb @@ -29,6 +29,7 @@ class CiCdSettingType < BaseObject null: true, description: 'Whether merge pipelines are enabled.', method: :merge_pipelines_enabled? + # TODO(Issue 422295): this is EE only and should be moved to the EE file field :merge_trains_enabled, GraphQL::Types::Boolean, null: true, @@ -41,3 +42,5 @@ class CiCdSettingType < BaseObject end end end + +Types::Ci::CiCdSettingType.prepend_mod_with('Types::Ci::CiCdSettingType') diff --git a/app/models/project_ci_cd_setting.rb b/app/models/project_ci_cd_setting.rb index cc9003423be687496eb70cfff8ebd06b7b84961c..8d049b8d1b1e54665ab71ae1898575ca474f5a16 100644 --- a/app/models/project_ci_cd_setting.rb +++ b/app/models/project_ci_cd_setting.rb @@ -19,6 +19,7 @@ class ProjectCiCdSetting < ApplicationRecord attribute :forward_deployment_enabled, default: true attribute :separated_caches, default: true + validates :merge_trains_skip_train_allowed, inclusion: { in: [true, false] } chronic_duration_attr :runner_token_expiration_interval_human_readable, :runner_token_expiration_interval diff --git a/config/feature_flags/development/merge_trains_skip_train.yml b/config/feature_flags/development/merge_trains_skip_train.yml new file mode 100644 index 0000000000000000000000000000000000000000..3d60acef4579598ff793ff1004fc57c3bb147581 --- /dev/null +++ b/config/feature_flags/development/merge_trains_skip_train.yml @@ -0,0 +1,8 @@ +--- +name: merge_trains_skip_train +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/129422 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/422111 +milestone: '16.4' +type: development +group: group::pipeline execution +default_enabled: false diff --git a/db/migrate/20230918194153_add_merge_immediately_to_ci_cd_settings.rb b/db/migrate/20230918194153_add_merge_immediately_to_ci_cd_settings.rb new file mode 100644 index 0000000000000000000000000000000000000000..eee1ba6f78176c14beb813c5a04aadd56734e685 --- /dev/null +++ b/db/migrate/20230918194153_add_merge_immediately_to_ci_cd_settings.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class AddMergeImmediatelyToCiCdSettings < Gitlab::Database::Migration[2.1] + enable_lock_retries! + + def up + add_column :project_ci_cd_settings, :merge_trains_skip_train_allowed, :boolean, default: false, null: false + end + + def down + remove_column :project_ci_cd_settings, :merge_trains_skip_train_allowed + end +end diff --git a/db/schema_migrations/20230918194153 b/db/schema_migrations/20230918194153 new file mode 100644 index 0000000000000000000000000000000000000000..2fd045aa9edf53363f34ead83bb4eaea11e5faa6 --- /dev/null +++ b/db/schema_migrations/20230918194153 @@ -0,0 +1 @@ +1ec3edbe609cd0142790b28c3b55e50ae36be4119f741ce970b36fd8a788a2ce \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 622c5988d2ac947e571134e17269ac9598402c15..57d77b05a03a70804a1d6451338299bb7a68491f 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -21348,7 +21348,8 @@ CREATE TABLE project_ci_cd_settings ( separated_caches boolean DEFAULT true NOT NULL, allow_fork_pipelines_to_run_in_parent_project boolean DEFAULT true NOT NULL, inbound_job_token_scope_enabled boolean DEFAULT true NOT NULL, - forward_deployment_rollback_allowed boolean DEFAULT true NOT NULL + forward_deployment_rollback_allowed boolean DEFAULT true NOT NULL, + merge_trains_skip_train_allowed boolean DEFAULT false NOT NULL ); CREATE SEQUENCE project_ci_cd_settings_id_seq diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 17033349edfc5ba40a3ab63159740e911f4dcef3..040a11c649bfdca48d1677d9f32bc9bf90be2261 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -5543,6 +5543,7 @@ Input type: `ProjectCiCdSettingsUpdateInput` | `keepLatestArtifact` | [`Boolean`](#boolean) | Indicates if the latest artifact should be kept for the project. | | `mergePipelinesEnabled` | [`Boolean`](#boolean) | Indicates if merge pipelines are enabled for the project. | | `mergeTrainsEnabled` | [`Boolean`](#boolean) | Indicates if merge trains are enabled for the project. | +| `mergeTrainsSkipTrainAllowed` | [`Boolean`](#boolean) | Indicates whether an option is allowed to merge without refreshing the merge train. Ignored unless the `merge_trains_skip_train` feature flag is also enabled. | #### Fields @@ -23268,6 +23269,7 @@ four standard [pagination arguments](#connection-pagination-arguments): | `keepLatestArtifact` | [`Boolean`](#boolean) | Whether to keep the latest builds artifacts. | | `mergePipelinesEnabled` | [`Boolean`](#boolean) | Whether merge pipelines are enabled. | | `mergeTrainsEnabled` | [`Boolean`](#boolean) | Whether merge trains are enabled. | +| `mergeTrainsSkipTrainAllowed` | [`Boolean!`](#boolean) | Whether merge immediately is allowed for merge trains. | | `project` | [`Project`](#project) | Project the CI/CD settings belong to. | ### `ProjectConversations` diff --git a/ee/app/controllers/ee/projects/settings/merge_requests_controller.rb b/ee/app/controllers/ee/projects/settings/merge_requests_controller.rb index 91f0eab2a7428093031867d3c612536c2412d804..1a0f79a0dc20ce80922f87ad43138c7d31203f51 100644 --- a/ee/app/controllers/ee/projects/settings/merge_requests_controller.rb +++ b/ee/app/controllers/ee/projects/settings/merge_requests_controller.rb @@ -50,6 +50,7 @@ def project_params_ee attrs << %i[merge_pipelines_enabled] if allow_merge_pipelines_params? attrs << %i[merge_trains_enabled] if allow_merge_trains_params? + attrs << %i[merge_trains_skip_train_allowed] if allow_merge_trains_params? attrs << %i[only_allow_merge_if_all_status_checks_passed] if allow_external_status_checks? attrs += merge_request_rules_params diff --git a/ee/app/controllers/ee/projects_controller.rb b/ee/app/controllers/ee/projects_controller.rb index cd299ca893199fa366687eac73618162605f74b0..e901a242fa2590224747d1ccb3f47a459f6b2e46 100644 --- a/ee/app/controllers/ee/projects_controller.rb +++ b/ee/app/controllers/ee/projects_controller.rb @@ -129,6 +129,7 @@ def project_params_ee attrs << %i[merge_pipelines_enabled] if allow_merge_pipelines_params? attrs << %i[merge_trains_enabled] if allow_merge_trains_params? + attrs << %i[merge_trains_skip_train_allowed] if allow_merge_trains_params? attrs += merge_request_rules_params diff --git a/ee/app/graphql/ee/mutations/ci/project_ci_cd_settings_update.rb b/ee/app/graphql/ee/mutations/ci/project_ci_cd_settings_update.rb index 7a401485be50e9d46508deed6d856b7cf9c46eab..475f8655dca717460ba0187ba5bfac8831fe97a0 100644 --- a/ee/app/graphql/ee/mutations/ci/project_ci_cd_settings_update.rb +++ b/ee/app/graphql/ee/mutations/ci/project_ci_cd_settings_update.rb @@ -15,10 +15,19 @@ module ProjectCiCdSettingsUpdate argument :merge_trains_enabled, GraphQL::Types::Boolean, required: false, description: 'Indicates if merge trains are enabled for the project.' + + argument :merge_trains_skip_train_allowed, GraphQL::Types::Boolean, + required: false, + description: 'Indicates whether an option is allowed to merge without refreshing the merge train. ' \ + 'Ignored unless the `merge_trains_skip_train` feature flag is also enabled.' end override :resolve def resolve(full_path:, **args) + if ::Feature.disabled?(:merge_trains_skip_train, project(full_path)) + args.delete(:merge_trains_skip_train_allowed) + end + super.tap do |result| ci_cd_settings = result[:ci_cd_settings] audit_project = ci_cd_settings.project diff --git a/ee/app/graphql/ee/types/ci/ci_cd_setting_type.rb b/ee/app/graphql/ee/types/ci/ci_cd_setting_type.rb new file mode 100644 index 0000000000000000000000000000000000000000..f1b96f5a361a91b8be90c9dc17121518d9560c79 --- /dev/null +++ b/ee/app/graphql/ee/types/ci/ci_cd_setting_type.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module EE + module Types + module Ci + module CiCdSettingType + extend ActiveSupport::Concern + + prepended do + field :merge_trains_skip_train_allowed, + GraphQL::Types::Boolean, + null: false, + description: 'Whether merge immediately is allowed for merge trains.', + method: :merge_trains_skip_train_allowed? + end + end + end + end +end diff --git a/ee/app/models/ee/project.rb b/ee/app/models/ee/project.rb index a05346d4b9dc53aa5ffb37f350d5d88d1c8b9148..3fde1178da93af54ddacd63c5643f4d362e5b9cc 100644 --- a/ee/app/models/ee/project.rb +++ b/ee/app/models/ee/project.rb @@ -333,6 +333,7 @@ def lock_for_confirmation!(id) delegate :merge_pipelines_enabled, :merge_pipelines_enabled=, to: :ci_cd_settings, allow_nil: true delegate :merge_trains_enabled, :merge_trains_enabled=, to: :ci_cd_settings, allow_nil: true + delegate :merge_trains_skip_train_allowed, :merge_trains_skip_train_allowed=, to: :ci_cd_settings, allow_nil: true delegate :auto_rollback_enabled, :auto_rollback_enabled=, to: :ci_cd_settings, allow_nil: true @@ -1111,6 +1112,12 @@ def merge_trains_enabled? ci_cd_settings.merge_trains_enabled? end + def merge_trains_skip_train_allowed? + return false unless ci_cd_settings + + ci_cd_settings.merge_trains_skip_train_allowed? + end + def auto_rollback_enabled? return false unless ci_cd_settings diff --git a/ee/app/models/ee/project_ci_cd_setting.rb b/ee/app/models/ee/project_ci_cd_setting.rb index 7884c3888dcf6181167543f5a43e2be9b35a826d..1d7e03009e1881730ebd172801074690c961d819 100644 --- a/ee/app/models/ee/project_ci_cd_setting.rb +++ b/ee/app/models/ee/project_ci_cd_setting.rb @@ -28,6 +28,10 @@ def auto_rollback_enabled? super && project.feature_available?(:auto_rollback) end + def merge_trains_skip_train_allowed? + merge_trains_skip_train_allowed && ::Feature.enabled?(:merge_trains_skip_train, project) + end + private def merge_trains_disabled?(project) diff --git a/ee/app/views/projects/settings/merge_requests/_merge_trains_settings.html.haml b/ee/app/views/projects/settings/merge_requests/_merge_trains_settings.html.haml index fc12aba5e6c8d3ea5ae5c0155e399642a058738f..41c420a6ba3c41274580b746570e88a15898d5c7 100644 --- a/ee/app/views/projects/settings/merge_requests/_merge_trains_settings.html.haml +++ b/ee/app/views/projects/settings/merge_requests/_merge_trains_settings.html.haml @@ -7,3 +7,8 @@ s_('ProjectSettings|Enable merge trains'), help_text: s_('ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}').html_safe % { link_start: merge_trains_help_link_start, link_end: ''.html_safe }, checkbox_options: { class: 'js-merge-options-merge-trains', data: { qa_selector: 'merge_trains_checkbox' } } + - if Feature.enabled?(:merge_trains_skip_train) + = form.gitlab_ui_checkbox_component :merge_trains_skip_train_allowed, + s_('ProjectSettings|Allow skipping the merge train'), + help_text: s_('ProjectSettings|Merge requests can be set to merge immediately without interrupting the merge train. Commits in earlier merge train pipelines might not get validated with immediately merged commits.'), + checkbox_options: { class: 'js-merge-options-merge-trains-skip-train-allowed' } diff --git a/ee/lib/ee/api/entities/project.rb b/ee/lib/ee/api/entities/project.rb index 346d27cf201d981d2c1498d560ce4ece7f3e0d1f..a2d62c4126395ab5794b5e8a753c3eca498be7fd 100644 --- a/ee/lib/ee/api/entities/project.rb +++ b/ee/lib/ee/api/entities/project.rb @@ -51,6 +51,7 @@ def preload_relation(projects_relation, options = {}) end expose :merge_pipelines_enabled?, as: :merge_pipelines_enabled, if: ->(project, _) { project.feature_available?(:merge_pipelines) } expose :merge_trains_enabled?, as: :merge_trains_enabled, if: ->(project, _) { project.feature_available?(:merge_pipelines) } + expose :merge_trains_skip_train_allowed?, as: :merge_trains_skip_train_allowed, if: ->(project, _) { project.feature_available?(:merge_pipelines) } expose :only_allow_merge_if_all_status_checks_passed, if: ->(project, _) { project.feature_available?(:external_status_checks) } expose :allow_pipeline_trigger_approve_deployment, documentation: { type: 'boolean' }, if: ->(project, _) { project.feature_available?(:protected_environments) } end diff --git a/ee/lib/ee/api/helpers/projects_helpers.rb b/ee/lib/ee/api/helpers/projects_helpers.rb index eb4e53550ed127b2cf852b9c0f5f67e28d209269..d02515cef67ae9d25d5b07559b227bee1f01460c 100644 --- a/ee/lib/ee/api/helpers/projects_helpers.rb +++ b/ee/lib/ee/api/helpers/projects_helpers.rb @@ -42,6 +42,7 @@ module ProjectsHelpers optional :merge_requests_template, type: String, desc: 'Default description for merge requests. Description is parsed with GitLab Flavored Markdown.' optional :merge_pipelines_enabled, type: Grape::API::Boolean, desc: 'Enable merged results pipelines.' optional :merge_trains_enabled, type: Grape::API::Boolean, desc: 'Enable merge trains.' + optional :merge_trains_skip_train_allowed, type: Grape::API::Boolean, desc: 'Allow merge train merge requests to be merged without waiting for pipelines to finish.' end end @@ -65,6 +66,7 @@ def update_params_at_least_one_of :merge_requests_template, :merge_pipelines_enabled, :merge_trains_enabled, + :merge_trains_skip_train_allowed, :requirements_access_level ] end diff --git a/ee/lib/ee/api/projects.rb b/ee/lib/ee/api/projects.rb index 2cf9a1cf754a02c1e17f868ea52d782e2f866bd7..56fe90eff7cf4a8cc65cf6b30801098f0a0f3024 100644 --- a/ee/lib/ee/api/projects.rb +++ b/ee/lib/ee/api/projects.rb @@ -127,6 +127,7 @@ def verify_merge_pipelines_attrs!(project, attrs) attrs.delete(:merge_pipelines_enabled) unless project.feature_available?(:merge_pipelines) attrs.delete(:merge_trains_enabled) unless project.feature_available?(:merge_trains) + attrs.delete(:merge_trains_skip_train_allowed) unless project.feature_available?(:merge_trains) end def check_audit_events_available!(project) diff --git a/ee/spec/controllers/projects/settings/merge_requests_controller_spec.rb b/ee/spec/controllers/projects/settings/merge_requests_controller_spec.rb index 1471a6ca55794eb7135569901521e6fe851ce094..3f2dbbfb6fae24b4259cee3480016cc746010961 100644 --- a/ee/spec/controllers/projects/settings/merge_requests_controller_spec.rb +++ b/ee/spec/controllers/projects/settings/merge_requests_controller_spec.rb @@ -129,6 +129,37 @@ end end + context 'when merge_trains_skip_train_allowed param is specified' do + let(:params) { { merge_trains_skip_train_allowed: true } } + let(:ci_settings) { project.ci_cd_settings } + + let(:request) do + put :update, params: { namespace_id: project.namespace, project_id: project, project: params } + end + + before do + stub_licensed_features(merge_pipelines: true, merge_trains: true) + end + + it 'updates the attribute' do + request + + expect(ci_settings.merge_trains_skip_train_allowed).to be_truthy + end + + context 'when license is not sufficient' do + before do + stub_licensed_features(merge_trains: false) + end + + it 'does not update the attribute' do + request + + expect(ci_settings.merge_trains_skip_train_allowed).to be_falsy + end + end + end + context 'when only_allow_merge_if_all_status_checks_passed param is specified' do let(:params) { { project_setting_attributes: { only_allow_merge_if_all_status_checks_passed: true } } } diff --git a/ee/spec/controllers/projects_controller_spec.rb b/ee/spec/controllers/projects_controller_spec.rb index 4ffc59e1a9d7bd3dbe3297cbcc05ab9d441abfc3..4a062fc9222838d399a515cbcddf1abb7d011feb 100644 --- a/ee/spec/controllers/projects_controller_spec.rb +++ b/ee/spec/controllers/projects_controller_spec.rb @@ -422,6 +422,36 @@ end end + context 'when merge_trains_skip_train_allowed param is specified' do + let(:params) { { merge_trains_skip_train_allowed: true } } + + let(:request) do + put :update, params: { namespace_id: project.namespace, id: project, project: params } + end + + before do + stub_licensed_features(merge_pipelines: true, merge_trains: true) + end + + it 'updates the attribute' do + request + + expect(project.merge_trains_skip_train_allowed).to be_truthy + end + + context 'when license is not sufficient' do + before do + stub_licensed_features(merge_trains: false) + end + + it 'does not update the attribute' do + request + + expect(project.merge_trains_skip_train_allowed).to be_falsy + end + end + end + context 'when auto_rollback_enabled param is specified' do let(:params) { { auto_rollback_enabled: true } } diff --git a/ee/spec/features/projects/settings/merge_requests/merge_trains/enable_merge_trains_skip_train_allowed_spec.rb b/ee/spec/features/projects/settings/merge_requests/merge_trains/enable_merge_trains_skip_train_allowed_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..aea7dc4eb26a7087abcd0588fa0e3471e7105e55 --- /dev/null +++ b/ee/spec/features/projects/settings/merge_requests/merge_trains/enable_merge_trains_skip_train_allowed_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Merge Trains Skip Train Setting', :js, feature_category: :merge_trains do + let_it_be_with_reload(:project) { create(:project) } + let_it_be(:user) { create(:user) } + + before_all do + project.add_maintainer(user) + end + + before do + stub_licensed_features(merge_pipelines: true, merge_trains: true) + sign_in(user) + end + + context 'when visiting the project settings page' do + before do + visit project_settings_merge_requests_path(project) + wait_for_requests + end + + it 'is unchecked by default' do + expect(find('#project_merge_trains_skip_train_allowed')).not_to be_checked + end + + it 'can be enabled' do + page.within('#project-merge-options') do + check _('Allow skipping the merge train') + expect(find('#project_merge_trains_skip_train_allowed')).to be_checked + end + + click_button('Save changes') + + wait_for_requests + + expect(project.ci_cd_settings.merge_trains_skip_train_allowed).to eq(true) + end + end + + context 'when the feature flag is disabled' do + before do + stub_feature_flags(merge_trains_skip_train: false) + end + + it 'does not show the checkbox' do + expect(page).not_to have_checked_field('#project_merge_trains_skip_train_allowed') + end + end +end diff --git a/ee/spec/graphql/ee/mutations/ci/project_ci_cd_settings_update_spec.rb b/ee/spec/graphql/ee/mutations/ci/project_ci_cd_settings_update_spec.rb index d35d538414c777a87b3e7d2850633e66dffbdeef..62cdb81e697e9d65611c6bb0e7ee54c925741f64 100644 --- a/ee/spec/graphql/ee/mutations/ci/project_ci_cd_settings_update_spec.rb +++ b/ee/spec/graphql/ee/mutations/ci/project_ci_cd_settings_update_spec.rb @@ -15,8 +15,11 @@ before do stub_licensed_features(merge_pipelines: true, merge_trains: true) stub_feature_flags(disable_merge_trains: false) - project.merge_pipelines_enabled = nil - project.merge_trains_enabled = false + project.update!( + merge_pipelines_enabled: nil, + merge_trains_enabled: false, + merge_trains_skip_train_allowed: false + ) end describe '#resolve' do @@ -53,6 +56,18 @@ expect(project.merge_trains_enabled?).to eq(true) end end + + context 'when merge_trains_skip_train_allowed is set to true' do + let(:mutation_params) do + { + merge_trains_skip_train_allowed: true + } + end + + it 'updates the value' do + expect(project.ci_cd_settings.merge_trains_skip_train_allowed?).to eq(true) + end + end end describe 'when the inbound_job_token_scope parameter is not provided' do diff --git a/ee/spec/models/ee/project_spec.rb b/ee/spec/models/ee/project_spec.rb index 6d70b3e131fa9378920e402280d466c916d14e90..9b9b40f6a66d67b22f42b61d60dc3b59d055d567 100644 --- a/ee/spec/models/ee/project_spec.rb +++ b/ee/spec/models/ee/project_spec.rb @@ -92,7 +92,8 @@ # EE only 'auto_rollback_enabled' => '', 'merge_pipelines_enabled' => '', - 'merge_trains_enabled' => '' + 'merge_trains_enabled' => '', + 'merge_trains_skip_train_allowed' => '' } end diff --git a/ee/spec/models/project_ci_cd_setting_spec.rb b/ee/spec/models/project_ci_cd_setting_spec.rb index 68db5d8d8545ebb4738c7cf49d30a188546097f0..81d4ce1e7094b2022e058e4a7943bd28b0f6e92c 100644 --- a/ee/spec/models/project_ci_cd_setting_spec.rb +++ b/ee/spec/models/project_ci_cd_setting_spec.rb @@ -9,6 +9,8 @@ stub_feature_flags(disable_merge_trains: false) end + it { is_expected.to validate_inclusion_of(:merge_trains_skip_train_allowed).in_array([true, false]) } + describe '#merge_pipelines_enabled?' do subject { project.merge_pipelines_enabled? } diff --git a/ee/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb b/ee/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..1469eb53fff5dcbef358d528dd39c5a3312a410c --- /dev/null +++ b/ee/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Getting Ci Cd Setting', feature_category: :continuous_integration do + include GraphqlHelpers + + let_it_be_with_reload(:project) { create(:project, :repository) } + let_it_be(:owner) { project.first_owner } + let_it_be(:user) { create(:user) } + + let(:fields) do + <<~QUERY + #{all_graphql_fields_for('ProjectCiCdSetting', max_depth: 1)} + QUERY + end + + let(:query) do + graphql_query_for( + 'project', + { 'fullPath' => project.full_path }, + query_graphql_field('ciCdSettings', {}, fields) + ) + end + + let(:settings_data) { graphql_data['project']['ciCdSettings'] } + + context 'without permissions' do + before_all do + project.add_reporter(user) + end + + before do + post_graphql(query, current_user: user) + end + + it_behaves_like 'a working graphql query' + + specify { expect(settings_data).to be nil } + end + + context 'with project permissions' do + before do + post_graphql(query, current_user: owner) + end + + let(:skip_train_setting) { project.ci_cd_settings.merge_trains_skip_train_allowed? } + + it_behaves_like 'a working graphql query' + + it 'fetches the settings data' do + expect(settings_data['mergeTrainsSkipTrainAllowed']).to eq skip_train_setting + end + end +end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 840af45c1fbdc85b2311926be4554b10a66b052a..860ec9cad7c7da1373e7804546cacb2f102570fb 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -36854,6 +36854,9 @@ msgstr "" msgid "ProjectSettings|Allow anyone to pull from Package Registry" msgstr "" +msgid "ProjectSettings|Allow skipping the merge train" +msgstr "" + msgid "ProjectSettings|Always show thumbs-up and thumbs-down emoji buttons on issues, merge requests, and snippets." msgstr "" @@ -37073,6 +37076,9 @@ msgstr "" msgid "ProjectSettings|Merge requests approved for merge are queued, and pipelines validate the combined results of the source and target branches before merge. %{link_start}What are merge trains?%{link_end}" msgstr "" +msgid "ProjectSettings|Merge requests can be set to merge immediately without interrupting the merge train. Commits in earlier merge train pipelines might not get validated with immediately merged commits." +msgstr "" + msgid "ProjectSettings|Merge suggestions" msgstr "" diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 6193a565d76fb4ac3db45dea20ec88b2c8966895..877da5e81ce3e31c1a4c3a561807196168ed3a6c 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1158,6 +1158,7 @@ merge_pipelines_enabled merge_trains_enabled auto_rollback_enabled + merge_trains_skip_train_allowed ) end end diff --git a/spec/requests/api/project_attributes.yml b/spec/requests/api/project_attributes.yml index 677cb243a7cab02f383a0fd89f0d9ed85b1d98c1..d95f96c25d64140e8dd7ac748c1f9f57beeba49c 100644 --- a/spec/requests/api/project_attributes.yml +++ b/spec/requests/api/project_attributes.yml @@ -94,6 +94,7 @@ ci_cd_settings: - id - project_id - merge_trains_enabled + - merge_trains_skip_train_allowed - merge_pipelines_enabled - auto_rollback_enabled - inbound_job_token_scope_enabled diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml index c2cb29064b69bfd28724ae448f1a014223b887d2..0c530f63e598cf948a0581bf0ae55f7c97e0c6a4 100644 --- a/spec/support/rspec_order_todo.yml +++ b/spec/support/rspec_order_todo.yml @@ -591,7 +591,6 @@ - './ee/spec/graphql/api/vulnerabilities_spec.rb' - './ee/spec/graphql/ee/mutations/boards/issues/issue_move_list_spec.rb' - './ee/spec/graphql/ee/mutations/boards/lists/create_spec.rb' -- './ee/spec/graphql/ee/mutations/ci/project_ci_cd_settings_update_spec.rb' - './ee/spec/graphql/ee/mutations/ci/runner/update_spec.rb' - './ee/spec/graphql/ee/mutations/concerns/mutations/resolves_issuable_spec.rb' - './ee/spec/graphql/ee/resolvers/board_list_issues_resolver_spec.rb'