diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 3d789035b9a42b03fc493cb4d4fa9c222da411bf..a4d9bed70df6818f4783c05012661c9646560a73 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -2002,6 +2002,10 @@ def target_default_branch? target_branch == project.default_branch end + def merge_blocked_by_other_mrs? + false # Overridden in EE + end + private attr_accessor :skip_fetch_ref diff --git a/app/services/auto_merge/base_service.rb b/app/services/auto_merge/base_service.rb index 9e49bd86ec092bd0104d1c9f91cd004e365f98e6..1660ddb934faa0a9fa26e2e1a53813924fd6f39a 100644 --- a/app/services/auto_merge/base_service.rb +++ b/app/services/auto_merge/base_service.rb @@ -59,6 +59,7 @@ def available_for?(merge_request) !merge_request.broken? && !merge_request.draft? && merge_request.mergeable_discussions_state? && + !merge_request.merge_blocked_by_other_mrs? && yield end end diff --git a/ee/app/models/ee/merge_request.rb b/ee/app/models/ee/merge_request.rb index 35eb48dc3ab4b52f68f7baa5a150f181d8588a32..6b7e5a75e99a87b67d1a85bc2ffd4bdcf8e6b175 100644 --- a/ee/app/models/ee/merge_request.rb +++ b/ee/app/models/ee/merge_request.rb @@ -151,6 +151,7 @@ def mergeability_checks ] + super end + override :merge_blocked_by_other_mrs? def merge_blocked_by_other_mrs? strong_memoize(:merge_blocked_by_other_mrs) do project.feature_available?(:blocking_merge_requests) && diff --git a/ee/spec/services/auto_merge/add_to_merge_train_when_pipeline_succeeds_service_spec.rb b/ee/spec/services/auto_merge/add_to_merge_train_when_pipeline_succeeds_service_spec.rb index 30c36c0109752df6aa8792d9c3a4030d880f169b..704a5d8912f8f1daa273371eeab3bfbd2c1f1a79 100644 --- a/ee/spec/services/auto_merge/add_to_merge_train_when_pipeline_succeeds_service_spec.rb +++ b/ee/spec/services/auto_merge/add_to_merge_train_when_pipeline_succeeds_service_spec.rb @@ -154,6 +154,15 @@ it { is_expected.to eq(false) } end + context 'when there is an open MR dependency' do + before do + stub_licensed_features(blocking_merge_requests: true) + create(:merge_request_block, blocked_merge_request: merge_request) + end + + it { is_expected.to be_falsy } + end + context 'when the user does not have permission to merge' do before do allow(merge_request).to receive(:can_be_merged_by?) { false } diff --git a/ee/spec/services/auto_merge/merge_train_service_spec.rb b/ee/spec/services/auto_merge/merge_train_service_spec.rb index 29d6bf486f7433dd48f2b06fc97f6137f21dc8ce..5fb7e498c878c685c37717b3d24c79d51965b752 100644 --- a/ee/spec/services/auto_merge/merge_train_service_spec.rb +++ b/ee/spec/services/auto_merge/merge_train_service_spec.rb @@ -357,6 +357,15 @@ it { is_expected.to be_falsy } end + context 'when there is an open MR dependency' do + before do + stub_licensed_features(blocking_merge_requests: true) + create(:merge_request_block, blocked_merge_request: merge_request) + end + + it { is_expected.to be_falsy } + end + context 'when merge train ci setting is disabled' do before do stub_feature_flags(disable_merge_trains: true) diff --git a/ee/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb b/ee/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..dc2c6ee5a0797c29331d55f0a622073f8be52940 --- /dev/null +++ b/ee/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe AutoMerge::MergeWhenPipelineSucceedsService do + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :repository) } + + let(:mr_merge_if_green_enabled) do + create(:merge_request, merge_when_pipeline_succeeds: true, merge_user: user, + source_branch: "master", target_branch: 'feature', + source_project: project, target_project: project, state: "opened") + end + + let(:pipeline) do + create(:ci_pipeline, ref: mr_merge_if_green_enabled.source_branch, project: project) + end + + let(:service) do + described_class.new(project, user, commit_message: 'Awesome message') + end + + before_all do + project.add_maintainer(user) + end + + before do + allow(MergeWorker).to receive(:with_status).and_return(MergeWorker) + end + + describe "#available_for?" do + subject { service.available_for?(mr_merge_if_green_enabled) } + + let(:pipeline_status) { :running } + + before do + create(:ci_pipeline, pipeline_status, ref: mr_merge_if_green_enabled.source_branch, + sha: mr_merge_if_green_enabled.diff_head_sha, + project: mr_merge_if_green_enabled.source_project) + mr_merge_if_green_enabled.update_head_pipeline + end + + context 'when there is an open MR dependency' do + before do + stub_licensed_features(blocking_merge_requests: true) + create(:merge_request_block, blocked_merge_request: mr_merge_if_green_enabled) + end + + it { is_expected.to be_falsy } + end + end +end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index bd35b5140965199ce81a4960b66f86894d513d22..d15f0bd4103640c364b067c060535e9634eb4e64 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -5078,6 +5078,12 @@ def create_build(pipeline, coverage, name) end end + describe '#merge_blocked_by_other_mrs?' do + it 'returns false when there is no blocking merge requests' do + expect(subject.merge_blocked_by_other_mrs?).to be_falsy + end + end + describe '#merge_request_reviewers_with' do let_it_be(:reviewer1) { create(:user) } let_it_be(:reviewer2) { create(:user) }