From fe673b492769dc888268a1b2ac25342faa18a817 Mon Sep 17 00:00:00 2001 From: Jarka Kadlecova Date: Thu, 7 Sep 2017 09:58:15 +0200 Subject: Ensure pippeline corresponds with the sha of an MR --- app/models/merge_request.rb | 8 ++++ app/services/ci/create_pipeline_service.rb | 23 +++++++++--- app/services/merge_requests/refresh_service.rb | 1 + ...pdate_head_pipeline_for_merge_request_worker.rb | 15 ++++++++ changelogs/unreleased/37354-pipelines-update.yml | 5 +++ spec/features/merge_requests/pipelines_spec.rb | 15 +++++++- spec/models/merge_request_spec.rb | 28 +++++++++----- spec/services/ci/create_pipeline_service_spec.rb | 43 ++++++++++++++++------ .../merge_requests/refresh_service_spec.rb | 14 +++++++ ..._head_pipeline_for_merge_request_worker_spec.rb | 38 +++++++++++++++++++ 10 files changed, 162 insertions(+), 28 deletions(-) create mode 100644 app/workers/update_head_pipeline_for_merge_request_worker.rb create mode 100644 changelogs/unreleased/37354-pipelines-update.yml create mode 100644 spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index bbc01e9677c..d2ed6f7a8ae 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -145,6 +145,14 @@ class MergeRequest < ActiveRecord::Base '!' end + def head_pipeline + return unless head_pipeline_id + + last_pipeline = Ci::Pipeline.find(head_pipeline_id) + + last_pipeline.sha == diff_head_sha ? last_pipeline : nil + end + # Pattern used to extract `!123` merge request references from text # # This pattern supports cross-project references. 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..ebe2435bbe5 --- /dev/null +++ b/app/workers/update_head_pipeline_for_merge_request_worker.rb @@ -0,0 +1,15 @@ +class UpdateHeadPipelineForMergeRequestWorker + include Sidekiq::Worker + + 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 diff --git a/changelogs/unreleased/37354-pipelines-update.yml b/changelogs/unreleased/37354-pipelines-update.yml new file mode 100644 index 00000000000..2b6ddfe95ed --- /dev/null +++ b/changelogs/unreleased/37354-pipelines-update.yml @@ -0,0 +1,5 @@ +--- +title: Make sure head pippeline always corresponds with the head sha of an MR +merge_request: +author: +type: fixed diff --git a/spec/features/merge_requests/pipelines_spec.rb b/spec/features/merge_requests/pipelines_spec.rb index a3fcc27cab0..307c860eac4 100644 --- a/spec/features/merge_requests/pipelines_spec.rb +++ b/spec/features/merge_requests/pipelines_spec.rb @@ -20,10 +20,14 @@ feature 'Pipelines for Merge Requests', :js do end before do - visit project_merge_request_path(project, merge_request) + merge_request.update_attribute(:head_pipeline_id, pipeline.id) end scenario 'user visits merge request pipelines tab' do + visit project_merge_request_path(project, merge_request) + + expect(page.find('.ci-widget')).to have_content('pending') + page.within('.merge-request-tabs') do click_link('Pipelines') end @@ -31,6 +35,15 @@ feature 'Pipelines for Merge Requests', :js do expect(page).to have_selector('.stage-cell') end + + scenario 'pipeline sha does not equal last commit sha' do + pipeline.update_attribute(:sha, '19e2e9b4ef76b422ce1154af39a91323ccc57434') + visit project_merge_request_path(project, merge_request) + wait_for_requests + + expect(page.find('.ci-widget')).to have_content( + 'Could not connect to the CI server. Please check your settings and try again') + end end context 'without pipelines' do diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 728028746d8..e10f375d42b 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -828,20 +828,28 @@ describe MergeRequest do end describe '#head_pipeline' do - describe 'when the source project exists' do - it 'returns the latest pipeline' do - pipeline = create(:ci_empty_pipeline, project: subject.source_project, ref: 'master', status: 'running', sha: "123abc", head_pipeline_of: subject) + before do + allow(subject).to receive(:diff_head_sha).and_return('lastsha') + end - expect(subject.head_pipeline).to eq(pipeline) - end + it 'returns nil for MR without head_pipeline_id' do + subject.update_attribute(:head_pipeline_id, nil) + + expect(subject.head_pipeline).to be_nil end - describe 'when the source project does not exist' do - it 'returns nil' do - allow(subject).to receive(:source_project).and_return(nil) + it 'returns nil for MR with old pipeline' do + pipeline = create(:ci_empty_pipeline, sha: 'notlatestsha') + subject.update_attribute(:head_pipeline_id, pipeline.id) - expect(subject.head_pipeline).to be_nil - end + expect(subject.head_pipeline).to be_nil + end + + it 'returns the pipeline for MR with recent pipeline' do + pipeline = create(:ci_empty_pipeline, sha: 'lastsha') + subject.update_attribute(:head_pipeline_id, pipeline.id) + + expect(subject.head_pipeline).to eq(pipeline) end end diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb index befd0faf1b6..b0de8d447a2 100644 --- a/spec/services/ci/create_pipeline_service_spec.rb +++ b/spec/services/ci/create_pipeline_service_spec.rb @@ -57,19 +57,39 @@ describe Ci::CreatePipelineService do end context 'when merge requests already exist for this source branch' do - it 'updates head pipeline of each merge request' do - merge_request_1 = create(:merge_request, source_branch: 'master', - target_branch: "branch_1", - source_project: project) + let(:merge_request_1) do + create(:merge_request, source_branch: 'master', target_branch: "branch_1", source_project: project) + end + let(:merge_request_2) do + create(:merge_request, source_branch: 'master', target_branch: "branch_2", source_project: project) + end - merge_request_2 = create(:merge_request, source_branch: 'master', - target_branch: "branch_2", - source_project: project) + context 'when the head pipeline sha equals merge request sha' do + it 'updates head pipeline of each merge request' do + merge_request_1 + merge_request_2 - head_pipeline = execute_service + head_pipeline = execute_service - expect(merge_request_1.reload.head_pipeline).to eq(head_pipeline) - expect(merge_request_2.reload.head_pipeline).to eq(head_pipeline) + expect(merge_request_1.reload.head_pipeline).to eq(head_pipeline) + expect(merge_request_2.reload.head_pipeline).to eq(head_pipeline) + end + end + + context 'when the head pipeline sha does not equal merge request sha' do + it 'raises the ArgumentError error from worker and does not update the head piepeline of MRs' do + merge_request_1 + merge_request_2 + + allow_any_instance_of(Ci::Pipeline).to receive(:latest?).and_return(true) + + expect { execute_service(after: 'ae73cb07c9eeaf35924a10f713b364d32b2dd34f') }.to raise_error(ArgumentError) + + last_pipeline = Ci::Pipeline.last + + expect(merge_request_1.reload.head_pipeline).not_to eq(last_pipeline) + expect(merge_request_2.reload.head_pipeline).not_to eq(last_pipeline) + end end context 'when there is no pipeline for source branch' do @@ -106,8 +126,7 @@ describe Ci::CreatePipelineService do target_branch: "branch_1", source_project: project) - allow_any_instance_of(Ci::Pipeline) - .to receive(:latest?).and_return(false) + allow_any_instance_of(Ci::Pipeline).to receive(:latest?).and_return(false) execute_service diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index a2c05761f6b..61ec4709c59 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -74,6 +74,20 @@ describe MergeRequests::RefreshService do end end + context 'when pipeline exists for the source branch' do + let!(:pipeline) { create(:ci_empty_pipeline, ref: @merge_request.source_branch, project: @project, sha: @commits.first.sha)} + + subject { service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/master') } + + it 'updates the head_pipeline_id for @merge_request' do + expect { subject }.to change { @merge_request.reload.head_pipeline_id }.from(nil).to(pipeline.id) + end + + it 'does not update the head_pipeline_id for @fork_merge_request' do + expect { subject }.not_to change { @fork_merge_request.reload.head_pipeline_id } + end + end + context 'push to origin repo source branch when an MR was reopened' do let(:refresh_service) { service.new(@project, @user) } diff --git a/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb b/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb new file mode 100644 index 00000000000..522e1566271 --- /dev/null +++ b/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe UpdateHeadPipelineForMergeRequestWorker do + describe '#perform' do + let(:user) { create(:user) } + let(:project) { create(:project, :repository) } + let(:merge_request) { create(:merge_request, source_project: project) } + let(:latest_sha) { 'b83d6e391c22777fca1ed3012fce84f633d7fed0' } + + context 'when pipeline exists for the source project and branch' do + before do + create(:ci_empty_pipeline, project: project, ref: merge_request.source_branch, sha: latest_sha) + end + + it 'updates the head_pipeline_id of the merge_request' do + expect { subject.perform(merge_request.id) }.to change { merge_request.reload.head_pipeline_id } + end + + context 'when merge request sha does not equal pipeline sha' do + before do + merge_request.merge_request_diff.update(head_commit_sha: 'different_sha') + end + + it 'does not update head_pipeline_id' do + expect { subject.perform(merge_request.id) }.to raise_error(ArgumentError) + + expect(merge_request.reload.head_pipeline_id).to eq(nil) + end + end + end + + context 'when pipeline does not exist for the source project and branch' do + it 'does not update the head_pipeline_id of the merge_request' do + expect { subject.perform(merge_request.id) }.not_to change { merge_request.reload.head_pipeline_id } + end + end + end +end -- cgit v1.2.1 From 8f78ba554d8cc7ff90a0f1c98b6f641afbc5b4ae Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Tue, 21 Nov 2017 15:11:11 -0200 Subject: Improve MergeRequest#head_pipeline --- app/models/merge_request.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index d2ed6f7a8ae..b9158d3c863 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -146,11 +146,7 @@ class MergeRequest < ActiveRecord::Base end def head_pipeline - return unless head_pipeline_id - - last_pipeline = Ci::Pipeline.find(head_pipeline_id) - - last_pipeline.sha == diff_head_sha ? last_pipeline : nil + super&.sha == diff_head_sha ? super : nil end # Pattern used to extract `!123` merge request references from text -- cgit v1.2.1 From f586dc0735545d96d73dd26ff182ddf2d50dd715 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Thu, 30 Nov 2017 16:00:09 -0200 Subject: Check if head_pipeline is correct before merging --- .../projects/merge_requests_controller.rb | 6 ++-- app/models/merge_request.rb | 12 ++++--- .../projects/merge_requests_controller_spec.rb | 20 +++++++++--- spec/models/merge_request_spec.rb | 37 ++++++++++++---------- 4 files changed, 48 insertions(+), 27 deletions(-) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index abe4e5245b1..ebf7774949a 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.current_head_pipeline - if @merge_request.head_pipeline.active? + if @merge_request.current_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.current_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 b9158d3c863..536ad05a43d 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -145,8 +145,11 @@ class MergeRequest < ActiveRecord::Base '!' end - def head_pipeline - super&.sha == diff_head_sha ? super : nil + # 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 current_head_pipeline + head_pipeline&.sha == diff_head_sha ? head_pipeline : nil end # Pattern used to extract `!123` merge request references from text @@ -826,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? + current_head_pipeline&.success? || current_head_pipeline&.skipped? end def environments_for(current_user) @@ -1001,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 current_head_pipeline && !(current_head_pipeline.success? || current_head_pipeline.active?) return false if last_diff_sha != diff_head_sha true diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index bfdad85c082..51d5d6a52b3 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -324,12 +324,12 @@ describe Projects::MergeRequestsController do end context 'when the pipeline succeeds is passed' do - def merge_when_pipeline_succeeds - post :merge, base_params.merge(sha: merge_request.diff_head_sha, merge_when_pipeline_succeeds: '1') + let!(:head_pipeline) do + create(:ci_empty_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch, head_pipeline_of: merge_request) end - before do - create(:ci_empty_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch, head_pipeline_of: merge_request) + def merge_when_pipeline_succeeds + post :merge, base_params.merge(sha: merge_request.diff_head_sha, merge_when_pipeline_succeeds: '1') end it 'returns :merge_when_pipeline_succeeds' do @@ -354,6 +354,18 @@ describe Projects::MergeRequestsController do project.update_column(:only_allow_merge_if_pipeline_succeeds, true) end + context 'and head pipeline is not the current one' do + before do + head_pipeline.update(sha: 'not_current_sha') + end + + it 'returns :failed' do + merge_when_pipeline_succeeds + + expect(json_response).to eq('status' => 'failed') + end + end + it 'returns :merge_when_pipeline_succeeds' do merge_when_pipeline_succeeds diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index e10f375d42b..07860b8e91f 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -827,29 +827,34 @@ describe MergeRequest do end end - describe '#head_pipeline' do + context 'head pipeline' do before do allow(subject).to receive(:diff_head_sha).and_return('lastsha') end - it 'returns nil for MR without head_pipeline_id' do - subject.update_attribute(:head_pipeline_id, nil) + describe '#head_pipeline' do + it 'returns nil for MR without head_pipeline_id' do + subject.update_attribute(:head_pipeline_id, nil) - expect(subject.head_pipeline).to be_nil + expect(subject.head_pipeline).to be_nil + end end - it 'returns nil for MR with old pipeline' do - pipeline = create(:ci_empty_pipeline, sha: 'notlatestsha') - subject.update_attribute(:head_pipeline_id, pipeline.id) + describe '#current_head_pipeline' do + it 'returns nil for MR with old pipeline' do + pipeline = create(:ci_empty_pipeline, sha: 'notlatestsha') + subject.update_attribute(:head_pipeline_id, pipeline.id) - expect(subject.head_pipeline).to be_nil - end + expect(subject.current_head_pipeline).to be_nil + end - it 'returns the pipeline for MR with recent pipeline' do - pipeline = create(:ci_empty_pipeline, sha: 'lastsha') - subject.update_attribute(:head_pipeline_id, pipeline.id) + it 'returns the pipeline for MR with recent pipeline' do + pipeline = create(:ci_empty_pipeline, sha: 'lastsha') + subject.update_attribute(:head_pipeline_id, pipeline.id) - expect(subject.head_pipeline).to eq(pipeline) + expect(subject.current_head_pipeline).to eq(subject.head_pipeline) + expect(subject.current_head_pipeline).to eq(pipeline) + end end end @@ -1187,7 +1192,7 @@ describe MergeRequest do context 'when it is only allowed to merge when build is green' do context 'and a failed pipeline is associated' do before do - pipeline.update(status: 'failed') + pipeline.update(status: 'failed', sha: subject.diff_head_sha) allow(subject).to receive(:head_pipeline) { pipeline } end @@ -1196,7 +1201,7 @@ describe MergeRequest do context 'and a successful pipeline is associated' do before do - pipeline.update(status: 'success') + pipeline.update(status: 'success', sha: subject.diff_head_sha) allow(subject).to receive(:head_pipeline) { pipeline } end @@ -1205,7 +1210,7 @@ describe MergeRequest do context 'and a skipped pipeline is associated' do before do - pipeline.update(status: 'skipped') + pipeline.update(status: 'skipped', sha: subject.diff_head_sha) allow(subject).to receive(:head_pipeline) { pipeline } end -- cgit v1.2.1 From 5cf3ff27c8f955e701837529d72a070697a41a04 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Fri, 1 Dec 2017 11:26:51 -0200 Subject: Use actual head pipeline on merge request serializer --- .../projects/merge_requests_controller.rb | 6 ++--- app/models/merge_request.rb | 6 ++--- app/presenters/merge_request_presenter.rb | 2 +- app/serializers/merge_request_entity.rb | 2 +- spec/models/merge_request_spec.rb | 8 +++--- spec/serializers/merge_request_entity_spec.rb | 30 +++++++++++++++------- 6 files changed, 33 insertions(+), 21 deletions(-) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index ebf7774949a..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.current_head_pipeline + return :failed unless @merge_request.actual_head_pipeline - if @merge_request.current_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.current_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 536ad05a43d..f2d639a3382 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -148,7 +148,7 @@ class MergeRequest < ActiveRecord::Base # 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 current_head_pipeline + def actual_head_pipeline head_pipeline&.sha == diff_head_sha ? head_pipeline : nil end @@ -831,7 +831,7 @@ class MergeRequest < ActiveRecord::Base return true unless project.only_allow_merge_if_pipeline_succeeds? return true unless head_pipeline - current_head_pipeline&.success? || current_head_pipeline&.skipped? + actual_head_pipeline&.success? || actual_head_pipeline&.skipped? end def environments_for(current_user) @@ -1005,7 +1005,7 @@ class MergeRequest < ActiveRecord::Base return true if autocomplete_precheck return false unless mergeable?(skip_ci_check: true) - return false if current_head_pipeline && !(current_head_pipeline.success? || current_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/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 07860b8e91f..34fae89b430 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -840,20 +840,20 @@ describe MergeRequest do end end - describe '#current_head_pipeline' do + describe '#actual_head_pipeline' do it 'returns nil for MR with old pipeline' do pipeline = create(:ci_empty_pipeline, sha: 'notlatestsha') subject.update_attribute(:head_pipeline_id, pipeline.id) - expect(subject.current_head_pipeline).to be_nil + expect(subject.actual_head_pipeline).to be_nil end it 'returns the pipeline for MR with recent pipeline' do pipeline = create(:ci_empty_pipeline, sha: 'lastsha') subject.update_attribute(:head_pipeline_id, pipeline.id) - expect(subject.current_head_pipeline).to eq(subject.head_pipeline) - expect(subject.current_head_pipeline).to eq(pipeline) + expect(subject.actual_head_pipeline).to eq(subject.head_pipeline) + expect(subject.actual_head_pipeline).to eq(pipeline) end end end diff --git a/spec/serializers/merge_request_entity_spec.rb b/spec/serializers/merge_request_entity_spec.rb index f9285049c0d..1ad672fd355 100644 --- a/spec/serializers/merge_request_entity_spec.rb +++ b/spec/serializers/merge_request_entity_spec.rb @@ -5,22 +5,34 @@ describe MergeRequestEntity do let(:resource) { create(:merge_request, source_project: project, target_project: project) } let(:user) { create(:user) } - let(:request) { double('request', current_user: user) } + let(:request) { double('request', current_user: user, project: project) } subject do described_class.new(resource, request: request).as_json end - it 'includes pipeline' do - req = double('request', current_user: user) - pipeline = build_stubbed(:ci_pipeline) - allow(resource).to receive(:head_pipeline).and_return(pipeline) + describe 'pipeline' do + let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: resource.source_branch, sha: resource.source_branch_sha, head_pipeline_of: resource) } - pipeline_payload = PipelineDetailsEntity - .represent(pipeline, request: req) - .as_json + context 'when is up to date' do + let(:req) { double('request', current_user: user, project: project) } - expect(subject[:pipeline]).to eq(pipeline_payload) + it 'returns pipeline' do + pipeline_payload = PipelineDetailsEntity + .represent(pipeline, request: req) + .as_json + + expect(subject[:pipeline]).to eq(pipeline_payload) + end + end + + context 'when is not up to date' do + it 'returns nil' do + pipeline.update(sha: "not up to date") + + expect(subject[:pipeline]).to be_nil + end + end end it 'includes issues_links' do -- cgit v1.2.1 From bac143ea63d74a33a73274746d24e6900b84cc6a Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Fri, 1 Dec 2017 13:33:24 -0200 Subject: use actual head pipeline on merge request presenter --- spec/models/merge_request_spec.rb | 14 ++++++++++++++ spec/presenters/merge_request_presenter_spec.rb | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 34fae89b430..e606fb027b5 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -838,6 +838,14 @@ describe MergeRequest do expect(subject.head_pipeline).to be_nil end + + context 'when the source project does not exist' do + it 'returns nil' do + allow(subject).to receive(:source_project).and_return(nil) + + expect(subject.head_pipeline).to be_nil + end + end end describe '#actual_head_pipeline' do @@ -855,6 +863,12 @@ describe MergeRequest do expect(subject.actual_head_pipeline).to eq(subject.head_pipeline) expect(subject.actual_head_pipeline).to eq(pipeline) end + + it 'returns nil when source project does not exist' do + allow(subject).to receive(:source_project).and_return(nil) + + expect(subject.actual_head_pipeline).to be_nil + end end end diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb index 5e114434a67..f325d1776e4 100644 --- a/spec/presenters/merge_request_presenter_spec.rb +++ b/spec/presenters/merge_request_presenter_spec.rb @@ -31,7 +31,7 @@ describe MergeRequestPresenter do let(:pipeline) { build_stubbed(:ci_pipeline) } before do - allow(resource).to receive(:head_pipeline).and_return(pipeline) + allow(resource).to receive(:actual_head_pipeline).and_return(pipeline) end context 'success with warnings' do -- cgit v1.2.1 From b328cff308431fd28a779f9356c9a43351de2754 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Tue, 5 Dec 2017 15:14:37 -0200 Subject: Fix update head pipeline worker --- app/workers/update_head_pipeline_for_merge_request_worker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workers/update_head_pipeline_for_merge_request_worker.rb b/app/workers/update_head_pipeline_for_merge_request_worker.rb index ebe2435bbe5..0a2e9b63578 100644 --- a/app/workers/update_head_pipeline_for_merge_request_worker.rb +++ b/app/workers/update_head_pipeline_for_merge_request_worker.rb @@ -1,5 +1,5 @@ class UpdateHeadPipelineForMergeRequestWorker - include Sidekiq::Worker + include ApplicationWorker sidekiq_options queue: 'pipeline_default' -- cgit v1.2.1