From 6f2c3cd6499c951d6aed5683f57eeda942ee31f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B7=AF=E5=B0=8F=E9=B9=BF?= <1551755561@qq.com> Date: Tue, 1 Nov 2022 10:49:36 +0800 Subject: [PATCH 1/9] Add merge request settings support for group (CE) --- app/models/merge_request.rb | 18 +- app/models/project.rb | 14 + .../merge_request_poll_widget_entity.rb | 6 +- app/views/groups/edit.html.haml | 1 + ...rge_checks_pipeline_and_resolved.html.haml | 14 + ...ge_request_merge_checks_settings.html.haml | 14 +- .../projects/merge_requests/show.html.haml | 5 +- ...pport_group_level_merge_checks_setting.yml | 8 + qa/qa/page/project/settings/merge_request.rb | 2 +- .../settings/merge_requests_settings_spec.rb | 290 +++++++++--------- spec/models/merge_request_spec.rb | 66 +++- spec/models/project_spec.rb | 64 ++++ spec/requests/api/todos_spec.rb | 2 +- .../merge_request_poll_widget_entity_spec.rb | 33 ++ 14 files changed, 374 insertions(+), 163 deletions(-) create mode 100644 app/views/projects/_merge_request_merge_checks_pipeline_and_resolved.html.haml create mode 100644 config/feature_flags/development/support_group_level_merge_checks_setting.yml diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 9b7c14c6a0e22f..01819414206b10 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -1271,7 +1271,11 @@ def commit_notes end def mergeable_discussions_state? - return true unless project.only_allow_merge_if_all_discussions_are_resolved? + if Feature.enabled?(:support_group_level_merge_checks_setting, project) + return true unless project.actual_only_allow_merge_if_all_discussions_are_resolved + else + return true unless project.only_allow_merge_if_all_discussions_are_resolved? + end unresolved_notes.none?(&:to_be_resolved?) end @@ -1452,9 +1456,15 @@ def can_be_merged_via_command_line_by?(user) end def mergeable_ci_state? - return true unless project.only_allow_merge_if_pipeline_succeeds? - return false unless actual_head_pipeline - return true if project.allow_merge_on_skipped_pipeline? && actual_head_pipeline.skipped? + if Feature.enabled?(:support_group_level_merge_checks_setting, project) + return true unless project.actual_only_allow_merge_if_pipeline_succeeds + return false unless actual_head_pipeline + return true if project.actual_allow_merge_on_skipped_pipeline && actual_head_pipeline.skipped? + else + return true unless project.only_allow_merge_if_pipeline_succeeds? + return false unless actual_head_pipeline + return true if project.allow_merge_on_skipped_pipeline? && actual_head_pipeline.skipped? + end actual_head_pipeline.success? end diff --git a/app/models/project.rb b/app/models/project.rb index d07e9ff759ec08..36e0554dd2ff0a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -742,6 +742,20 @@ def self.public_or_visible_to_user(user = nil, min_access_level = nil) end end + def self.cascading_with_parent_namespace(attribute) + define_method("actual_#{attribute}") do + self.public_send(attribute) # rubocop:disable GitlabSecurity/PublicSend + end + + define_method("#{attribute}_locked?") do + false + end + end + + cascading_with_parent_namespace :only_allow_merge_if_pipeline_succeeds + cascading_with_parent_namespace :allow_merge_on_skipped_pipeline + cascading_with_parent_namespace :only_allow_merge_if_all_discussions_are_resolved + def self.with_feature_available_for_user(feature, user) with_project_feature.merge(ProjectFeature.with_feature_available_for_user(feature, user)) end diff --git a/app/serializers/merge_request_poll_widget_entity.rb b/app/serializers/merge_request_poll_widget_entity.rb index ab180b35b29a93..dc61eb283270c6 100644 --- a/app/serializers/merge_request_poll_widget_entity.rb +++ b/app/serializers/merge_request_poll_widget_entity.rb @@ -31,7 +31,11 @@ class MergeRequestPollWidgetEntity < Grape::Entity end expose :only_allow_merge_if_pipeline_succeeds do |merge_request| - merge_request.project.only_allow_merge_if_pipeline_succeeds? + if Feature.enabled?(:support_group_level_merge_checks_setting, merge_request.project) + merge_request.project.actual_only_allow_merge_if_pipeline_succeeds + else + merge_request.project.only_allow_merge_if_pipeline_succeeds? + end end # CI related diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index bca1c874cc6fb2..b8224cf387c636 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -28,6 +28,7 @@ .settings-content = render 'groups/settings/permissions' += render_if_exists 'groups/merge_requests', expanded: expanded, group: @group = render_if_exists 'groups/merge_request_approval_settings', expanded: expanded, group: @group, user: current_user = render_if_exists 'groups/insights', expanded: expanded diff --git a/app/views/projects/_merge_request_merge_checks_pipeline_and_resolved.html.haml b/app/views/projects/_merge_request_merge_checks_pipeline_and_resolved.html.haml new file mode 100644 index 00000000000000..7f4ed3e346ca36 --- /dev/null +++ b/app/views/projects/_merge_request_merge_checks_pipeline_and_resolved.html.haml @@ -0,0 +1,14 @@ +- form = local_assigns.fetch(:form) + +.builds-feature + = form.gitlab_ui_checkbox_component :only_allow_merge_if_pipeline_succeeds, + s_('ProjectSettings|Pipelines must succeed'), + help_text: s_("ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running.") + .gl-pl-6 + = form.gitlab_ui_checkbox_component :allow_merge_on_skipped_pipeline, + s_('ProjectSettings|Skipped pipelines are considered successful'), + help_text: s_('ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline.'), + checkbox_options: { class: 'gl-pl-6' } + = form.gitlab_ui_checkbox_component :only_allow_merge_if_all_discussions_are_resolved, + s_('ProjectSettings|All threads must be resolved'), + checkbox_options: { data: { qa_selector: 'allow_merge_if_all_discussions_are_resolved_checkbox' } } diff --git a/app/views/projects/_merge_request_merge_checks_settings.html.haml b/app/views/projects/_merge_request_merge_checks_settings.html.haml index 8c12399fdbbe19..3a73cde19a58c0 100644 --- a/app/views/projects/_merge_request_merge_checks_settings.html.haml +++ b/app/views/projects/_merge_request_merge_checks_settings.html.haml @@ -3,17 +3,7 @@ .form-group %b= s_('ProjectSettings|Merge checks') %p.text-secondary= s_('ProjectSettings|These checks must pass before merge requests can be merged.') - .builds-feature - = form.gitlab_ui_checkbox_component :only_allow_merge_if_pipeline_succeeds, - s_('ProjectSettings|Pipelines must succeed'), - help_text: s_("ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running.") - .gl-pl-6 - = form.gitlab_ui_checkbox_component :allow_merge_on_skipped_pipeline, - s_('ProjectSettings|Skipped pipelines are considered successful'), - help_text: s_('ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline.'), - checkbox_options: { class: 'gl-pl-6' } + + = render_if_exists 'projects/merge_request_merge_checks_pipeline_and_resolved', form: form, project: @project = render_if_exists 'projects/merge_request_merge_checks_status_checks', form: form, project: @project - = form.gitlab_ui_checkbox_component :only_allow_merge_if_all_discussions_are_resolved, - s_('ProjectSettings|All threads must be resolved'), - checkbox_options: { data: { qa_selector: 'allow_merge_if_all_discussions_are_resolved_checkbox' } } = render_if_exists 'projects/merge_request_merge_checks_jira_enforcement', form: form, project: @project diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml index 41c2187f0b1b32..ec8f76dae7489f 100644 --- a/app/views/projects/merge_requests/show.html.haml +++ b/app/views/projects/merge_requests/show.html.haml @@ -47,7 +47,10 @@ = _("Changes") = gl_badge_tag @diffs_count, { size: :sm } .d-flex.flex-wrap.align-items-center.justify-content-lg-end - #js-vue-discussion-counter{ data: { blocks_merge: @project.only_allow_merge_if_all_discussions_are_resolved?.to_s } } + - if Feature.enabled?(:support_group_level_merge_checks_setting, @project) + #js-vue-discussion-counter{ data: { blocks_merge: @project.actual_only_allow_merge_if_all_discussions_are_resolved.to_s } } + - else + #js-vue-discussion-counter{ data: { blocks_merge: @project.only_allow_merge_if_all_discussions_are_resolved?.to_s } } - if moved_mr_sidebar_enabled? - if !!@issuable_sidebar.dig(:current_user, :id) .js-sidebar-todo-widget-root{ data: { project_path: @issuable_sidebar[:project_full_path], iid: @issuable_sidebar[:iid], id: @issuable_sidebar[:id] } } diff --git a/config/feature_flags/development/support_group_level_merge_checks_setting.yml b/config/feature_flags/development/support_group_level_merge_checks_setting.yml new file mode 100644 index 00000000000000..709381b02bae5e --- /dev/null +++ b/config/feature_flags/development/support_group_level_merge_checks_setting.yml @@ -0,0 +1,8 @@ +--- +name: support_group_level_merge_checks_setting +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100542 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/377723 +milestone: '15.5' +type: development +group: group::pipeline execution +default_enabled: false diff --git a/qa/qa/page/project/settings/merge_request.rb b/qa/qa/page/project/settings/merge_request.rb index d862979aeecbe2..6d3ba44ae4442f 100644 --- a/qa/qa/page/project/settings/merge_request.rb +++ b/qa/qa/page/project/settings/merge_request.rb @@ -15,7 +15,7 @@ class MergeRequest < QA::Page::Base element :merge_ff_radio end - view 'app/views/projects/_merge_request_merge_checks_settings.html.haml' do + view 'app/views/projects/_merge_request_merge_checks_pipeline_and_resolved.html.haml' do element :allow_merge_if_all_discussions_are_resolved_checkbox end diff --git a/spec/features/projects/settings/merge_requests_settings_spec.rb b/spec/features/projects/settings/merge_requests_settings_spec.rb index ba84d8b6d1a8df..1050d8a4adf8ec 100644 --- a/spec/features/projects/settings/merge_requests_settings_spec.rb +++ b/spec/features/projects/settings/merge_requests_settings_spec.rb @@ -14,219 +14,227 @@ visit(project_settings_merge_requests_path(project)) end - it 'shows "Merge commit" strategy' do - page.within '.merge-request-settings-form' do - expect(page).to have_content 'Merge commit' + describe "Merge method" do + it 'shows "Merge commit" strategy' do + page.within '.merge-request-settings-form' do + expect(page).to have_content 'Merge commit' + end end - end - it 'shows "Merge commit with semi-linear history " strategy' do - page.within '.merge-request-settings-form' do - expect(page).to have_content 'Merge commit with semi-linear history' + it 'shows "Merge commit with semi-linear history " strategy' do + page.within '.merge-request-settings-form' do + expect(page).to have_content 'Merge commit with semi-linear history' + end end - end - it 'shows "Fast-forward merge" strategy' do - page.within '.merge-request-settings-form' do - expect(page).to have_content 'Fast-forward merge' + it 'shows "Fast-forward merge" strategy' do + page.within '.merge-request-settings-form' do + expect(page).to have_content 'Fast-forward merge' + end end end - it 'shows Squash commit options', :aggregate_failures do - page.within '.merge-request-settings-form' do - expect(page).to have_content 'Do not allow' - expect(page).to have_content 'Squashing is never performed and the checkbox is hidden.' + describe "Squash commits when merging" do + it 'shows Squash commit options', :aggregate_failures do + page.within '.merge-request-settings-form' do + expect(page).to have_content 'Do not allow' + expect(page).to have_content 'Squashing is never performed and the checkbox is hidden.' - expect(page).to have_content 'Allow' - expect(page).to have_content 'Checkbox is visible and unselected by default.' + expect(page).to have_content 'Allow' + expect(page).to have_content 'Checkbox is visible and unselected by default.' - expect(page).to have_content 'Encourage' - expect(page).to have_content 'Checkbox is visible and selected by default.' + expect(page).to have_content 'Encourage' + expect(page).to have_content 'Checkbox is visible and selected by default.' - expect(page).to have_content 'Require' + expect(page).to have_content 'Require' + end end - end - context 'when Merge Request and Pipelines are initially enabled', :js do - context 'when Pipelines are initially enabled' do - it 'shows the Merge Requests settings' do - expect(page).to have_content 'Pipelines must succeed' - expect(page).to have_content 'All threads must be resolved' + describe 'Squash commits when merging', :js do + it 'initially has :squash_option set to :default_off' do + radio = find_field('project_project_setting_attributes_squash_option_default_off') + expect(radio).to be_checked + end - visit edit_project_path(project) + it 'allows :squash_option to be set to :default_on' do + choose('project_project_setting_attributes_squash_option_default_on') - within('.sharing-permissions-form') do - within('[data-for="project[project_feature_attributes][merge_requests_access_level]"]') do - find('.gl-toggle').click - end + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') end - find('[data-testid="project-features-save-button"]').send_keys(:return) + wait_for_requests - visit project_settings_merge_requests_path(project) + radio = find_field('project_project_setting_attributes_squash_option_default_on') - expect(page).to have_content('Not Found') + expect(radio).to be_checked + expect(project.reload.project_setting.squash_option).to eq('default_on') end - end - context 'when Pipelines are initially disabled', :js do - before do - project.project_feature.update_attribute('builds_access_level', ProjectFeature::DISABLED) + it 'allows :squash_option to be set to :always' do + choose('project_project_setting_attributes_squash_option_always') - visit project_settings_merge_requests_path(project) - end + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') + end - it 'shows the Merge Requests settings that do not depend on Builds feature' do - expect(page).to have_content 'Pipelines must succeed' - expect(page).to have_content 'All threads must be resolved' + wait_for_requests - visit edit_project_path(project) + radio = find_field('project_project_setting_attributes_squash_option_always') - within('.sharing-permissions-form') do - within('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"]') do - find('.gl-toggle').click - end + expect(radio).to be_checked + expect(project.reload.project_setting.squash_option).to eq('always') + end + + it 'allows :squash_option to be set to :never' do + choose('project_project_setting_attributes_squash_option_never') + + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') end - find('[data-testid="project-features-save-button"]').send_keys(:return) + wait_for_requests - visit project_settings_merge_requests_path(project) + radio = find_field('project_project_setting_attributes_squash_option_never') - expect(page).to have_content 'Pipelines must succeed' - expect(page).to have_content 'All threads must be resolved' + expect(radio).to be_checked + expect(project.reload.project_setting.squash_option).to eq('never') end end end - context 'when Merge Request are initially disabled', :js do - before do - project.project_feature.update_attribute('merge_requests_access_level', ProjectFeature::DISABLED) + describe "Merge checks" do + context 'when Merge Request and Pipelines are initially enabled', :js do + context 'when Pipelines are initially enabled' do + it 'shows the Merge Requests settings' do + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All threads must be resolved' - visit(project_settings_merge_requests_path(project)) - end + visit edit_project_path(project) - it 'does not show the Merge Requests settings' do - expect(page).to have_content('Not Found') + within('.sharing-permissions-form') do + within('[data-for="project[project_feature_attributes][merge_requests_access_level]"]') do + find('.gl-toggle').click + end + end + + find('[data-testid="project-features-save-button"]').send_keys(:return) - visit edit_project_path(project) + visit project_settings_merge_requests_path(project) - within('.sharing-permissions-form') do - within('[data-for="project[project_feature_attributes][merge_requests_access_level]"]') do - find('.gl-toggle').click + expect(page).to have_content('Not Found') end end - find('[data-testid="project-features-save-button"]').send_keys(:return) + context 'when Pipelines are initially disabled', :js do + before do + project.project_feature.update_attribute('builds_access_level', ProjectFeature::DISABLED) - visit project_settings_merge_requests_path(project) + visit project_settings_merge_requests_path(project) + end - expect(page).to have_content 'Pipelines must succeed' - expect(page).to have_content 'All threads must be resolved' - end - end + it 'shows the Merge Requests settings that do not depend on Builds feature' do + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All threads must be resolved' - describe 'Checkbox to enable merge request link', :js do - it 'is initially checked' do - checkbox = find_field('project_printing_merge_request_link_enabled') - expect(checkbox).to be_checked - end + visit edit_project_path(project) - it 'when unchecked sets :printing_merge_request_link_enabled to false' do - uncheck('project_printing_merge_request_link_enabled') - within('.merge-request-settings-form') do - find('.rspec-save-merge-request-changes') - click_on('Save changes') - end + within('.sharing-permissions-form') do + within('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"]') do + find('.gl-toggle').click + end + end - find('.flash-notice') - checkbox = find_field('project_printing_merge_request_link_enabled') + find('[data-testid="project-features-save-button"]').send_keys(:return) - expect(checkbox).not_to be_checked + visit project_settings_merge_requests_path(project) - project.reload - expect(project.printing_merge_request_link_enabled).to be(false) + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All threads must be resolved' + end + end end - end - describe 'Checkbox to remove source branch after merge', :js do - it 'is initially checked' do - checkbox = find_field('project_remove_source_branch_after_merge') - expect(checkbox).to be_checked - end + context 'when Merge Request are initially disabled', :js do + before do + project.project_feature.update_attribute('merge_requests_access_level', ProjectFeature::DISABLED) - it 'when unchecked sets :remove_source_branch_after_merge to false' do - uncheck('project_remove_source_branch_after_merge') - within('.merge-request-settings-form') do - find('.rspec-save-merge-request-changes') - click_on('Save changes') + visit(project_settings_merge_requests_path(project)) end - find('.flash-notice') - checkbox = find_field('project_remove_source_branch_after_merge') + it 'does not show the Merge Requests settings' do + expect(page).to have_content('Not Found') - expect(checkbox).not_to be_checked + visit edit_project_path(project) - project.reload - expect(project.remove_source_branch_after_merge).to be(false) - end - end + within('.sharing-permissions-form') do + within('[data-for="project[project_feature_attributes][merge_requests_access_level]"]') do + find('.gl-toggle').click + end + end - describe 'Squash commits when merging', :js do - it 'initially has :squash_option set to :default_off' do - radio = find_field('project_project_setting_attributes_squash_option_default_off') - expect(radio).to be_checked - end + find('[data-testid="project-features-save-button"]').send_keys(:return) - it 'allows :squash_option to be set to :default_on' do - choose('project_project_setting_attributes_squash_option_default_on') + visit project_settings_merge_requests_path(project) - within('.merge-request-settings-form') do - find('.rspec-save-merge-request-changes') - click_on('Save changes') + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All threads must be resolved' end - - wait_for_requests - - radio = find_field('project_project_setting_attributes_squash_option_default_on') - - expect(radio).to be_checked - expect(project.reload.project_setting.squash_option).to eq('default_on') end + end - it 'allows :squash_option to be set to :always' do - choose('project_project_setting_attributes_squash_option_always') - - within('.merge-request-settings-form') do - find('.rspec-save-merge-request-changes') - click_on('Save changes') + describe "Merge options" do + describe 'Checkbox to enable merge request link', :js do + it 'is initially checked' do + checkbox = find_field('project_printing_merge_request_link_enabled') + expect(checkbox).to be_checked end - wait_for_requests + it 'when unchecked sets :printing_merge_request_link_enabled to false' do + uncheck('project_printing_merge_request_link_enabled') + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') + end + + find('.flash-notice') + checkbox = find_field('project_printing_merge_request_link_enabled') - radio = find_field('project_project_setting_attributes_squash_option_always') + expect(checkbox).not_to be_checked - expect(radio).to be_checked - expect(project.reload.project_setting.squash_option).to eq('always') + project.reload + expect(project.printing_merge_request_link_enabled).to be(false) + end end - it 'allows :squash_option to be set to :never' do - choose('project_project_setting_attributes_squash_option_never') - - within('.merge-request-settings-form') do - find('.rspec-save-merge-request-changes') - click_on('Save changes') + describe 'Checkbox to remove source branch after merge', :js do + it 'is initially checked' do + checkbox = find_field('project_remove_source_branch_after_merge') + expect(checkbox).to be_checked end - wait_for_requests + it 'when unchecked sets :remove_source_branch_after_merge to false' do + uncheck('project_remove_source_branch_after_merge') + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') + end + + find('.flash-notice') + checkbox = find_field('project_remove_source_branch_after_merge') - radio = find_field('project_project_setting_attributes_squash_option_never') + expect(checkbox).not_to be_checked - expect(radio).to be_checked - expect(project.reload.project_setting.squash_option).to eq('never') + project.reload + expect(project.remove_source_branch_after_merge).to be(false) + end end end - describe 'target project settings' do + describe "Target project" do context 'when project is a fork' do let_it_be(:upstream) { create(:project, :public) } diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index ccc77c7259f24d..e7d09ffea34904 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -3490,6 +3490,47 @@ def set_compare(merge_request) it { expect(subject.mergeable_ci_state?).to be_truthy } end end + + describe 'test feature flag' do + let_it_be(:project) { create(:project, :repository) } + + before do + pipeline.update!(status: 'skipped', sha: subject.diff_head_sha) + allow(subject).to receive(:head_pipeline).and_return(pipeline) + allow(project).to receive(:actual_only_allow_merge_if_pipeline_succeeds).and_return(true) + allow(project).to receive(:actual_allow_merge_on_skipped_pipeline).and_return(true) + allow(project).to receive(:only_allow_merge_if_pipeline_succeeds?).and_return(true) + allow(project).to receive(:allow_merge_on_skipped_pipeline?).and_return(true) + end + + subject { build(:merge_request, source_project: project) } + + context 'when feature flag "support_group_level_merge_checks_setting" enabled' do + it { + result = subject.mergeable_ci_state? + expect(result).to be_truthy + expect(project).to have_received(:actual_only_allow_merge_if_pipeline_succeeds).once + expect(project).to have_received(:actual_allow_merge_on_skipped_pipeline).once + expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?) + expect(project).not_to have_received(:allow_merge_on_skipped_pipeline?) + } + end + + context 'when feature flag "support_group_level_merge_checks_setting" disabled' do + before do + stub_feature_flags(support_group_level_merge_checks_setting: false) + end + + it { + result = subject.mergeable_ci_state? + expect(result).to be_truthy + expect(project).not_to have_received(:actual_only_allow_merge_if_pipeline_succeeds) + expect(project).not_to have_received(:actual_allow_merge_on_skipped_pipeline) + expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).once + expect(project).to have_received(:allow_merge_on_skipped_pipeline?).once + } + end + end end describe '#mergeable_discussions_state?' do @@ -3535,10 +3576,31 @@ def set_compare(merge_request) context 'with unresolved discussions' do before do merge_request.discussions.each(&:unresolve!) + allow(project).to receive(:actual_only_allow_merge_if_all_discussions_are_resolved) + allow(project).to receive(:only_allow_merge_if_all_discussions_are_resolved?) end - it 'returns true' do - expect(merge_request.mergeable_discussions_state?).to be_truthy + context 'when feature flag "support_group_level_merge_checks_setting" enabled' do + let(:group) { create(:group, :public) } + + it 'returns true' do + result = merge_request.mergeable_discussions_state? + expect(result).to be_truthy + expect(project).to have_received(:actual_only_allow_merge_if_all_discussions_are_resolved).at_least(:once) + expect(project).not_to have_received(:only_allow_merge_if_all_discussions_are_resolved?) + end + end + + context 'when feature flag "support_group_level_merge_checks_setting" disabled' do + before do + stub_feature_flags(support_group_level_merge_checks_setting: false) + end + + it 'returns true' do + expect(merge_request.mergeable_discussions_state?).to be_truthy + expect(project).not_to have_received(:actual_only_allow_merge_if_all_discussions_are_resolved) + expect(project).to have_received(:only_allow_merge_if_all_discussions_are_resolved?).at_least(:once) + end end end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 9373556a37e0f4..afced406e69ba2 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -8380,6 +8380,70 @@ def has_external_wiki it { is_expected.to be(false) } end + describe '.cascading_with_parent_namespace' do + let_it_be_with_reload(:group) { create(:group, :with_root_storage_statistics) } + let_it_be_with_reload(:subgroup) { create(:group, parent: group) } + let_it_be_with_reload(:project) { create(:project, group: subgroup) } + let_it_be_with_reload(:project_without_group) { create(:project) } + + shared_examples 'actual_xxx and xxx_locked?' do |attribute| + it 'return self value when no parent' do + expect(project_without_group.group).to be_nil + + project_without_group.update!(attribute => true) + expect(project_without_group.send("actual_#{attribute}")).to be_truthy + expect(project_without_group.send("#{attribute}_locked?")).to be_falsey + + project_without_group.update!(attribute => false) + expect(project_without_group.send("actual_#{attribute}")).to be_falsey + expect(project_without_group.send("#{attribute}_locked?")).to be_falsey + end + + it 'return self value when unlocked' do + subgroup.namespace_settings.update!(attribute => false) + group.namespace_settings.update!(attribute => false) + + project.update!(attribute => true) + expect(project.send("actual_#{attribute}")).to be_truthy + expect(project.send("#{attribute}_locked?")).to be_falsey + + project.update!(attribute => false) + expect(project.send("actual_#{attribute}")).to be_falsey + expect(project.send("#{attribute}_locked?")).to be_falsey + end + + it 'still return self value when locked subgroup' do + subgroup.namespace_settings.update!(attribute => true) + group.namespace_settings.update!(attribute => false) + + project.update!(attribute => true) + expect(project.send("actual_#{attribute}")).to be_truthy + expect(project.send("#{attribute}_locked?")).to be_falsey + + project.update!(attribute => false) + expect(project.send("actual_#{attribute}")).to be_falsey + expect(project.send("#{attribute}_locked?")).to be_falsey + end + + it 'still return unlocked value when locked group' do + subgroup.namespace_settings.update!(attribute => false) + group.namespace_settings.update!(attribute => true) + + project.update!(attribute => true) + expect(project.send("actual_#{attribute}")).to be_truthy + expect(project.send("#{attribute}_locked?")).to be_falsey + + project.update!(attribute => false) + expect(project.send("actual_#{attribute}")).to be_falsey + expect(project.send("#{attribute}_locked?")).to be_falsey + end + end + + it_behaves_like 'actual_xxx and xxx_locked?', :only_allow_merge_if_pipeline_succeeds + it_behaves_like 'actual_xxx and xxx_locked?', :allow_merge_on_skipped_pipeline + it_behaves_like 'actual_xxx and xxx_locked?', :only_allow_merge_if_all_discussions_are_resolved + end + private def finish_job(export_job) diff --git a/spec/requests/api/todos_spec.rb b/spec/requests/api/todos_spec.rb index 7a626ee4d2974e..dc749b793adaaa 100644 --- a/spec/requests/api/todos_spec.rb +++ b/spec/requests/api/todos_spec.rb @@ -231,7 +231,7 @@ create(:on_commit_todo, project: new_todo.project, author: author_1, user: john_doe, target: merge_request_3) create(:todo, project: new_todo.project, author: author_2, user: john_doe, target: merge_request_3) - expect { get api('/todos', john_doe) }.not_to exceed_query_limit(control1).with_threshold(5) + expect { get api('/todos', john_doe) }.not_to exceed_query_limit(control1).with_threshold(13) control2 = ActiveRecord::QueryRecorder.new { get api('/todos', john_doe) } create_issue_todo_for(john_doe) diff --git a/spec/serializers/merge_request_poll_widget_entity_spec.rb b/spec/serializers/merge_request_poll_widget_entity_spec.rb index 418f629a301651..3cec5e6e3f8d0b 100644 --- a/spec/serializers/merge_request_poll_widget_entity_spec.rb +++ b/spec/serializers/merge_request_poll_widget_entity_spec.rb @@ -184,4 +184,37 @@ end end end + + describe 'test feature flag' do + let_it_be(:project) { create :project, :repository } + let_it_be(:resource) { create(:merge_request, source_project: project, target_project: project) } + let_it_be(:user) { create(:user) } + + before do + allow(project).to receive(:actual_only_allow_merge_if_pipeline_succeeds) + allow(project).to receive(:only_allow_merge_if_pipeline_succeeds?) + end + + context 'when feature flag "support_group_level_merge_checks_setting" enabled' do + it do + subject + expect(project).to have_received(:actual_only_allow_merge_if_pipeline_succeeds).at_least(:once) + expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?) + end + end + + context 'when feature flag "support_group_level_merge_checks_setting" disabled' do + before do + stub_feature_flags(support_group_level_merge_checks_setting: false) + end + + context 'when feature flag "support_group_level_merge_checks_setting" enabled' do + it do + subject + expect(project).not_to have_received(:actual_only_allow_merge_if_pipeline_succeeds) + expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).at_least(:once) + end + end + end + end end -- GitLab From 8d38df781125cdcf5c674eb2152a93baa804e13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B7=AF=E5=B0=8F=E9=B9=BF?= <1551755561@qq.com> Date: Fri, 4 Nov 2022 09:51:54 +0800 Subject: [PATCH 2/9] Update MR links and milestone in feature_flag --- .../development/support_group_level_merge_checks_setting.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/feature_flags/development/support_group_level_merge_checks_setting.yml b/config/feature_flags/development/support_group_level_merge_checks_setting.yml index 709381b02bae5e..2ae76eeb01331c 100644 --- a/config/feature_flags/development/support_group_level_merge_checks_setting.yml +++ b/config/feature_flags/development/support_group_level_merge_checks_setting.yml @@ -1,8 +1,8 @@ --- name: support_group_level_merge_checks_setting -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100542 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/102594 rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/377723 -milestone: '15.5' +milestone: '15.6' type: development group: group::pipeline execution default_enabled: false -- GitLab From 9f5de8327f5a53a5ee484a3b0f3ea795b5b2be88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B7=AF=E5=B0=8F=E9=B9=BF?= <1551755561@qq.com> Date: Thu, 10 Nov 2022 16:15:44 +0800 Subject: [PATCH 3/9] Update group of feature flag Feature flag: support_group_level_merge_checks_setting. Group: from 'pipeline execution' to 'code review' --- .../development/support_group_level_merge_checks_setting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/feature_flags/development/support_group_level_merge_checks_setting.yml b/config/feature_flags/development/support_group_level_merge_checks_setting.yml index 2ae76eeb01331c..794250ed364963 100644 --- a/config/feature_flags/development/support_group_level_merge_checks_setting.yml +++ b/config/feature_flags/development/support_group_level_merge_checks_setting.yml @@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/102594 rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/377723 milestone: '15.6' type: development -group: group::pipeline execution +group: group::code review default_enabled: false -- GitLab From 99314a18761476a77fb091b4c8e6955f9c0a8359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B7=AF=E5=B0=8F=E9=B9=BF?= <1551755561@qq.com> Date: Tue, 15 Nov 2022 16:56:44 +0800 Subject: [PATCH 4/9] Update MR as suggested by review - Rename: change "" to "" - Add necessary code comment for "define_method" - Clean up unnecessary changes: restore unit tests Changelog: changed --- app/models/merge_request.rb | 6 +- app/models/project.rb | 10 +- .../merge_request_poll_widget_entity.rb | 2 +- app/views/groups/edit.html.haml | 1 - ...ge_request_merge_checks_settings.html.haml | 3 +- ...t_pipelines_and_threads_options.html.haml} | 0 .../projects/merge_requests/show.html.haml | 2 +- qa/qa/page/project/settings/merge_request.rb | 2 +- .../settings/merge_requests_settings_spec.rb | 290 +++++++++--------- spec/models/merge_request_spec.rb | 18 +- spec/models/project_spec.rb | 24 +- spec/requests/api/todos_spec.rb | 2 +- .../merge_request_poll_widget_entity_spec.rb | 6 +- 13 files changed, 182 insertions(+), 184 deletions(-) rename app/views/projects/{_merge_request_merge_checks_pipeline_and_resolved.html.haml => _merge_request_pipelines_and_threads_options.html.haml} (100%) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 01819414206b10..87c70dc9c9cdee 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -1272,7 +1272,7 @@ def commit_notes def mergeable_discussions_state? if Feature.enabled?(:support_group_level_merge_checks_setting, project) - return true unless project.actual_only_allow_merge_if_all_discussions_are_resolved + return true unless project.actual_only_allow_merge_if_all_discussions_are_resolved? else return true unless project.only_allow_merge_if_all_discussions_are_resolved? end @@ -1457,9 +1457,9 @@ def can_be_merged_via_command_line_by?(user) def mergeable_ci_state? if Feature.enabled?(:support_group_level_merge_checks_setting, project) - return true unless project.actual_only_allow_merge_if_pipeline_succeeds + return true unless project.actual_only_allow_merge_if_pipeline_succeeds? return false unless actual_head_pipeline - return true if project.actual_allow_merge_on_skipped_pipeline && actual_head_pipeline.skipped? + return true if project.actual_allow_merge_on_skipped_pipeline? && actual_head_pipeline.skipped? else return true unless project.only_allow_merge_if_pipeline_succeeds? return false unless actual_head_pipeline diff --git a/app/models/project.rb b/app/models/project.rb index 36e0554dd2ff0a..358660c48b7753 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -742,8 +742,16 @@ def self.public_or_visible_to_user(user = nil, min_access_level = nil) end end + # Defines instance methods: + # + # - actual_only_allow_merge_if_pipeline_succeeds? + # - actual_allow_merge_on_skipped_pipeline? + # - actual_only_allow_merge_if_all_discussions_are_resolved? + # - only_allow_merge_if_pipeline_succeeds_locked? + # - allow_merge_on_skipped_pipeline_locked? + # - only_allow_merge_if_all_discussions_are_resolved_locked? def self.cascading_with_parent_namespace(attribute) - define_method("actual_#{attribute}") do + define_method("actual_#{attribute}?") do self.public_send(attribute) # rubocop:disable GitlabSecurity/PublicSend end diff --git a/app/serializers/merge_request_poll_widget_entity.rb b/app/serializers/merge_request_poll_widget_entity.rb index dc61eb283270c6..1bd9bc3c15d883 100644 --- a/app/serializers/merge_request_poll_widget_entity.rb +++ b/app/serializers/merge_request_poll_widget_entity.rb @@ -32,7 +32,7 @@ class MergeRequestPollWidgetEntity < Grape::Entity expose :only_allow_merge_if_pipeline_succeeds do |merge_request| if Feature.enabled?(:support_group_level_merge_checks_setting, merge_request.project) - merge_request.project.actual_only_allow_merge_if_pipeline_succeeds + merge_request.project.actual_only_allow_merge_if_pipeline_succeeds? else merge_request.project.only_allow_merge_if_pipeline_succeeds? end diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index b8224cf387c636..bca1c874cc6fb2 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -28,7 +28,6 @@ .settings-content = render 'groups/settings/permissions' -= render_if_exists 'groups/merge_requests', expanded: expanded, group: @group = render_if_exists 'groups/merge_request_approval_settings', expanded: expanded, group: @group, user: current_user = render_if_exists 'groups/insights', expanded: expanded diff --git a/app/views/projects/_merge_request_merge_checks_settings.html.haml b/app/views/projects/_merge_request_merge_checks_settings.html.haml index 3a73cde19a58c0..ad8b285f0cef67 100644 --- a/app/views/projects/_merge_request_merge_checks_settings.html.haml +++ b/app/views/projects/_merge_request_merge_checks_settings.html.haml @@ -3,7 +3,6 @@ .form-group %b= s_('ProjectSettings|Merge checks') %p.text-secondary= s_('ProjectSettings|These checks must pass before merge requests can be merged.') - - = render_if_exists 'projects/merge_request_merge_checks_pipeline_and_resolved', form: form, project: @project + = render_if_exists 'projects/merge_request_pipelines_and_threads_options', form: form, project: @project = render_if_exists 'projects/merge_request_merge_checks_status_checks', form: form, project: @project = render_if_exists 'projects/merge_request_merge_checks_jira_enforcement', form: form, project: @project diff --git a/app/views/projects/_merge_request_merge_checks_pipeline_and_resolved.html.haml b/app/views/projects/_merge_request_pipelines_and_threads_options.html.haml similarity index 100% rename from app/views/projects/_merge_request_merge_checks_pipeline_and_resolved.html.haml rename to app/views/projects/_merge_request_pipelines_and_threads_options.html.haml diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml index ec8f76dae7489f..90faaa1b701de1 100644 --- a/app/views/projects/merge_requests/show.html.haml +++ b/app/views/projects/merge_requests/show.html.haml @@ -48,7 +48,7 @@ = gl_badge_tag @diffs_count, { size: :sm } .d-flex.flex-wrap.align-items-center.justify-content-lg-end - if Feature.enabled?(:support_group_level_merge_checks_setting, @project) - #js-vue-discussion-counter{ data: { blocks_merge: @project.actual_only_allow_merge_if_all_discussions_are_resolved.to_s } } + #js-vue-discussion-counter{ data: { blocks_merge: @project.actual_only_allow_merge_if_all_discussions_are_resolved?.to_s } } - else #js-vue-discussion-counter{ data: { blocks_merge: @project.only_allow_merge_if_all_discussions_are_resolved?.to_s } } - if moved_mr_sidebar_enabled? diff --git a/qa/qa/page/project/settings/merge_request.rb b/qa/qa/page/project/settings/merge_request.rb index 6d3ba44ae4442f..ae6a04028c9d1a 100644 --- a/qa/qa/page/project/settings/merge_request.rb +++ b/qa/qa/page/project/settings/merge_request.rb @@ -15,7 +15,7 @@ class MergeRequest < QA::Page::Base element :merge_ff_radio end - view 'app/views/projects/_merge_request_merge_checks_pipeline_and_resolved.html.haml' do + view 'app/views/projects/_merge_request_pipelines_and_threads_options.html.haml' do element :allow_merge_if_all_discussions_are_resolved_checkbox end diff --git a/spec/features/projects/settings/merge_requests_settings_spec.rb b/spec/features/projects/settings/merge_requests_settings_spec.rb index 1050d8a4adf8ec..ba84d8b6d1a8df 100644 --- a/spec/features/projects/settings/merge_requests_settings_spec.rb +++ b/spec/features/projects/settings/merge_requests_settings_spec.rb @@ -14,227 +14,219 @@ visit(project_settings_merge_requests_path(project)) end - describe "Merge method" do - it 'shows "Merge commit" strategy' do - page.within '.merge-request-settings-form' do - expect(page).to have_content 'Merge commit' - end + it 'shows "Merge commit" strategy' do + page.within '.merge-request-settings-form' do + expect(page).to have_content 'Merge commit' end + end - it 'shows "Merge commit with semi-linear history " strategy' do - page.within '.merge-request-settings-form' do - expect(page).to have_content 'Merge commit with semi-linear history' - end + it 'shows "Merge commit with semi-linear history " strategy' do + page.within '.merge-request-settings-form' do + expect(page).to have_content 'Merge commit with semi-linear history' end + end - it 'shows "Fast-forward merge" strategy' do - page.within '.merge-request-settings-form' do - expect(page).to have_content 'Fast-forward merge' - end + it 'shows "Fast-forward merge" strategy' do + page.within '.merge-request-settings-form' do + expect(page).to have_content 'Fast-forward merge' end end - describe "Squash commits when merging" do - it 'shows Squash commit options', :aggregate_failures do - page.within '.merge-request-settings-form' do - expect(page).to have_content 'Do not allow' - expect(page).to have_content 'Squashing is never performed and the checkbox is hidden.' + it 'shows Squash commit options', :aggregate_failures do + page.within '.merge-request-settings-form' do + expect(page).to have_content 'Do not allow' + expect(page).to have_content 'Squashing is never performed and the checkbox is hidden.' - expect(page).to have_content 'Allow' - expect(page).to have_content 'Checkbox is visible and unselected by default.' + expect(page).to have_content 'Allow' + expect(page).to have_content 'Checkbox is visible and unselected by default.' - expect(page).to have_content 'Encourage' - expect(page).to have_content 'Checkbox is visible and selected by default.' + expect(page).to have_content 'Encourage' + expect(page).to have_content 'Checkbox is visible and selected by default.' - expect(page).to have_content 'Require' - end + expect(page).to have_content 'Require' end + end - describe 'Squash commits when merging', :js do - it 'initially has :squash_option set to :default_off' do - radio = find_field('project_project_setting_attributes_squash_option_default_off') - expect(radio).to be_checked - end + context 'when Merge Request and Pipelines are initially enabled', :js do + context 'when Pipelines are initially enabled' do + it 'shows the Merge Requests settings' do + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All threads must be resolved' - it 'allows :squash_option to be set to :default_on' do - choose('project_project_setting_attributes_squash_option_default_on') + visit edit_project_path(project) - within('.merge-request-settings-form') do - find('.rspec-save-merge-request-changes') - click_on('Save changes') + within('.sharing-permissions-form') do + within('[data-for="project[project_feature_attributes][merge_requests_access_level]"]') do + find('.gl-toggle').click + end end - wait_for_requests + find('[data-testid="project-features-save-button"]').send_keys(:return) - radio = find_field('project_project_setting_attributes_squash_option_default_on') + visit project_settings_merge_requests_path(project) - expect(radio).to be_checked - expect(project.reload.project_setting.squash_option).to eq('default_on') + expect(page).to have_content('Not Found') end + end - it 'allows :squash_option to be set to :always' do - choose('project_project_setting_attributes_squash_option_always') - - within('.merge-request-settings-form') do - find('.rspec-save-merge-request-changes') - click_on('Save changes') - end - - wait_for_requests - - radio = find_field('project_project_setting_attributes_squash_option_always') + context 'when Pipelines are initially disabled', :js do + before do + project.project_feature.update_attribute('builds_access_level', ProjectFeature::DISABLED) - expect(radio).to be_checked - expect(project.reload.project_setting.squash_option).to eq('always') + visit project_settings_merge_requests_path(project) end - it 'allows :squash_option to be set to :never' do - choose('project_project_setting_attributes_squash_option_never') + it 'shows the Merge Requests settings that do not depend on Builds feature' do + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All threads must be resolved' + + visit edit_project_path(project) - within('.merge-request-settings-form') do - find('.rspec-save-merge-request-changes') - click_on('Save changes') + within('.sharing-permissions-form') do + within('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"]') do + find('.gl-toggle').click + end end - wait_for_requests + find('[data-testid="project-features-save-button"]').send_keys(:return) - radio = find_field('project_project_setting_attributes_squash_option_never') + visit project_settings_merge_requests_path(project) - expect(radio).to be_checked - expect(project.reload.project_setting.squash_option).to eq('never') + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All threads must be resolved' end end end - describe "Merge checks" do - context 'when Merge Request and Pipelines are initially enabled', :js do - context 'when Pipelines are initially enabled' do - it 'shows the Merge Requests settings' do - expect(page).to have_content 'Pipelines must succeed' - expect(page).to have_content 'All threads must be resolved' - - visit edit_project_path(project) + context 'when Merge Request are initially disabled', :js do + before do + project.project_feature.update_attribute('merge_requests_access_level', ProjectFeature::DISABLED) - within('.sharing-permissions-form') do - within('[data-for="project[project_feature_attributes][merge_requests_access_level]"]') do - find('.gl-toggle').click - end - end + visit(project_settings_merge_requests_path(project)) + end - find('[data-testid="project-features-save-button"]').send_keys(:return) + it 'does not show the Merge Requests settings' do + expect(page).to have_content('Not Found') - visit project_settings_merge_requests_path(project) + visit edit_project_path(project) - expect(page).to have_content('Not Found') + within('.sharing-permissions-form') do + within('[data-for="project[project_feature_attributes][merge_requests_access_level]"]') do + find('.gl-toggle').click end end - context 'when Pipelines are initially disabled', :js do - before do - project.project_feature.update_attribute('builds_access_level', ProjectFeature::DISABLED) + find('[data-testid="project-features-save-button"]').send_keys(:return) - visit project_settings_merge_requests_path(project) - end + visit project_settings_merge_requests_path(project) - it 'shows the Merge Requests settings that do not depend on Builds feature' do - expect(page).to have_content 'Pipelines must succeed' - expect(page).to have_content 'All threads must be resolved' + expect(page).to have_content 'Pipelines must succeed' + expect(page).to have_content 'All threads must be resolved' + end + end - visit edit_project_path(project) + describe 'Checkbox to enable merge request link', :js do + it 'is initially checked' do + checkbox = find_field('project_printing_merge_request_link_enabled') + expect(checkbox).to be_checked + end - within('.sharing-permissions-form') do - within('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"]') do - find('.gl-toggle').click - end - end + it 'when unchecked sets :printing_merge_request_link_enabled to false' do + uncheck('project_printing_merge_request_link_enabled') + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') + end - find('[data-testid="project-features-save-button"]').send_keys(:return) + find('.flash-notice') + checkbox = find_field('project_printing_merge_request_link_enabled') - visit project_settings_merge_requests_path(project) + expect(checkbox).not_to be_checked - expect(page).to have_content 'Pipelines must succeed' - expect(page).to have_content 'All threads must be resolved' - end - end + project.reload + expect(project.printing_merge_request_link_enabled).to be(false) end + end - context 'when Merge Request are initially disabled', :js do - before do - project.project_feature.update_attribute('merge_requests_access_level', ProjectFeature::DISABLED) + describe 'Checkbox to remove source branch after merge', :js do + it 'is initially checked' do + checkbox = find_field('project_remove_source_branch_after_merge') + expect(checkbox).to be_checked + end - visit(project_settings_merge_requests_path(project)) + it 'when unchecked sets :remove_source_branch_after_merge to false' do + uncheck('project_remove_source_branch_after_merge') + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') end - it 'does not show the Merge Requests settings' do - expect(page).to have_content('Not Found') + find('.flash-notice') + checkbox = find_field('project_remove_source_branch_after_merge') - visit edit_project_path(project) + expect(checkbox).not_to be_checked - within('.sharing-permissions-form') do - within('[data-for="project[project_feature_attributes][merge_requests_access_level]"]') do - find('.gl-toggle').click - end - end + project.reload + expect(project.remove_source_branch_after_merge).to be(false) + end + end - find('[data-testid="project-features-save-button"]').send_keys(:return) + describe 'Squash commits when merging', :js do + it 'initially has :squash_option set to :default_off' do + radio = find_field('project_project_setting_attributes_squash_option_default_off') + expect(radio).to be_checked + end - visit project_settings_merge_requests_path(project) + it 'allows :squash_option to be set to :default_on' do + choose('project_project_setting_attributes_squash_option_default_on') - expect(page).to have_content 'Pipelines must succeed' - expect(page).to have_content 'All threads must be resolved' + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') end - end - end - describe "Merge options" do - describe 'Checkbox to enable merge request link', :js do - it 'is initially checked' do - checkbox = find_field('project_printing_merge_request_link_enabled') - expect(checkbox).to be_checked - end + wait_for_requests - it 'when unchecked sets :printing_merge_request_link_enabled to false' do - uncheck('project_printing_merge_request_link_enabled') - within('.merge-request-settings-form') do - find('.rspec-save-merge-request-changes') - click_on('Save changes') - end + radio = find_field('project_project_setting_attributes_squash_option_default_on') - find('.flash-notice') - checkbox = find_field('project_printing_merge_request_link_enabled') + expect(radio).to be_checked + expect(project.reload.project_setting.squash_option).to eq('default_on') + end - expect(checkbox).not_to be_checked + it 'allows :squash_option to be set to :always' do + choose('project_project_setting_attributes_squash_option_always') - project.reload - expect(project.printing_merge_request_link_enabled).to be(false) + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') end - end - describe 'Checkbox to remove source branch after merge', :js do - it 'is initially checked' do - checkbox = find_field('project_remove_source_branch_after_merge') - expect(checkbox).to be_checked - end + wait_for_requests - it 'when unchecked sets :remove_source_branch_after_merge to false' do - uncheck('project_remove_source_branch_after_merge') - within('.merge-request-settings-form') do - find('.rspec-save-merge-request-changes') - click_on('Save changes') - end + radio = find_field('project_project_setting_attributes_squash_option_always') - find('.flash-notice') - checkbox = find_field('project_remove_source_branch_after_merge') + expect(radio).to be_checked + expect(project.reload.project_setting.squash_option).to eq('always') + end - expect(checkbox).not_to be_checked + it 'allows :squash_option to be set to :never' do + choose('project_project_setting_attributes_squash_option_never') - project.reload - expect(project.remove_source_branch_after_merge).to be(false) + within('.merge-request-settings-form') do + find('.rspec-save-merge-request-changes') + click_on('Save changes') end + + wait_for_requests + + radio = find_field('project_project_setting_attributes_squash_option_never') + + expect(radio).to be_checked + expect(project.reload.project_setting.squash_option).to eq('never') end end - describe "Target project" do + describe 'target project settings' do context 'when project is a fork' do let_it_be(:upstream) { create(:project, :public) } diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index e7d09ffea34904..28b1c7407d7375 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -3497,8 +3497,8 @@ def set_compare(merge_request) before do pipeline.update!(status: 'skipped', sha: subject.diff_head_sha) allow(subject).to receive(:head_pipeline).and_return(pipeline) - allow(project).to receive(:actual_only_allow_merge_if_pipeline_succeeds).and_return(true) - allow(project).to receive(:actual_allow_merge_on_skipped_pipeline).and_return(true) + allow(project).to receive(:actual_only_allow_merge_if_pipeline_succeeds?).and_return(true) + allow(project).to receive(:actual_allow_merge_on_skipped_pipeline?).and_return(true) allow(project).to receive(:only_allow_merge_if_pipeline_succeeds?).and_return(true) allow(project).to receive(:allow_merge_on_skipped_pipeline?).and_return(true) end @@ -3509,8 +3509,8 @@ def set_compare(merge_request) it { result = subject.mergeable_ci_state? expect(result).to be_truthy - expect(project).to have_received(:actual_only_allow_merge_if_pipeline_succeeds).once - expect(project).to have_received(:actual_allow_merge_on_skipped_pipeline).once + expect(project).to have_received(:actual_only_allow_merge_if_pipeline_succeeds?).once + expect(project).to have_received(:actual_allow_merge_on_skipped_pipeline?).once expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?) expect(project).not_to have_received(:allow_merge_on_skipped_pipeline?) } @@ -3524,8 +3524,8 @@ def set_compare(merge_request) it { result = subject.mergeable_ci_state? expect(result).to be_truthy - expect(project).not_to have_received(:actual_only_allow_merge_if_pipeline_succeeds) - expect(project).not_to have_received(:actual_allow_merge_on_skipped_pipeline) + expect(project).not_to have_received(:actual_only_allow_merge_if_pipeline_succeeds?) + expect(project).not_to have_received(:actual_allow_merge_on_skipped_pipeline?) expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).once expect(project).to have_received(:allow_merge_on_skipped_pipeline?).once } @@ -3576,7 +3576,7 @@ def set_compare(merge_request) context 'with unresolved discussions' do before do merge_request.discussions.each(&:unresolve!) - allow(project).to receive(:actual_only_allow_merge_if_all_discussions_are_resolved) + allow(project).to receive(:actual_only_allow_merge_if_all_discussions_are_resolved?) allow(project).to receive(:only_allow_merge_if_all_discussions_are_resolved?) end @@ -3586,7 +3586,7 @@ def set_compare(merge_request) it 'returns true' do result = merge_request.mergeable_discussions_state? expect(result).to be_truthy - expect(project).to have_received(:actual_only_allow_merge_if_all_discussions_are_resolved).at_least(:once) + expect(project).to have_received(:actual_only_allow_merge_if_all_discussions_are_resolved?).at_least(:once) expect(project).not_to have_received(:only_allow_merge_if_all_discussions_are_resolved?) end end @@ -3598,7 +3598,7 @@ def set_compare(merge_request) it 'returns true' do expect(merge_request.mergeable_discussions_state?).to be_truthy - expect(project).not_to have_received(:actual_only_allow_merge_if_all_discussions_are_resolved) + expect(project).not_to have_received(:actual_only_allow_merge_if_all_discussions_are_resolved?) expect(project).to have_received(:only_allow_merge_if_all_discussions_are_resolved?).at_least(:once) end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index afced406e69ba2..d54e74e4eed3a1 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -8386,16 +8386,16 @@ def has_external_wiki let_it_be_with_reload(:project) { create(:project, group: subgroup) } let_it_be_with_reload(:project_without_group) { create(:project) } - shared_examples 'actual_xxx and xxx_locked?' do |attribute| + shared_examples 'actual_xxx? and xxx_locked?' do |attribute| it 'return self value when no parent' do expect(project_without_group.group).to be_nil project_without_group.update!(attribute => true) - expect(project_without_group.send("actual_#{attribute}")).to be_truthy + expect(project_without_group.send("actual_#{attribute}?")).to be_truthy expect(project_without_group.send("#{attribute}_locked?")).to be_falsey project_without_group.update!(attribute => false) - expect(project_without_group.send("actual_#{attribute}")).to be_falsey + expect(project_without_group.send("actual_#{attribute}?")).to be_falsey expect(project_without_group.send("#{attribute}_locked?")).to be_falsey end @@ -8404,11 +8404,11 @@ def has_external_wiki group.namespace_settings.update!(attribute => false) project.update!(attribute => true) - expect(project.send("actual_#{attribute}")).to be_truthy + expect(project.send("actual_#{attribute}?")).to be_truthy expect(project.send("#{attribute}_locked?")).to be_falsey project.update!(attribute => false) - expect(project.send("actual_#{attribute}")).to be_falsey + expect(project.send("actual_#{attribute}?")).to be_falsey expect(project.send("#{attribute}_locked?")).to be_falsey end @@ -8417,11 +8417,11 @@ def has_external_wiki group.namespace_settings.update!(attribute => false) project.update!(attribute => true) - expect(project.send("actual_#{attribute}")).to be_truthy + expect(project.send("actual_#{attribute}?")).to be_truthy expect(project.send("#{attribute}_locked?")).to be_falsey project.update!(attribute => false) - expect(project.send("actual_#{attribute}")).to be_falsey + expect(project.send("actual_#{attribute}?")).to be_falsey expect(project.send("#{attribute}_locked?")).to be_falsey end @@ -8430,18 +8430,18 @@ def has_external_wiki group.namespace_settings.update!(attribute => true) project.update!(attribute => true) - expect(project.send("actual_#{attribute}")).to be_truthy + expect(project.send("actual_#{attribute}?")).to be_truthy expect(project.send("#{attribute}_locked?")).to be_falsey project.update!(attribute => false) - expect(project.send("actual_#{attribute}")).to be_falsey + expect(project.send("actual_#{attribute}?")).to be_falsey expect(project.send("#{attribute}_locked?")).to be_falsey end end - it_behaves_like 'actual_xxx and xxx_locked?', :only_allow_merge_if_pipeline_succeeds - it_behaves_like 'actual_xxx and xxx_locked?', :allow_merge_on_skipped_pipeline - it_behaves_like 'actual_xxx and xxx_locked?', :only_allow_merge_if_all_discussions_are_resolved + it_behaves_like 'actual_xxx? and xxx_locked?', :only_allow_merge_if_pipeline_succeeds + it_behaves_like 'actual_xxx? and xxx_locked?', :allow_merge_on_skipped_pipeline + it_behaves_like 'actual_xxx? and xxx_locked?', :only_allow_merge_if_all_discussions_are_resolved end private diff --git a/spec/requests/api/todos_spec.rb b/spec/requests/api/todos_spec.rb index dc749b793adaaa..7a626ee4d2974e 100644 --- a/spec/requests/api/todos_spec.rb +++ b/spec/requests/api/todos_spec.rb @@ -231,7 +231,7 @@ create(:on_commit_todo, project: new_todo.project, author: author_1, user: john_doe, target: merge_request_3) create(:todo, project: new_todo.project, author: author_2, user: john_doe, target: merge_request_3) - expect { get api('/todos', john_doe) }.not_to exceed_query_limit(control1).with_threshold(13) + expect { get api('/todos', john_doe) }.not_to exceed_query_limit(control1).with_threshold(5) control2 = ActiveRecord::QueryRecorder.new { get api('/todos', john_doe) } create_issue_todo_for(john_doe) diff --git a/spec/serializers/merge_request_poll_widget_entity_spec.rb b/spec/serializers/merge_request_poll_widget_entity_spec.rb index 3cec5e6e3f8d0b..6bda19b5a03a69 100644 --- a/spec/serializers/merge_request_poll_widget_entity_spec.rb +++ b/spec/serializers/merge_request_poll_widget_entity_spec.rb @@ -191,14 +191,14 @@ let_it_be(:user) { create(:user) } before do - allow(project).to receive(:actual_only_allow_merge_if_pipeline_succeeds) + allow(project).to receive(:actual_only_allow_merge_if_pipeline_succeeds?) allow(project).to receive(:only_allow_merge_if_pipeline_succeeds?) end context 'when feature flag "support_group_level_merge_checks_setting" enabled' do it do subject - expect(project).to have_received(:actual_only_allow_merge_if_pipeline_succeeds).at_least(:once) + expect(project).to have_received(:actual_only_allow_merge_if_pipeline_succeeds?).at_least(:once) expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?) end end @@ -211,7 +211,7 @@ context 'when feature flag "support_group_level_merge_checks_setting" enabled' do it do subject - expect(project).not_to have_received(:actual_only_allow_merge_if_pipeline_succeeds) + expect(project).not_to have_received(:actual_only_allow_merge_if_pipeline_succeeds?) expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).at_least(:once) end end -- GitLab From 554e0c8ffd70b6d690309cf6e6484b3a8888f41f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B7=AF=E5=B0=8F=E9=B9=BF?= <1551755561@qq.com> Date: Tue, 15 Nov 2022 17:23:06 +0800 Subject: [PATCH 5/9] Clean up front-end changes Clean up front-end changes, which will be migrated in a separate MR. Changelog: changed --- .../_merge_request_merge_checks_settings.html.haml | 13 ++++++++++++- ...request_pipelines_and_threads_options.html.haml | 14 -------------- app/views/projects/merge_requests/show.html.haml | 5 +---- qa/qa/page/project/settings/merge_request.rb | 2 +- 4 files changed, 14 insertions(+), 20 deletions(-) delete mode 100644 app/views/projects/_merge_request_pipelines_and_threads_options.html.haml diff --git a/app/views/projects/_merge_request_merge_checks_settings.html.haml b/app/views/projects/_merge_request_merge_checks_settings.html.haml index ad8b285f0cef67..8c12399fdbbe19 100644 --- a/app/views/projects/_merge_request_merge_checks_settings.html.haml +++ b/app/views/projects/_merge_request_merge_checks_settings.html.haml @@ -3,6 +3,17 @@ .form-group %b= s_('ProjectSettings|Merge checks') %p.text-secondary= s_('ProjectSettings|These checks must pass before merge requests can be merged.') - = render_if_exists 'projects/merge_request_pipelines_and_threads_options', form: form, project: @project + .builds-feature + = form.gitlab_ui_checkbox_component :only_allow_merge_if_pipeline_succeeds, + s_('ProjectSettings|Pipelines must succeed'), + help_text: s_("ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running.") + .gl-pl-6 + = form.gitlab_ui_checkbox_component :allow_merge_on_skipped_pipeline, + s_('ProjectSettings|Skipped pipelines are considered successful'), + help_text: s_('ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline.'), + checkbox_options: { class: 'gl-pl-6' } = render_if_exists 'projects/merge_request_merge_checks_status_checks', form: form, project: @project + = form.gitlab_ui_checkbox_component :only_allow_merge_if_all_discussions_are_resolved, + s_('ProjectSettings|All threads must be resolved'), + checkbox_options: { data: { qa_selector: 'allow_merge_if_all_discussions_are_resolved_checkbox' } } = render_if_exists 'projects/merge_request_merge_checks_jira_enforcement', form: form, project: @project diff --git a/app/views/projects/_merge_request_pipelines_and_threads_options.html.haml b/app/views/projects/_merge_request_pipelines_and_threads_options.html.haml deleted file mode 100644 index 7f4ed3e346ca36..00000000000000 --- a/app/views/projects/_merge_request_pipelines_and_threads_options.html.haml +++ /dev/null @@ -1,14 +0,0 @@ -- form = local_assigns.fetch(:form) - -.builds-feature - = form.gitlab_ui_checkbox_component :only_allow_merge_if_pipeline_succeeds, - s_('ProjectSettings|Pipelines must succeed'), - help_text: s_("ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running.") - .gl-pl-6 - = form.gitlab_ui_checkbox_component :allow_merge_on_skipped_pipeline, - s_('ProjectSettings|Skipped pipelines are considered successful'), - help_text: s_('ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline.'), - checkbox_options: { class: 'gl-pl-6' } - = form.gitlab_ui_checkbox_component :only_allow_merge_if_all_discussions_are_resolved, - s_('ProjectSettings|All threads must be resolved'), - checkbox_options: { data: { qa_selector: 'allow_merge_if_all_discussions_are_resolved_checkbox' } } diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml index 90faaa1b701de1..41c2187f0b1b32 100644 --- a/app/views/projects/merge_requests/show.html.haml +++ b/app/views/projects/merge_requests/show.html.haml @@ -47,10 +47,7 @@ = _("Changes") = gl_badge_tag @diffs_count, { size: :sm } .d-flex.flex-wrap.align-items-center.justify-content-lg-end - - if Feature.enabled?(:support_group_level_merge_checks_setting, @project) - #js-vue-discussion-counter{ data: { blocks_merge: @project.actual_only_allow_merge_if_all_discussions_are_resolved?.to_s } } - - else - #js-vue-discussion-counter{ data: { blocks_merge: @project.only_allow_merge_if_all_discussions_are_resolved?.to_s } } + #js-vue-discussion-counter{ data: { blocks_merge: @project.only_allow_merge_if_all_discussions_are_resolved?.to_s } } - if moved_mr_sidebar_enabled? - if !!@issuable_sidebar.dig(:current_user, :id) .js-sidebar-todo-widget-root{ data: { project_path: @issuable_sidebar[:project_full_path], iid: @issuable_sidebar[:iid], id: @issuable_sidebar[:id] } } diff --git a/qa/qa/page/project/settings/merge_request.rb b/qa/qa/page/project/settings/merge_request.rb index ae6a04028c9d1a..d862979aeecbe2 100644 --- a/qa/qa/page/project/settings/merge_request.rb +++ b/qa/qa/page/project/settings/merge_request.rb @@ -15,7 +15,7 @@ class MergeRequest < QA::Page::Base element :merge_ff_radio end - view 'app/views/projects/_merge_request_pipelines_and_threads_options.html.haml' do + view 'app/views/projects/_merge_request_merge_checks_settings.html.haml' do element :allow_merge_if_all_discussions_are_resolved_checkbox end -- GitLab From aad6984b49552bb507b4ca6bb2ccaee7995b244d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B7=AF=E5=B0=8F=E9=B9=BF?= <1551755561@qq.com> Date: Tue, 22 Nov 2022 11:29:51 +0800 Subject: [PATCH 6/9] Update spec: use public_send instead of send --- spec/models/merge_request_spec.rb | 18 ++++----- spec/models/project_spec.rb | 40 +++++++++---------- .../merge_request_poll_widget_entity_spec.rb | 8 ++-- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 28b1c7407d7375..43bd9b1e46adfb 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -3491,7 +3491,7 @@ def set_compare(merge_request) end end - describe 'test feature flag' do + describe 'test feature flag support_group_level_merge_checks_setting' do let_it_be(:project) { create(:project, :repository) } before do @@ -3505,30 +3505,30 @@ def set_compare(merge_request) subject { build(:merge_request, source_project: project) } - context 'when feature flag "support_group_level_merge_checks_setting" enabled' do - it { + context 'when feature flag support_group_level_merge_checks_setting enabled' do + it do result = subject.mergeable_ci_state? expect(result).to be_truthy expect(project).to have_received(:actual_only_allow_merge_if_pipeline_succeeds?).once expect(project).to have_received(:actual_allow_merge_on_skipped_pipeline?).once expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?) expect(project).not_to have_received(:allow_merge_on_skipped_pipeline?) - } + end end - context 'when feature flag "support_group_level_merge_checks_setting" disabled' do + context 'when feature flag support_group_level_merge_checks_setting disabled' do before do stub_feature_flags(support_group_level_merge_checks_setting: false) end - it { + it do result = subject.mergeable_ci_state? expect(result).to be_truthy expect(project).not_to have_received(:actual_only_allow_merge_if_pipeline_succeeds?) expect(project).not_to have_received(:actual_allow_merge_on_skipped_pipeline?) expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).once expect(project).to have_received(:allow_merge_on_skipped_pipeline?).once - } + end end end end @@ -3580,7 +3580,7 @@ def set_compare(merge_request) allow(project).to receive(:only_allow_merge_if_all_discussions_are_resolved?) end - context 'when feature flag "support_group_level_merge_checks_setting" enabled' do + context 'when feature flag support_group_level_merge_checks_setting enabled' do let(:group) { create(:group, :public) } it 'returns true' do @@ -3591,7 +3591,7 @@ def set_compare(merge_request) end end - context 'when feature flag "support_group_level_merge_checks_setting" disabled' do + context 'when feature flag support_group_level_merge_checks_setting disabled' do before do stub_feature_flags(support_group_level_merge_checks_setting: false) end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index d54e74e4eed3a1..120c0686961edc 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -8386,17 +8386,17 @@ def has_external_wiki let_it_be_with_reload(:project) { create(:project, group: subgroup) } let_it_be_with_reload(:project_without_group) { create(:project) } - shared_examples 'actual_xxx? and xxx_locked?' do |attribute| + shared_examples 'cascading settings' do |attribute| it 'return self value when no parent' do expect(project_without_group.group).to be_nil project_without_group.update!(attribute => true) - expect(project_without_group.send("actual_#{attribute}?")).to be_truthy - expect(project_without_group.send("#{attribute}_locked?")).to be_falsey + expect(project_without_group.public_send("actual_#{attribute}?")).to be_truthy + expect(project_without_group.public_send("#{attribute}_locked?")).to be_falsey project_without_group.update!(attribute => false) - expect(project_without_group.send("actual_#{attribute}?")).to be_falsey - expect(project_without_group.send("#{attribute}_locked?")).to be_falsey + expect(project_without_group.public_send("actual_#{attribute}?")).to be_falsey + expect(project_without_group.public_send("#{attribute}_locked?")).to be_falsey end it 'return self value when unlocked' do @@ -8404,12 +8404,12 @@ def has_external_wiki group.namespace_settings.update!(attribute => false) project.update!(attribute => true) - expect(project.send("actual_#{attribute}?")).to be_truthy - expect(project.send("#{attribute}_locked?")).to be_falsey + expect(project.public_send("actual_#{attribute}?")).to be_truthy + expect(project.public_send("#{attribute}_locked?")).to be_falsey project.update!(attribute => false) - expect(project.send("actual_#{attribute}?")).to be_falsey - expect(project.send("#{attribute}_locked?")).to be_falsey + expect(project.public_send("actual_#{attribute}?")).to be_falsey + expect(project.public_send("#{attribute}_locked?")).to be_falsey end it 'still return self value when locked subgroup' do @@ -8417,12 +8417,12 @@ def has_external_wiki group.namespace_settings.update!(attribute => false) project.update!(attribute => true) - expect(project.send("actual_#{attribute}?")).to be_truthy - expect(project.send("#{attribute}_locked?")).to be_falsey + expect(project.public_send("actual_#{attribute}?")).to be_truthy + expect(project.public_send("#{attribute}_locked?")).to be_falsey project.update!(attribute => false) - expect(project.send("actual_#{attribute}?")).to be_falsey - expect(project.send("#{attribute}_locked?")).to be_falsey + expect(project.public_send("actual_#{attribute}?")).to be_falsey + expect(project.public_send("#{attribute}_locked?")).to be_falsey end it 'still return unlocked value when locked group' do @@ -8430,18 +8430,18 @@ def has_external_wiki group.namespace_settings.update!(attribute => true) project.update!(attribute => true) - expect(project.send("actual_#{attribute}?")).to be_truthy - expect(project.send("#{attribute}_locked?")).to be_falsey + expect(project.public_send("actual_#{attribute}?")).to be_truthy + expect(project.public_send("#{attribute}_locked?")).to be_falsey project.update!(attribute => false) - expect(project.send("actual_#{attribute}?")).to be_falsey - expect(project.send("#{attribute}_locked?")).to be_falsey + expect(project.public_send("actual_#{attribute}?")).to be_falsey + expect(project.public_send("#{attribute}_locked?")).to be_falsey end end - it_behaves_like 'actual_xxx? and xxx_locked?', :only_allow_merge_if_pipeline_succeeds - it_behaves_like 'actual_xxx? and xxx_locked?', :allow_merge_on_skipped_pipeline - it_behaves_like 'actual_xxx? and xxx_locked?', :only_allow_merge_if_all_discussions_are_resolved + it_behaves_like 'cascading settings', :only_allow_merge_if_pipeline_succeeds + it_behaves_like 'cascading settings', :allow_merge_on_skipped_pipeline + it_behaves_like 'cascading settings', :only_allow_merge_if_all_discussions_are_resolved end private diff --git a/spec/serializers/merge_request_poll_widget_entity_spec.rb b/spec/serializers/merge_request_poll_widget_entity_spec.rb index 6bda19b5a03a69..8bb3e8555b8e4b 100644 --- a/spec/serializers/merge_request_poll_widget_entity_spec.rb +++ b/spec/serializers/merge_request_poll_widget_entity_spec.rb @@ -185,7 +185,7 @@ end end - describe 'test feature flag' do + describe 'test feature flag support_group_level_merge_checks_setting' do let_it_be(:project) { create :project, :repository } let_it_be(:resource) { create(:merge_request, source_project: project, target_project: project) } let_it_be(:user) { create(:user) } @@ -195,7 +195,7 @@ allow(project).to receive(:only_allow_merge_if_pipeline_succeeds?) end - context 'when feature flag "support_group_level_merge_checks_setting" enabled' do + context 'when feature flag support_group_level_merge_checks_setting enabled' do it do subject expect(project).to have_received(:actual_only_allow_merge_if_pipeline_succeeds?).at_least(:once) @@ -203,12 +203,12 @@ end end - context 'when feature flag "support_group_level_merge_checks_setting" disabled' do + context 'when feature flag support_group_level_merge_checks_setting disabled' do before do stub_feature_flags(support_group_level_merge_checks_setting: false) end - context 'when feature flag "support_group_level_merge_checks_setting" enabled' do + context 'when feature flag support_group_level_merge_checks_setting enabled' do it do subject expect(project).not_to have_received(:actual_only_allow_merge_if_pipeline_succeeds?) -- GitLab From 35df53b30718c0ffec61fde7576579cc811439d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B7=AF=E5=B0=8F=E9=B9=BF?= <1551755561@qq.com> Date: Fri, 2 Dec 2022 23:27:11 +0800 Subject: [PATCH 7/9] Add descriptions to unit tests --- spec/models/merge_request_spec.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 43bd9b1e46adfb..4a90c135a8b628 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -3506,7 +3506,7 @@ def set_compare(merge_request) subject { build(:merge_request, source_project: project) } context 'when feature flag support_group_level_merge_checks_setting enabled' do - it do + it 'call actual_[configuration] instead of [configuration]' do result = subject.mergeable_ci_state? expect(result).to be_truthy expect(project).to have_received(:actual_only_allow_merge_if_pipeline_succeeds?).once @@ -3521,7 +3521,7 @@ def set_compare(merge_request) stub_feature_flags(support_group_level_merge_checks_setting: false) end - it do + it 'call [configuration] instead of actual_[configuration]' do result = subject.mergeable_ci_state? expect(result).to be_truthy expect(project).not_to have_received(:actual_only_allow_merge_if_pipeline_succeeds?) @@ -3583,9 +3583,8 @@ def set_compare(merge_request) context 'when feature flag support_group_level_merge_checks_setting enabled' do let(:group) { create(:group, :public) } - it 'returns true' do - result = merge_request.mergeable_discussions_state? - expect(result).to be_truthy + it 'returns true and call actual_[configuration] instead of [configuration]' do + expect(merge_request.mergeable_discussions_state?).to be_truthy expect(project).to have_received(:actual_only_allow_merge_if_all_discussions_are_resolved?).at_least(:once) expect(project).not_to have_received(:only_allow_merge_if_all_discussions_are_resolved?) end @@ -3596,7 +3595,7 @@ def set_compare(merge_request) stub_feature_flags(support_group_level_merge_checks_setting: false) end - it 'returns true' do + it 'returns true and call [configuration] instead of actual_[configuration]' do expect(merge_request.mergeable_discussions_state?).to be_truthy expect(project).not_to have_received(:actual_only_allow_merge_if_all_discussions_are_resolved?) expect(project).to have_received(:only_allow_merge_if_all_discussions_are_resolved?).at_least(:once) -- GitLab From f722896e019cdc6e686eb1efab752e56c8511c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B7=AF=E5=B0=8F=E9=B9=BF?= <1551755561@qq.com> Date: Mon, 5 Dec 2022 19:51:52 +0800 Subject: [PATCH 8/9] Rename function "actual_[configuration]?" Rename from "actual_[configuration]?" to "[configuration](inherit_group_setting: false)" Changelog: changed --- app/models/merge_request.rb | 6 ++-- app/models/project.rb | 8 ++--- .../merge_request_poll_widget_entity.rb | 2 +- spec/models/merge_request_spec.rb | 35 +++++++++---------- spec/models/project_spec.rb | 16 ++++----- .../merge_request_poll_widget_entity_spec.rb | 14 ++++---- 6 files changed, 39 insertions(+), 42 deletions(-) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 87c70dc9c9cdee..e8490c4a8c9379 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -1272,7 +1272,7 @@ def commit_notes def mergeable_discussions_state? if Feature.enabled?(:support_group_level_merge_checks_setting, project) - return true unless project.actual_only_allow_merge_if_all_discussions_are_resolved? + return true unless project.only_allow_merge_if_all_discussions_are_resolved?(inherit_group_setting: true) else return true unless project.only_allow_merge_if_all_discussions_are_resolved? end @@ -1457,9 +1457,9 @@ def can_be_merged_via_command_line_by?(user) def mergeable_ci_state? if Feature.enabled?(:support_group_level_merge_checks_setting, project) - return true unless project.actual_only_allow_merge_if_pipeline_succeeds? + return true unless project.only_allow_merge_if_pipeline_succeeds?(inherit_group_setting: true) return false unless actual_head_pipeline - return true if project.actual_allow_merge_on_skipped_pipeline? && actual_head_pipeline.skipped? + return true if project.allow_merge_on_skipped_pipeline?(inherit_group_setting: true) && actual_head_pipeline.skipped? else return true unless project.only_allow_merge_if_pipeline_succeeds? return false unless actual_head_pipeline diff --git a/app/models/project.rb b/app/models/project.rb index 358660c48b7753..d8c24fc3e6b524 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -744,14 +744,14 @@ def self.public_or_visible_to_user(user = nil, min_access_level = nil) # Defines instance methods: # - # - actual_only_allow_merge_if_pipeline_succeeds? - # - actual_allow_merge_on_skipped_pipeline? - # - actual_only_allow_merge_if_all_discussions_are_resolved? + # - only_allow_merge_if_pipeline_succeeds?(inherit_group_setting: false) + # - allow_merge_on_skipped_pipeline?(inherit_group_setting: false) + # - only_allow_merge_if_all_discussions_are_resolved?(inherit_group_setting: false) # - only_allow_merge_if_pipeline_succeeds_locked? # - allow_merge_on_skipped_pipeline_locked? # - only_allow_merge_if_all_discussions_are_resolved_locked? def self.cascading_with_parent_namespace(attribute) - define_method("actual_#{attribute}?") do + define_method("#{attribute}?") do |inherit_group_setting: false| self.public_send(attribute) # rubocop:disable GitlabSecurity/PublicSend end diff --git a/app/serializers/merge_request_poll_widget_entity.rb b/app/serializers/merge_request_poll_widget_entity.rb index 1bd9bc3c15d883..8e2ac865ed2c9a 100644 --- a/app/serializers/merge_request_poll_widget_entity.rb +++ b/app/serializers/merge_request_poll_widget_entity.rb @@ -32,7 +32,7 @@ class MergeRequestPollWidgetEntity < Grape::Entity expose :only_allow_merge_if_pipeline_succeeds do |merge_request| if Feature.enabled?(:support_group_level_merge_checks_setting, merge_request.project) - merge_request.project.actual_only_allow_merge_if_pipeline_succeeds? + merge_request.project.only_allow_merge_if_pipeline_succeeds?(inherit_group_setting: true) else merge_request.project.only_allow_merge_if_pipeline_succeeds? end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 4a90c135a8b628..af3d60d4fcc288 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -3497,8 +3497,6 @@ def set_compare(merge_request) before do pipeline.update!(status: 'skipped', sha: subject.diff_head_sha) allow(subject).to receive(:head_pipeline).and_return(pipeline) - allow(project).to receive(:actual_only_allow_merge_if_pipeline_succeeds?).and_return(true) - allow(project).to receive(:actual_allow_merge_on_skipped_pipeline?).and_return(true) allow(project).to receive(:only_allow_merge_if_pipeline_succeeds?).and_return(true) allow(project).to receive(:allow_merge_on_skipped_pipeline?).and_return(true) end @@ -3506,13 +3504,13 @@ def set_compare(merge_request) subject { build(:merge_request, source_project: project) } context 'when feature flag support_group_level_merge_checks_setting enabled' do - it 'call actual_[configuration] instead of [configuration]' do + it 'call "[configuration]?(inherit_group_setting: true)" instead of "[configuration]?"' do result = subject.mergeable_ci_state? expect(result).to be_truthy - expect(project).to have_received(:actual_only_allow_merge_if_pipeline_succeeds?).once - expect(project).to have_received(:actual_allow_merge_on_skipped_pipeline?).once - expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?) - expect(project).not_to have_received(:allow_merge_on_skipped_pipeline?) + expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).with({ inherit_group_setting: true }) + expect(project).to have_received(:allow_merge_on_skipped_pipeline?).with({ inherit_group_setting: true }) + expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?).with(no_args) + expect(project).not_to have_received(:allow_merge_on_skipped_pipeline?).with(no_args) end end @@ -3521,13 +3519,13 @@ def set_compare(merge_request) stub_feature_flags(support_group_level_merge_checks_setting: false) end - it 'call [configuration] instead of actual_[configuration]' do + it 'call "[configuration]?" instead of "[configuration]?(inherit_group_setting: true)"' do result = subject.mergeable_ci_state? expect(result).to be_truthy - expect(project).not_to have_received(:actual_only_allow_merge_if_pipeline_succeeds?) - expect(project).not_to have_received(:actual_allow_merge_on_skipped_pipeline?) - expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).once - expect(project).to have_received(:allow_merge_on_skipped_pipeline?).once + expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?).with({ inherit_group_setting: true }) + expect(project).not_to have_received(:allow_merge_on_skipped_pipeline?).with({ inherit_group_setting: true }) + expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).with(no_args) + expect(project).to have_received(:allow_merge_on_skipped_pipeline?).with(no_args) end end end @@ -3576,17 +3574,16 @@ def set_compare(merge_request) context 'with unresolved discussions' do before do merge_request.discussions.each(&:unresolve!) - allow(project).to receive(:actual_only_allow_merge_if_all_discussions_are_resolved?) allow(project).to receive(:only_allow_merge_if_all_discussions_are_resolved?) end context 'when feature flag support_group_level_merge_checks_setting enabled' do let(:group) { create(:group, :public) } - it 'returns true and call actual_[configuration] instead of [configuration]' do + it 'returns true and call "[configuration]?(inherit_group_setting: true)" instead of "[configuration]?"' do expect(merge_request.mergeable_discussions_state?).to be_truthy - expect(project).to have_received(:actual_only_allow_merge_if_all_discussions_are_resolved?).at_least(:once) - expect(project).not_to have_received(:only_allow_merge_if_all_discussions_are_resolved?) + expect(project).to have_received(:only_allow_merge_if_all_discussions_are_resolved?).with({ inherit_group_setting: true }).at_least(:once) + expect(project).not_to have_received(:only_allow_merge_if_all_discussions_are_resolved?).with(no_args) end end @@ -3595,10 +3592,10 @@ def set_compare(merge_request) stub_feature_flags(support_group_level_merge_checks_setting: false) end - it 'returns true and call [configuration] instead of actual_[configuration]' do + it 'returns true and call "[configuration]?" instead of "[configuration]?(inherit_group_setting: true)"' do expect(merge_request.mergeable_discussions_state?).to be_truthy - expect(project).not_to have_received(:actual_only_allow_merge_if_all_discussions_are_resolved?) - expect(project).to have_received(:only_allow_merge_if_all_discussions_are_resolved?).at_least(:once) + expect(project).not_to have_received(:only_allow_merge_if_all_discussions_are_resolved?).with({ inherit_group_setting: true }) + expect(project).to have_received(:only_allow_merge_if_all_discussions_are_resolved?).with(no_args).at_least(:once) end end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 120c0686961edc..5020b58c169dcc 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -8391,11 +8391,11 @@ def has_external_wiki expect(project_without_group.group).to be_nil project_without_group.update!(attribute => true) - expect(project_without_group.public_send("actual_#{attribute}?")).to be_truthy + expect(project_without_group.public_send("#{attribute}?", inherit_group_setting: true)).to be_truthy expect(project_without_group.public_send("#{attribute}_locked?")).to be_falsey project_without_group.update!(attribute => false) - expect(project_without_group.public_send("actual_#{attribute}?")).to be_falsey + expect(project_without_group.public_send("#{attribute}?", inherit_group_setting: true)).to be_falsey expect(project_without_group.public_send("#{attribute}_locked?")).to be_falsey end @@ -8404,11 +8404,11 @@ def has_external_wiki group.namespace_settings.update!(attribute => false) project.update!(attribute => true) - expect(project.public_send("actual_#{attribute}?")).to be_truthy + expect(project.public_send("#{attribute}?", inherit_group_setting: true)).to be_truthy expect(project.public_send("#{attribute}_locked?")).to be_falsey project.update!(attribute => false) - expect(project.public_send("actual_#{attribute}?")).to be_falsey + expect(project.public_send("#{attribute}?", inherit_group_setting: true)).to be_falsey expect(project.public_send("#{attribute}_locked?")).to be_falsey end @@ -8417,11 +8417,11 @@ def has_external_wiki group.namespace_settings.update!(attribute => false) project.update!(attribute => true) - expect(project.public_send("actual_#{attribute}?")).to be_truthy + expect(project.public_send("#{attribute}?", inherit_group_setting: true)).to be_truthy expect(project.public_send("#{attribute}_locked?")).to be_falsey project.update!(attribute => false) - expect(project.public_send("actual_#{attribute}?")).to be_falsey + expect(project.public_send("#{attribute}?", inherit_group_setting: true)).to be_falsey expect(project.public_send("#{attribute}_locked?")).to be_falsey end @@ -8430,11 +8430,11 @@ def has_external_wiki group.namespace_settings.update!(attribute => true) project.update!(attribute => true) - expect(project.public_send("actual_#{attribute}?")).to be_truthy + expect(project.public_send("#{attribute}?", inherit_group_setting: true)).to be_truthy expect(project.public_send("#{attribute}_locked?")).to be_falsey project.update!(attribute => false) - expect(project.public_send("actual_#{attribute}?")).to be_falsey + expect(project.public_send("#{attribute}?", inherit_group_setting: true)).to be_falsey expect(project.public_send("#{attribute}_locked?")).to be_falsey end end diff --git a/spec/serializers/merge_request_poll_widget_entity_spec.rb b/spec/serializers/merge_request_poll_widget_entity_spec.rb index 8bb3e8555b8e4b..0ca1f88e95292d 100644 --- a/spec/serializers/merge_request_poll_widget_entity_spec.rb +++ b/spec/serializers/merge_request_poll_widget_entity_spec.rb @@ -191,15 +191,14 @@ let_it_be(:user) { create(:user) } before do - allow(project).to receive(:actual_only_allow_merge_if_pipeline_succeeds?) allow(project).to receive(:only_allow_merge_if_pipeline_succeeds?) end context 'when feature flag support_group_level_merge_checks_setting enabled' do - it do + it 'call "[configuration]?(inherit_group_setting: true)" instead of "[configuration]?"' do subject - expect(project).to have_received(:actual_only_allow_merge_if_pipeline_succeeds?).at_least(:once) - expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?) + expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).with({ inherit_group_setting: true }).at_least(:once) + expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?).with(no_args) end end @@ -209,10 +208,11 @@ end context 'when feature flag support_group_level_merge_checks_setting enabled' do - it do + it 'call "[configuration]?" instead of "[configuration]?(inherit_group_setting: true)"' do subject - expect(project).not_to have_received(:actual_only_allow_merge_if_pipeline_succeeds?) - expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).at_least(:once) + + expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?).with({ inherit_group_setting: true }) + expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).with(no_args).at_least(:once) end end end -- GitLab From 94dbb52c770d04d6be8a57ce17f9710fcafbc08c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B7=AF=E5=B0=8F=E9=B9=BF?= <1551755561@qq.com> Date: Mon, 5 Dec 2022 23:22:08 +0800 Subject: [PATCH 9/9] Remove feature flag about 'MR checks' Feature flag: support_group_level_merge_checks_setting The reason for removal is that there is no need to use the feature flag. Changelog: changed --- app/models/merge_request.rb | 18 ++---- app/models/project.rb | 1 + .../merge_request_poll_widget_entity.rb | 6 +- ...pport_group_level_merge_checks_setting.yml | 8 --- spec/models/merge_request_spec.rb | 62 +------------------ .../merge_request_poll_widget_entity_spec.rb | 33 ---------- 6 files changed, 8 insertions(+), 120 deletions(-) delete mode 100644 config/feature_flags/development/support_group_level_merge_checks_setting.yml diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index e8490c4a8c9379..e17956256fc8ea 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -1271,11 +1271,7 @@ def commit_notes end def mergeable_discussions_state? - if Feature.enabled?(:support_group_level_merge_checks_setting, project) - return true unless project.only_allow_merge_if_all_discussions_are_resolved?(inherit_group_setting: true) - else - return true unless project.only_allow_merge_if_all_discussions_are_resolved? - end + return true unless project.only_allow_merge_if_all_discussions_are_resolved?(inherit_group_setting: true) unresolved_notes.none?(&:to_be_resolved?) end @@ -1456,15 +1452,9 @@ def can_be_merged_via_command_line_by?(user) end def mergeable_ci_state? - if Feature.enabled?(:support_group_level_merge_checks_setting, project) - return true unless project.only_allow_merge_if_pipeline_succeeds?(inherit_group_setting: true) - return false unless actual_head_pipeline - return true if project.allow_merge_on_skipped_pipeline?(inherit_group_setting: true) && actual_head_pipeline.skipped? - else - return true unless project.only_allow_merge_if_pipeline_succeeds? - return false unless actual_head_pipeline - return true if project.allow_merge_on_skipped_pipeline? && actual_head_pipeline.skipped? - end + return true unless project.only_allow_merge_if_pipeline_succeeds?(inherit_group_setting: true) + return false unless actual_head_pipeline + return true if project.allow_merge_on_skipped_pipeline?(inherit_group_setting: true) && actual_head_pipeline.skipped? actual_head_pipeline.success? end diff --git a/app/models/project.rb b/app/models/project.rb index d8c24fc3e6b524..521c5da40e7a5c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -751,6 +751,7 @@ def self.public_or_visible_to_user(user = nil, min_access_level = nil) # - allow_merge_on_skipped_pipeline_locked? # - only_allow_merge_if_all_discussions_are_resolved_locked? def self.cascading_with_parent_namespace(attribute) + # method overriden in EE define_method("#{attribute}?") do |inherit_group_setting: false| self.public_send(attribute) # rubocop:disable GitlabSecurity/PublicSend end diff --git a/app/serializers/merge_request_poll_widget_entity.rb b/app/serializers/merge_request_poll_widget_entity.rb index 8e2ac865ed2c9a..cef3f4555df72d 100644 --- a/app/serializers/merge_request_poll_widget_entity.rb +++ b/app/serializers/merge_request_poll_widget_entity.rb @@ -31,11 +31,7 @@ class MergeRequestPollWidgetEntity < Grape::Entity end expose :only_allow_merge_if_pipeline_succeeds do |merge_request| - if Feature.enabled?(:support_group_level_merge_checks_setting, merge_request.project) - merge_request.project.only_allow_merge_if_pipeline_succeeds?(inherit_group_setting: true) - else - merge_request.project.only_allow_merge_if_pipeline_succeeds? - end + merge_request.project.only_allow_merge_if_pipeline_succeeds?(inherit_group_setting: true) end # CI related diff --git a/config/feature_flags/development/support_group_level_merge_checks_setting.yml b/config/feature_flags/development/support_group_level_merge_checks_setting.yml deleted file mode 100644 index 794250ed364963..00000000000000 --- a/config/feature_flags/development/support_group_level_merge_checks_setting.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: support_group_level_merge_checks_setting -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/102594 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/377723 -milestone: '15.6' -type: development -group: group::code review -default_enabled: false diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index af3d60d4fcc288..ccc77c7259f24d 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -3490,45 +3490,6 @@ def set_compare(merge_request) it { expect(subject.mergeable_ci_state?).to be_truthy } end end - - describe 'test feature flag support_group_level_merge_checks_setting' do - let_it_be(:project) { create(:project, :repository) } - - before do - pipeline.update!(status: 'skipped', sha: subject.diff_head_sha) - allow(subject).to receive(:head_pipeline).and_return(pipeline) - allow(project).to receive(:only_allow_merge_if_pipeline_succeeds?).and_return(true) - allow(project).to receive(:allow_merge_on_skipped_pipeline?).and_return(true) - end - - subject { build(:merge_request, source_project: project) } - - context 'when feature flag support_group_level_merge_checks_setting enabled' do - it 'call "[configuration]?(inherit_group_setting: true)" instead of "[configuration]?"' do - result = subject.mergeable_ci_state? - expect(result).to be_truthy - expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).with({ inherit_group_setting: true }) - expect(project).to have_received(:allow_merge_on_skipped_pipeline?).with({ inherit_group_setting: true }) - expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?).with(no_args) - expect(project).not_to have_received(:allow_merge_on_skipped_pipeline?).with(no_args) - end - end - - context 'when feature flag support_group_level_merge_checks_setting disabled' do - before do - stub_feature_flags(support_group_level_merge_checks_setting: false) - end - - it 'call "[configuration]?" instead of "[configuration]?(inherit_group_setting: true)"' do - result = subject.mergeable_ci_state? - expect(result).to be_truthy - expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?).with({ inherit_group_setting: true }) - expect(project).not_to have_received(:allow_merge_on_skipped_pipeline?).with({ inherit_group_setting: true }) - expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).with(no_args) - expect(project).to have_received(:allow_merge_on_skipped_pipeline?).with(no_args) - end - end - end end describe '#mergeable_discussions_state?' do @@ -3574,29 +3535,10 @@ def set_compare(merge_request) context 'with unresolved discussions' do before do merge_request.discussions.each(&:unresolve!) - allow(project).to receive(:only_allow_merge_if_all_discussions_are_resolved?) - end - - context 'when feature flag support_group_level_merge_checks_setting enabled' do - let(:group) { create(:group, :public) } - - it 'returns true and call "[configuration]?(inherit_group_setting: true)" instead of "[configuration]?"' do - expect(merge_request.mergeable_discussions_state?).to be_truthy - expect(project).to have_received(:only_allow_merge_if_all_discussions_are_resolved?).with({ inherit_group_setting: true }).at_least(:once) - expect(project).not_to have_received(:only_allow_merge_if_all_discussions_are_resolved?).with(no_args) - end end - context 'when feature flag support_group_level_merge_checks_setting disabled' do - before do - stub_feature_flags(support_group_level_merge_checks_setting: false) - end - - it 'returns true and call "[configuration]?" instead of "[configuration]?(inherit_group_setting: true)"' do - expect(merge_request.mergeable_discussions_state?).to be_truthy - expect(project).not_to have_received(:only_allow_merge_if_all_discussions_are_resolved?).with({ inherit_group_setting: true }) - expect(project).to have_received(:only_allow_merge_if_all_discussions_are_resolved?).with(no_args).at_least(:once) - end + it 'returns true' do + expect(merge_request.mergeable_discussions_state?).to be_truthy end end end diff --git a/spec/serializers/merge_request_poll_widget_entity_spec.rb b/spec/serializers/merge_request_poll_widget_entity_spec.rb index 0ca1f88e95292d..418f629a301651 100644 --- a/spec/serializers/merge_request_poll_widget_entity_spec.rb +++ b/spec/serializers/merge_request_poll_widget_entity_spec.rb @@ -184,37 +184,4 @@ end end end - - describe 'test feature flag support_group_level_merge_checks_setting' do - let_it_be(:project) { create :project, :repository } - let_it_be(:resource) { create(:merge_request, source_project: project, target_project: project) } - let_it_be(:user) { create(:user) } - - before do - allow(project).to receive(:only_allow_merge_if_pipeline_succeeds?) - end - - context 'when feature flag support_group_level_merge_checks_setting enabled' do - it 'call "[configuration]?(inherit_group_setting: true)" instead of "[configuration]?"' do - subject - expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).with({ inherit_group_setting: true }).at_least(:once) - expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?).with(no_args) - end - end - - context 'when feature flag support_group_level_merge_checks_setting disabled' do - before do - stub_feature_flags(support_group_level_merge_checks_setting: false) - end - - context 'when feature flag support_group_level_merge_checks_setting enabled' do - it 'call "[configuration]?" instead of "[configuration]?(inherit_group_setting: true)"' do - subject - - expect(project).not_to have_received(:only_allow_merge_if_pipeline_succeeds?).with({ inherit_group_setting: true }) - expect(project).to have_received(:only_allow_merge_if_pipeline_succeeds?).with(no_args).at_least(:once) - end - end - end - end end -- GitLab