From ecb0cb563e4339b4fc807ced7ce1a6d57d82fc85 Mon Sep 17 00:00:00 2001
From: Gary Holtz <gholtz@gitlab.com>
Date: Wed, 3 Aug 2022 16:22:27 +0000
Subject: [PATCH] This adds a dependency condition to the base auto merge
 service

* This will do a check for any MR dependencies before allowing the
  appropriate auto merge strategy.
* Adds backend specs for the possible scenarios as well

Changelog: fixed
EE: true
---
 app/models/merge_request.rb                   |  4 ++
 app/services/auto_merge/base_service.rb       |  1 +
 ee/app/models/ee/merge_request.rb             |  1 +
 ...ain_when_pipeline_succeeds_service_spec.rb |  9 ++++
 .../auto_merge/merge_train_service_spec.rb    |  9 ++++
 ...rge_when_pipeline_succeeds_service_spec.rb | 52 +++++++++++++++++++
 spec/models/merge_request_spec.rb             |  6 +++
 7 files changed, 82 insertions(+)
 create mode 100644 ee/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb

diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 3d789035b9a42..a4d9bed70df68 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 9e49bd86ec092..1660ddb934faa 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 35eb48dc3ab4b..6b7e5a75e99a8 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 30c36c0109752..704a5d8912f8f 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 29d6bf486f743..5fb7e498c878c 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 0000000000000..dc2c6ee5a0797
--- /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 bd35b51409651..d15f0bd410364 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) }
-- 
GitLab