summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorKamil Trzciński <ayufan@ayufan.eu>2017-12-06 09:01:31 +0000
committerKamil Trzciński <ayufan@ayufan.eu>2017-12-06 09:01:31 +0000
commit67a94b2ff3b0d714549c7d30b3c6212f3046a3c2 (patch)
tree9d99b4db7f5cbfbcb8e6143ac79d18403437ab45 /app
parentf92292815868a67db53059cbe8e7607cc4891f47 (diff)
parentb328cff308431fd28a779f9356c9a43351de2754 (diff)
downloadgitlab-ce-67a94b2ff3b0d714549c7d30b3c6212f3046a3c2.tar.gz
Merge branch '37354-pipelines-update' into 'master'
Make sure head pippeline always corresponds with an MR Closes #37354 See merge request gitlab-org/gitlab-ce!14358
Diffstat (limited to 'app')
-rw-r--r--app/controllers/projects/merge_requests_controller.rb6
-rw-r--r--app/models/merge_request.rb12
-rw-r--r--app/presenters/merge_request_presenter.rb2
-rw-r--r--app/serializers/merge_request_entity.rb2
-rw-r--r--app/services/ci/create_pipeline_service.rb23
-rw-r--r--app/services/merge_requests/refresh_service.rb1
-rw-r--r--app/workers/update_head_pipeline_for_merge_request_worker.rb15
7 files changed, 49 insertions, 12 deletions
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index abe4e5245b1..37acd1c9787 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -283,15 +283,15 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
@merge_request.update(merge_error: nil)
if params[:merge_when_pipeline_succeeds].present?
- return :failed unless @merge_request.head_pipeline
+ return :failed unless @merge_request.actual_head_pipeline
- if @merge_request.head_pipeline.active?
+ if @merge_request.actual_head_pipeline.active?
::MergeRequests::MergeWhenPipelineSucceedsService
.new(@project, current_user, merge_params)
.execute(@merge_request)
:merge_when_pipeline_succeeds
- elsif @merge_request.head_pipeline.success?
+ elsif @merge_request.actual_head_pipeline.success?
# This can be triggered when a user clicks the auto merge button while
# the tests finish at about the same time
@merge_request.merge_async(current_user.id, params)
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index bbc01e9677c..f2d639a3382 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -145,6 +145,13 @@ class MergeRequest < ActiveRecord::Base
'!'
end
+ # Use this method whenever you need to make sure the head_pipeline is synced with the
+ # branch head commit, for example checking if a merge request can be merged.
+ # For more information check: https://gitlab.com/gitlab-org/gitlab-ce/issues/40004
+ def actual_head_pipeline
+ head_pipeline&.sha == diff_head_sha ? head_pipeline : nil
+ end
+
# Pattern used to extract `!123` merge request references from text
#
# This pattern supports cross-project references.
@@ -822,8 +829,9 @@ class MergeRequest < ActiveRecord::Base
def mergeable_ci_state?
return true unless project.only_allow_merge_if_pipeline_succeeds?
+ return true unless head_pipeline
- !head_pipeline || head_pipeline.success? || head_pipeline.skipped?
+ actual_head_pipeline&.success? || actual_head_pipeline&.skipped?
end
def environments_for(current_user)
@@ -997,7 +1005,7 @@ class MergeRequest < ActiveRecord::Base
return true if autocomplete_precheck
return false unless mergeable?(skip_ci_check: true)
- return false if head_pipeline && !(head_pipeline.success? || head_pipeline.active?)
+ return false if actual_head_pipeline && !(actual_head_pipeline.success? || actual_head_pipeline.active?)
return false if last_diff_sha != diff_head_sha
true
diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb
index a25882cbb62..ab4c87c0169 100644
--- a/app/presenters/merge_request_presenter.rb
+++ b/app/presenters/merge_request_presenter.rb
@@ -163,7 +163,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
end
def pipeline
- @pipeline ||= head_pipeline
+ @pipeline ||= actual_head_pipeline
end
def issues_sentence(project, issues)
diff --git a/app/serializers/merge_request_entity.rb b/app/serializers/merge_request_entity.rb
index b53a49fe59e..eece9445dca 100644
--- a/app/serializers/merge_request_entity.rb
+++ b/app/serializers/merge_request_entity.rb
@@ -33,7 +33,7 @@ class MergeRequestEntity < IssuableEntity
end
expose :merge_commit_message
- expose :head_pipeline, with: PipelineDetailsEntity, as: :pipeline
+ expose :actual_head_pipeline, with: PipelineDetailsEntity, as: :pipeline
# Booleans
expose :merge_ongoing?, as: :merge_ongoing
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index 7b9ea223d26..1e5f2ed4dd2 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -29,7 +29,7 @@ module Ci
.new(pipeline, command, SEQUENCE)
sequence.build! do |pipeline, sequence|
- update_merge_requests_head_pipeline if pipeline.persisted?
+ schedule_head_pipeline_update
if sequence.complete?
cancel_pending_pipelines if project.auto_cancel_pending_pipelines?
@@ -38,15 +38,18 @@ module Ci
pipeline.process!
end
end
+
+ pipeline
end
private
- def update_merge_requests_head_pipeline
- return unless pipeline.latest?
+ def commit
+ @commit ||= project.commit(origin_sha || origin_ref)
+ end
- MergeRequest.where(source_project: @pipeline.project, source_branch: @pipeline.ref)
- .update_all(head_pipeline_id: @pipeline.id)
+ def sha
+ commit.try(:id)
end
def cancel_pending_pipelines
@@ -69,5 +72,15 @@ module Ci
@pipeline_created_counter ||= Gitlab::Metrics
.counter(:pipelines_created_total, "Counter of pipelines created")
end
+
+ def schedule_head_pipeline_update
+ related_merge_requests.each do |merge_request|
+ UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id)
+ end
+ end
+
+ def related_merge_requests
+ MergeRequest.where(source_project: pipeline.project, source_branch: pipeline.ref)
+ end
end
end
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index bf3d4855122..434dda89db0 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -76,6 +76,7 @@ module MergeRequests
end
merge_request.mark_as_unchecked
+ UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id)
end
end
diff --git a/app/workers/update_head_pipeline_for_merge_request_worker.rb b/app/workers/update_head_pipeline_for_merge_request_worker.rb
new file mode 100644
index 00000000000..0a2e9b63578
--- /dev/null
+++ b/app/workers/update_head_pipeline_for_merge_request_worker.rb
@@ -0,0 +1,15 @@
+class UpdateHeadPipelineForMergeRequestWorker
+ include ApplicationWorker
+
+ sidekiq_options queue: 'pipeline_default'
+
+ def perform(merge_request_id)
+ merge_request = MergeRequest.find(merge_request_id)
+ pipeline = Ci::Pipeline.where(project: merge_request.source_project, ref: merge_request.source_branch).last
+
+ return unless pipeline && pipeline.latest?
+ raise ArgumentError, 'merge request sha does not equal pipeline sha' if merge_request.diff_head_sha != pipeline.sha
+
+ merge_request.update_attribute(:head_pipeline_id, pipeline.id)
+ end
+end