From e3d464d82a15cb524d066c2ba5d0973efbbfeeef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9my=20Coutable?= <remy@rymai.me>
Date: Fri, 24 Jun 2016 18:13:56 +0200
Subject: [PATCH] Fix a wrong MR status when merge_when_build_succeeds &
 project.only_allow_merge_if_build_succeeds are true
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The issue was that `MergeRequest#mergeable?` returns false when the CI
state is not success and project.only_allow_merge_if_build_succeeds is
true. In this case `Projects::MergeRequestsController#merge` would
return the `:failed` status when enabling `merge_when_build_succeeds`,
thus leading to a weird state and the MR never automatically merged.

The fix is to disable the CI state check in the controller safeguard
that early return the `:failed` status.

Signed-off-by: Rémy Coutable <remy@rymai.me>
---
 CHANGELOG                                            |  1 +
 .../projects/merge_requests_controller.rb            |  9 ++++++++-
 app/models/merge_request.rb                          |  8 ++++----
 .../projects/merge_requests_controller_spec.rb       | 12 ++++++++++++
 4 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 2c139336b15..26042860dbc 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -22,6 +22,7 @@ v 8.9.1
   - Fix mobile Safari bug where horizontal nav arrows would flicker on scroll
   - Fix in auto merge when pipeline is nil
   - Fix GitLab import project deleting imported file straight after being uploaded
+  - Fix a wrong MR status when merge_when_build_succeeds & project.only_allow_merge_if_build_succeeds are true
 
 v 8.9.0
   - Fix builds API response not including commit data
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 79ba032996c..39c8ba40ca2 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -199,7 +199,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
   def merge
     return access_denied! unless @merge_request.can_be_merged_by?(current_user)
 
-    unless @merge_request.mergeable?
+    # Disable the CI check if merge_when_build_succeeds is enabled since we have
+    # to wait until CI completes to know
+    unless @merge_request.mergeable?(skip_ci_check: merge_when_build_succeeds_active?)
       @status = :failed
       return
     end
@@ -395,4 +397,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
   def ensure_ref_fetched
     @merge_request.ensure_ref_fetched
   end
+
+  def merge_when_build_succeeds_active?
+    params[:merge_when_build_succeeds].present? &&
+      @merge_request.pipeline && @merge_request.pipeline.active?
+  end
 end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 36bc98bdb1e..f5c5b7c1306 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -264,19 +264,19 @@ class MergeRequest < ActiveRecord::Base
     self.title.sub(WIP_REGEX, "")
   end
 
-  def mergeable?
-    return false unless mergeable_state?
+  def mergeable?(skip_ci_check: false)
+    return false unless mergeable_state?(skip_ci_check: skip_ci_check)
 
     check_if_can_be_merged
 
     can_be_merged?
   end
 
-  def mergeable_state?
+  def mergeable_state?(skip_ci_check: false)
     return false unless open?
     return false if work_in_progress?
     return false if broken?
-    return false unless mergeable_ci_state?
+    return false unless skip_ci_check || mergeable_ci_state?
 
     true
   end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 4b408c03703..5e66106122c 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -264,6 +264,18 @@ describe Projects::MergeRequestsController do
 
           merge_when_build_succeeds
         end
+
+        context 'when project.only_allow_merge_if_build_succeeds? is true' do
+          before do
+            project.update_column(:only_allow_merge_if_build_succeeds, true)
+          end
+
+          it 'returns :merge_when_build_succeeds' do
+            merge_when_build_succeeds
+
+            expect(assigns(:status)).to eq(:merge_when_build_succeeds)
+          end
+        end
       end
     end
   end
-- 
GitLab