From 4ae411ff40352ec21bd10f859b7f3f9f85a7aee6 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Fri, 17 Mar 2017 19:14:27 -0300 Subject: [PATCH 1/6] Preloads head pipeline for each merge request --- app/controllers/concerns/issuable_collections.rb | 2 +- app/models/merge_request.rb | 8 ++------ app/services/ci/create_pipeline_service.rb | 8 +++++++- changelogs/unreleased/issue_27168_2.yml | 4 ++++ ...7205316_add_head_pipeline_id_to_merge_requests.rb | 7 +++++++ db/schema.rb | 2 ++ .../gitlab/import_export/safe_model_attributes.yml | 1 + spec/services/ci/create_pipeline_service_spec.rb | 12 ++++++++++++ 8 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 changelogs/unreleased/issue_27168_2.yml create mode 100644 db/migrate/20170427205316_add_head_pipeline_id_to_merge_requests.rb diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb index 6df2c068745..650ec1e326a 100644 --- a/app/controllers/concerns/issuable_collections.rb +++ b/app/controllers/concerns/issuable_collections.rb @@ -47,7 +47,7 @@ module IssuableCollections end def merge_requests_collection - merge_requests_finder.execute.preload(:source_project, :target_project, :author, :assignee, :labels, :milestone, :merge_request_diff, target_project: :namespace) + merge_requests_finder.execute.preload(:source_project, :target_project, :author, :assignee, :labels, :milestone, :merge_request_diff, :head_pipeline, target_project: :namespace) end def issues_finder diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 35231bab12e..3a2cff6ac21 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -13,6 +13,8 @@ class MergeRequest < ActiveRecord::Base has_one :merge_request_diff, -> { order('merge_request_diffs.id DESC') } + belongs_to :head_pipeline, foreign_key: "head_pipeline_id", class_name: "Ci::Pipeline" + has_many :events, as: :target, dependent: :destroy has_many :merge_requests_closing_issues, class_name: 'MergeRequestsClosingIssues', dependent: :delete_all @@ -829,12 +831,6 @@ class MergeRequest < ActiveRecord::Base diverged_commits_count > 0 end - def head_pipeline - return unless diff_head_sha && source_project - - @head_pipeline ||= source_project.pipeline_for(source_branch, diff_head_sha) - end - def all_pipelines return Ci::Pipeline.none unless source_project diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb index ccdda08d885..26b744ae3c4 100644 --- a/app/services/ci/create_pipeline_service.rb +++ b/app/services/ci/create_pipeline_service.rb @@ -47,7 +47,7 @@ module Ci end Ci::Pipeline.transaction do - pipeline.save + update_merge_requests_head_pipeline if pipeline.save Ci::CreatePipelineBuildsService .new(project, current_user) @@ -118,6 +118,12 @@ module Ci origin_sha && origin_sha != Gitlab::Git::BLANK_SHA end + def update_merge_requests_head_pipeline + merge_requests = MergeRequest.where(source_branch: @pipeline.ref, source_project: @pipeline.project) + + merge_requests.update_all(head_pipeline_id: @pipeline.id) if merge_requests.any? + end + def error(message, save: false) pipeline.errors.add(:base, message) pipeline.drop if save diff --git a/changelogs/unreleased/issue_27168_2.yml b/changelogs/unreleased/issue_27168_2.yml new file mode 100644 index 00000000000..c91a95323d5 --- /dev/null +++ b/changelogs/unreleased/issue_27168_2.yml @@ -0,0 +1,4 @@ +--- +title: Preloads head pipeline for each merge request +merge_request: +author: diff --git a/db/migrate/20170427205316_add_head_pipeline_id_to_merge_requests.rb b/db/migrate/20170427205316_add_head_pipeline_id_to_merge_requests.rb new file mode 100644 index 00000000000..8fc6e380a77 --- /dev/null +++ b/db/migrate/20170427205316_add_head_pipeline_id_to_merge_requests.rb @@ -0,0 +1,7 @@ +class AddHeadPipelineIdToMergeRequests < ActiveRecord::Migration + DOWNTIME = false + + def change + add_column :merge_requests, :head_pipeline_id, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 722e776c27d..d5b1d3bb0d8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -123,6 +123,7 @@ ActiveRecord::Schema.define(version: 20170506185517) do t.integer "cached_markdown_version" t.boolean "clientside_sentry_enabled", default: false, null: false t.string "clientside_sentry_dsn" + t.string "default_artifacts_expire_in", default: "0", null: false end create_table "audit_events", force: :cascade do |t| @@ -690,6 +691,7 @@ ActiveRecord::Schema.define(version: 20170506185517) do t.integer "cached_markdown_version" t.datetime "last_edited_at" t.integer "last_edited_by_id" + t.integer "head_pipeline_id" end add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 3af2a172e6d..d2ceb1cf9ae 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -158,6 +158,7 @@ MergeRequest: - time_estimate - last_edited_at - last_edited_by_id +- head_pipeline_id MergeRequestDiff: - id - state diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb index fa5014cee07..f2ed66b5e8e 100644 --- a/spec/services/ci/create_pipeline_service_spec.rb +++ b/spec/services/ci/create_pipeline_service_spec.rb @@ -34,6 +34,18 @@ describe Ci::CreatePipelineService, services: true do it { expect(pipeline).to have_attributes(status: 'pending') } it { expect(pipeline.builds.first).to be_kind_of(Ci::Build) } + 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) + merge_request_2 = create(:merge_request, source_branch: 'master', target_branch: "branch_2", source_project: project) + merge_request_3 = create(:merge_request, source_branch: 'other_branch', target_branch: "branch_2", source_project: project) + + head_pipeline = pipeline + + 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_3.reload.head_pipeline).to be_nil + end + context 'auto-cancel enabled' do before do project.update(auto_cancel_pending_pipelines: 'enabled') From 85f0b3a984048d1e5d146a233612a0bc96f12b5c Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Wed, 22 Mar 2017 12:20:44 -0300 Subject: [PATCH 2/6] Add merge requests association to pipeline --- app/models/ci/pipeline.rb | 1 + spec/workers/pipeline_metrics_worker_spec.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index db994b861e5..481f9c8dac8 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -17,6 +17,7 @@ module Ci has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id has_many :builds, foreign_key: :commit_id has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id + has_many :merge_requests, foreign_key: "head_pipeline_id" has_many :pending_builds, -> { pending }, foreign_key: :commit_id, class_name: 'Ci::Build' has_many :retryable_builds, -> { latest.failed_or_canceled }, foreign_key: :commit_id, class_name: 'Ci::Build' diff --git a/spec/workers/pipeline_metrics_worker_spec.rb b/spec/workers/pipeline_metrics_worker_spec.rb index 5dbc0da95c2..dbf2b7251c6 100644 --- a/spec/workers/pipeline_metrics_worker_spec.rb +++ b/spec/workers/pipeline_metrics_worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe PipelineMetricsWorker do let(:project) { create(:project, :repository) } - let!(:merge_request) { create(:merge_request, source_project: project, source_branch: pipeline.ref) } + let!(:merge_request) { create(:merge_request, source_project: project, source_branch: pipeline.ref, head_pipeline_id: pipeline.id) } let(:pipeline) do create(:ci_empty_pipeline, From 24824cbb4c6d2c5ebd08dea03007f65c5df763da Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Wed, 22 Mar 2017 16:36:14 -0300 Subject: [PATCH 3/6] Fix Specs --- changelogs/unreleased/issue_27168_2.yml | 2 +- features/steps/project/merge_requests.rb | 1 + .../projects/merge_requests_controller_spec.rb | 3 ++- spec/features/cycle_analytics_spec.rb | 5 ++++- spec/features/issuables/issuable_list_spec.rb | 3 +++ .../merge_immediately_with_pipeline_spec.rb | 10 ++++++---- .../merge_when_pipeline_succeeds_spec.rb | 5 ++++- .../merge_requests/mini_pipeline_graph_spec.rb | 2 +- .../only_allow_merge_if_build_succeeds_spec.rb | 2 ++ spec/features/merge_requests/widget_spec.rb | 17 +++++++++++++---- spec/lib/gitlab/cycle_analytics/events_spec.rb | 4 ++++ spec/lib/gitlab/import_export/all_models.yml | 1 + spec/models/ci/pipeline_spec.rb | 2 +- spec/models/cycle_analytics/test_spec.rb | 1 + spec/models/merge_request_spec.rb | 16 +++++++--------- .../projects/cycle_analytics_events_spec.rb | 1 + ...merge_when_pipeline_succeeds_service_spec.rb | 6 ++++++ .../merge_requests/update_service_spec.rb | 4 +++- 18 files changed, 61 insertions(+), 24 deletions(-) diff --git a/changelogs/unreleased/issue_27168_2.yml b/changelogs/unreleased/issue_27168_2.yml index c91a95323d5..c67692493e0 100644 --- a/changelogs/unreleased/issue_27168_2.yml +++ b/changelogs/unreleased/issue_27168_2.yml @@ -1,4 +1,4 @@ --- -title: Preloads head pipeline for each merge request +title: Preloads head pipeline for merge request collection merge_request: author: diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb index 4b7d6cd840b..8bd2065ac34 100644 --- a/features/steps/project/merge_requests.rb +++ b/features/steps/project/merge_requests.rb @@ -544,6 +544,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps project = merge_request.source_project project.enable_ci pipeline = create :ci_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch + merge_request.update(head_pipeline: pipeline) create :ci_build, pipeline: pipeline end diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 0483c6b7879..bc13a8123a5 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -354,7 +354,8 @@ describe Projects::MergeRequestsController do end before do - create(:ci_empty_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch) + pipeline = create(:ci_empty_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch) + merge_request.update(head_pipeline: pipeline) end it 'returns :merge_when_pipeline_succeeds' do diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb index df2714f91ff..57826fe872b 100644 --- a/spec/features/cycle_analytics_spec.rb +++ b/spec/features/cycle_analytics_spec.rb @@ -9,10 +9,13 @@ feature 'Cycle Analytics', feature: true, js: true do let(:mr) { create_merge_request_closing_issue(issue, commit_message: "References #{issue.to_reference}") } let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha) } + before { mr.update(head_pipeline: pipeline) } + context 'as an allowed user' do context 'when project is new' do before do - project.team << [user, :master] + project.add_master(user) + mr.update(head_pipeline_id: pipeline.id) login_as(user) visit namespace_project_cycle_analytics_path(project.namespace, project) wait_for_ajax diff --git a/spec/features/issuables/issuable_list_spec.rb b/spec/features/issuables/issuable_list_spec.rb index f3ec80bb149..414838fa22e 100644 --- a/spec/features/issuables/issuable_list_spec.rb +++ b/spec/features/issuables/issuable_list_spec.rb @@ -52,6 +52,9 @@ describe 'issuable list', feature: true do create(:issue, project: project, author: user) else create(:merge_request, source_project: project, source_branch: generate(:branch)) + source_branch = FFaker::Name.name + pipeline = create(:ci_empty_pipeline, project: project, ref: source_branch, status: %w(running failed success).sample, sha: 'any') + create(:merge_request, title: FFaker::Lorem.sentence, source_project: project, source_branch: source_branch, head_pipeline: pipeline) end 2.times do diff --git a/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb b/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb index 497240803d4..4f9a69baad8 100644 --- a/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb +++ b/spec/features/merge_requests/merge_immediately_with_pipeline_spec.rb @@ -4,16 +4,18 @@ feature 'Merge immediately', :feature, :js do let(:user) { create(:user) } let(:project) { create(:project, :public) } - let(:merge_request) do + let!(:merge_request) do create(:merge_request_with_diffs, source_project: project, author: user, - title: 'Bug NS-04') + title: 'Bug NS-04', + head_pipeline: pipeline, + source_branch: pipeline.ref) end let(:pipeline) do create(:ci_pipeline, project: project, - sha: merge_request.diff_head_sha, - ref: merge_request.source_branch) + ref: 'master', + sha: project.repository.commit('master').id) end before { project.team << [user, :master] } diff --git a/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb b/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb index cd540ca113a..9367789c7d4 100644 --- a/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb +++ b/spec/features/merge_requests/merge_when_pipeline_succeeds_spec.rb @@ -16,7 +16,10 @@ feature 'Merge When Pipeline Succeeds', :feature, :js do ref: merge_request.source_branch) end - before { project.team << [user, :master] } + before do + project.add_master(user) + merge_request.update(head_pipeline_id: pipeline.id) + end context 'when there is active pipeline for merge request' do background do diff --git a/spec/features/merge_requests/mini_pipeline_graph_spec.rb b/spec/features/merge_requests/mini_pipeline_graph_spec.rb index 449a60c1d05..5b2798af32f 100644 --- a/spec/features/merge_requests/mini_pipeline_graph_spec.rb +++ b/spec/features/merge_requests/mini_pipeline_graph_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' feature 'Mini Pipeline Graph', :js, :feature do let(:user) { create(:user) } let(:project) { create(:project, :public) } - let(:merge_request) { create(:merge_request, source_project: project) } + let(:merge_request) { create(:merge_request, source_project: project, head_pipeline: pipeline) } let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: 'master', status: 'running', sha: project.commit.id) } let(:build) { create(:ci_build, pipeline: pipeline, stage: 'test', commands: 'test') } diff --git a/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb b/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb index 4a590e3bf68..981989b0095 100644 --- a/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb +++ b/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb @@ -27,6 +27,8 @@ feature 'Only allow merge requests to be merged if the pipeline succeeds', featu status: status) end + before { merge_request.update(head_pipeline: pipeline) } + context 'when merge requests can only be merged if the pipeline succeeds' do before do project.update_attribute(:only_allow_merge_if_pipeline_succeeds, true) diff --git a/spec/features/merge_requests/widget_spec.rb b/spec/features/merge_requests/widget_spec.rb index d918181a238..02193dbfc8d 100644 --- a/spec/features/merge_requests/widget_spec.rb +++ b/spec/features/merge_requests/widget_spec.rb @@ -89,6 +89,8 @@ describe 'Merge request', :feature, :js do statuses: [commit_status]) create(:ci_build, :pending, pipeline: pipeline) + merge_request.update(head_pipeline_id: pipeline.id) + visit namespace_project_merge_request_path(project.namespace, project, merge_request) end @@ -101,10 +103,15 @@ describe 'Merge request', :feature, :js do context 'when merge request is in the blocked pipeline state' do before do - create(:ci_pipeline, project: project, - sha: merge_request.diff_head_sha, - ref: merge_request.source_branch, - status: :manual) + pipeline = create( + :ci_pipeline, + project: project, + sha: merge_request.diff_head_sha, + ref: merge_request.source_branch, + status: :manual + ) + + merge_request.update(head_pipeline_id: pipeline.id) visit namespace_project_merge_request_path(project.namespace, project, @@ -129,6 +136,8 @@ describe 'Merge request', :feature, :js do statuses: [commit_status]) create(:ci_build, :pending, pipeline: pipeline) + merge_request.update(head_pipeline_id: pipeline.id) + visit namespace_project_merge_request_path(project.namespace, project, merge_request) end diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 0d56bdd0ebd..8753679e233 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -130,6 +130,8 @@ describe 'cycle analytics events' do end before do + merge_request.update(head_pipeline_id: pipeline.id) + create(:ci_build, pipeline: pipeline, status: :success, author: user) create(:ci_build, pipeline: pipeline, status: :success, author: user) @@ -226,6 +228,8 @@ describe 'cycle analytics events' do end before do + merge_request.update(head_pipeline_id: pipeline.id) + create(:ci_build, pipeline: pipeline, status: :success, author: user) create(:ci_build, pipeline: pipeline, status: :success, author: user) diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 688e731bf15..63797c0fc0e 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -85,6 +85,7 @@ merge_requests: - merge_requests_closing_issues - metrics - timelogs +- head_pipeline merge_request_diff: - merge_request pipelines: diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 208c8cb1c3d..86ed37b50aa 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -1044,8 +1044,8 @@ describe Ci::Pipeline, models: true do let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master', sha: 'a288a022a53a5a944fae87bcec6efc87b7061808') } it "returns merge requests whose `diff_head_sha` matches the pipeline's SHA" do - merge_request = create(:merge_request, source_project: project, source_branch: pipeline.ref) allow_any_instance_of(MergeRequest).to receive(:diff_head_sha) { 'a288a022a53a5a944fae87bcec6efc87b7061808' } + merge_request = create(:merge_request, source_project: project, head_pipeline: pipeline, , source_branch: pipeline.ref) expect(pipeline.merge_requests).to eq([merge_request]) end diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb index c2ba012a0e6..d0b919efcf9 100644 --- a/spec/models/cycle_analytics/test_spec.rb +++ b/spec/models/cycle_analytics/test_spec.rb @@ -14,6 +14,7 @@ describe 'CycleAnalytics#test', feature: true do issue = context.create(:issue, project: context.project) merge_request = context.create_merge_request_closing_issue(issue) pipeline = context.create(:ci_pipeline, ref: merge_request.source_branch, sha: merge_request.diff_head_sha, project: context.project) + merge_request.update(head_pipeline: pipeline) { pipeline: pipeline, issue: issue } end, start_time_conditions: [["pipeline is started", -> (context, data) { data[:pipeline].run! }]], diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 6cf3dd30ead..45a5cd049a2 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -760,13 +760,9 @@ describe MergeRequest, models: true do describe '#head_pipeline' do describe 'when the source project exists' do it 'returns the latest pipeline' do - pipeline = double(:ci_pipeline, ref: 'master') - - allow(subject).to receive(:diff_head_sha).and_return('123abc') - - expect(subject.source_project).to receive(:pipeline_for). - with('master', '123abc'). - and_return(pipeline) + sha = "123abc" + pipeline = create(:ci_empty_pipeline, project: subject.source_project, ref: 'master', status: 'running', sha: sha) + subject.update(head_pipeline: pipeline) expect(subject.head_pipeline).to eq(pipeline) end @@ -1504,11 +1500,13 @@ describe MergeRequest, models: true do describe '#mergeable_with_slash_command?' do def create_pipeline(status) - create(:ci_pipeline_with_one_job, + pipeline = create(:ci_pipeline_with_one_job, project: project, ref: merge_request.source_branch, sha: merge_request.diff_head_sha, status: status) + + merge_request.update(head_pipeline: pipeline) end let(:project) { create(:project, :public, :repository, only_allow_merge_if_pipeline_succeeds: true) } @@ -1594,7 +1592,7 @@ describe MergeRequest, models: true do context 'with running pipeline' do before do - create_pipeline(:running) + merge_request.update(head_pipeline: create_pipeline(:running)) end it 'is mergeable' do diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index c5a45949841..d92daa345b3 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -122,6 +122,7 @@ describe 'cycle analytics events', api: true do mr = create_merge_request_closing_issue(issue, commit_message: "References #{issue.to_reference}") pipeline = create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha) + mr.update(head_pipeline_id: pipeline.id) pipeline.run create(:ci_build, pipeline: pipeline, status: :success, author: user) diff --git a/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb b/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb index 769b3193275..b0304b3b73f 100644 --- a/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb +++ b/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb @@ -82,6 +82,10 @@ describe MergeRequests::MergeWhenPipelineSucceedsService do sha: merge_request_head, status: 'success') end + before do + mr_merge_if_green_enabled.update(head_pipeline: triggering_pipeline) + end + it "merges all merge requests with merge when the pipeline succeeds enabled" do expect(MergeWorker).to receive(:perform_async) service.trigger(triggering_pipeline) @@ -124,6 +128,8 @@ describe MergeRequests::MergeWhenPipelineSucceedsService do sha: mr_conflict.diff_head_sha, status: 'success') end + before { mr_conflict.update(head_pipeline_id: conflict_pipeline.id) } + it 'does not merge the merge request' do expect(MergeWorker).not_to receive(:perform_async) diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index 31487c0f794..e5071c2f447 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -174,11 +174,13 @@ describe MergeRequests::UpdateService, services: true do context 'with active pipeline' do before do service_mock = double - create(:ci_pipeline_with_one_job, + pipeline = create(:ci_pipeline_with_one_job, project: project, ref: merge_request.source_branch, sha: merge_request.diff_head_sha) + merge_request.update(head_pipeline_id: pipeline.id) + expect(MergeRequests::MergeWhenPipelineSucceedsService).to receive(:new).with(project, user). and_return(service_mock) expect(service_mock).to receive(:execute).with(merge_request) From 1bf2dacf2002fabf3b7bd364031d9020e5d0b624 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Mon, 27 Mar 2017 19:19:28 -0300 Subject: [PATCH 4/6] Populate merge requests head_pipeline_id --- ...dd_head_pipeline_for_each_merge_request.rb | 23 +++++++++++++++++++ db/schema.rb | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 db/post_migrate/20170428170547_add_head_pipeline_for_each_merge_request.rb diff --git a/db/post_migrate/20170428170547_add_head_pipeline_for_each_merge_request.rb b/db/post_migrate/20170428170547_add_head_pipeline_for_each_merge_request.rb new file mode 100644 index 00000000000..0e139c28402 --- /dev/null +++ b/db/post_migrate/20170428170547_add_head_pipeline_for_each_merge_request.rb @@ -0,0 +1,23 @@ +class AddHeadPipelineForEachMergeRequest < ActiveRecord::Migration + DOWNTIME = false + + class Pipeline < ActiveRecord::Base + self.table_name = "ci_pipelines" + + def self.last_per_branch + select('ref, MAX(id) as head_id, project_id').group(:ref).group(:project_id) + end + end + + class MergeRequest < ActiveRecord::Base; end + + def up + Pipeline.last_per_branch.each do |pipeline| + mrs = MergeRequest.where(source_branch: pipeline.ref, source_project_id: pipeline.project_id) + mrs.update_all(head_pipeline_id: pipeline.head_id) + end + end + + def down + end +end diff --git a/db/schema.rb b/db/schema.rb index d5b1d3bb0d8..d0e10f00ffd 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -114,6 +114,7 @@ ActiveRecord::Schema.define(version: 20170506185517) do t.string "plantuml_url" t.boolean "plantuml_enabled" t.integer "terminal_max_session_time", default: 0, null: false + t.string "default_artifacts_expire_in", default: "0", null: false t.integer "unique_ips_limit_per_user" t.integer "unique_ips_limit_time_window" t.boolean "unique_ips_limit_enabled", default: false, null: false @@ -123,7 +124,6 @@ ActiveRecord::Schema.define(version: 20170506185517) do t.integer "cached_markdown_version" t.boolean "clientside_sentry_enabled", default: false, null: false t.string "clientside_sentry_dsn" - t.string "default_artifacts_expire_in", default: "0", null: false end create_table "audit_events", force: :cascade do |t| From d9bebd89dfcf7e4b163b271eea3d7a5c3e99fb5d Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Tue, 28 Mar 2017 17:04:14 -0300 Subject: [PATCH 5/6] Fix specs 2 --- app/models/ci/pipeline.rb | 11 ++----- ...dd_head_pipeline_for_each_merge_request.rb | 30 ++++++++++--------- .../merge_requests_controller_spec.rb | 5 +++- spec/features/cycle_analytics_spec.rb | 13 ++++---- spec/features/merge_requests/widget_spec.rb | 6 ++-- .../lib/gitlab/cycle_analytics/events_spec.rb | 4 +-- spec/models/ci/pipeline_spec.rb | 2 +- spec/models/merge_request_spec.rb | 4 ++- ...rge_when_pipeline_succeeds_service_spec.rb | 2 +- .../merge_requests/update_service_spec.rb | 2 +- spec/workers/pipeline_metrics_worker_spec.rb | 2 +- 11 files changed, 43 insertions(+), 38 deletions(-) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 481f9c8dac8..81c30b0e077 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -17,6 +17,9 @@ module Ci has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id has_many :builds, foreign_key: :commit_id has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id + + # Merge requests for which the current pipeline is running against + # the merge request's latest commit. has_many :merge_requests, foreign_key: "head_pipeline_id" has_many :pending_builds, -> { pending }, foreign_key: :commit_id, class_name: 'Ci::Build' @@ -382,14 +385,6 @@ module Ci project.execute_services(data, :pipeline_hooks) end - # Merge requests for which the current pipeline is running against - # the merge request's latest commit. - def merge_requests - @merge_requests ||= project.merge_requests - .where(source_branch: self.ref) - .select { |merge_request| merge_request.head_pipeline.try(:id) == self.id } - end - # All the merge requests for which the current pipeline runs/ran against def all_merge_requests @all_merge_requests ||= project.merge_requests.where(source_branch: ref) diff --git a/db/post_migrate/20170428170547_add_head_pipeline_for_each_merge_request.rb b/db/post_migrate/20170428170547_add_head_pipeline_for_each_merge_request.rb index 0e139c28402..bc3850c0c23 100644 --- a/db/post_migrate/20170428170547_add_head_pipeline_for_each_merge_request.rb +++ b/db/post_migrate/20170428170547_add_head_pipeline_for_each_merge_request.rb @@ -1,21 +1,23 @@ class AddHeadPipelineForEachMergeRequest < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + DOWNTIME = false - class Pipeline < ActiveRecord::Base - self.table_name = "ci_pipelines" - - def self.last_per_branch - select('ref, MAX(id) as head_id, project_id').group(:ref).group(:project_id) - end - end - - class MergeRequest < ActiveRecord::Base; end - def up - Pipeline.last_per_branch.each do |pipeline| - mrs = MergeRequest.where(source_branch: pipeline.ref, source_project_id: pipeline.project_id) - mrs.update_all(head_pipeline_id: pipeline.head_id) - end + disable_statement_timeout + + pipelines = Arel::Table.new(:ci_pipelines) + merge_requests = Arel::Table.new(:merge_requests) + + head_id = pipelines. + project(Arel::Nodes::NamedFunction.new('max', [pipelines[:id]])). + from(pipelines). + where(pipelines[:ref].eq(merge_requests[:source_branch])). + where(pipelines[:project_id].eq(merge_requests[:source_project_id])) + + sub_query = Arel::Nodes::SqlLiteral.new(Arel::Nodes::Grouping.new(head_id).to_sql) + + update_column_in_batches(:merge_requests, :head_pipeline_id, sub_query) end def down diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index bc13a8123a5..d9dae999a87 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -1200,7 +1200,10 @@ describe Projects::MergeRequestsController do let(:status) { pipeline.detailed_status(double('user')) } - before { get_pipeline_status } + before do + merge_request.update(head_pipeline: pipeline) + get_pipeline_status + end it 'return a detailed head_pipeline status in json' do expect(response).to have_http_status(:ok) diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb index 57826fe872b..5553687707d 100644 --- a/spec/features/cycle_analytics_spec.rb +++ b/spec/features/cycle_analytics_spec.rb @@ -9,14 +9,17 @@ feature 'Cycle Analytics', feature: true, js: true do let(:mr) { create_merge_request_closing_issue(issue, commit_message: "References #{issue.to_reference}") } let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha) } - before { mr.update(head_pipeline: pipeline) } + before do + allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([issue]) + end context 'as an allowed user' do context 'when project is new' do before do project.add_master(user) - mr.update(head_pipeline_id: pipeline.id) + login_as(user) + visit namespace_project_cycle_analytics_path(project.namespace, project) wait_for_ajax end @@ -33,8 +36,8 @@ feature 'Cycle Analytics', feature: true, js: true do context "when there's cycle analytics data" do before do - project.team << [user, :master] - + mr.update(head_pipeline: pipeline) + project.add_master(user) create_cycle deploy_master @@ -87,7 +90,7 @@ feature 'Cycle Analytics', feature: true, js: true do context "as a guest" do before do - project.team << [guest, :guest] + project.add_guest(guest) allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([issue]) create_cycle diff --git a/spec/features/merge_requests/widget_spec.rb b/spec/features/merge_requests/widget_spec.rb index 02193dbfc8d..b1255ac0bd5 100644 --- a/spec/features/merge_requests/widget_spec.rb +++ b/spec/features/merge_requests/widget_spec.rb @@ -89,7 +89,7 @@ describe 'Merge request', :feature, :js do statuses: [commit_status]) create(:ci_build, :pending, pipeline: pipeline) - merge_request.update(head_pipeline_id: pipeline.id) + merge_request.update(head_pipeline: pipeline) visit namespace_project_merge_request_path(project.namespace, project, merge_request) end @@ -111,7 +111,7 @@ describe 'Merge request', :feature, :js do status: :manual ) - merge_request.update(head_pipeline_id: pipeline.id) + merge_request.update(head_pipeline: pipeline) visit namespace_project_merge_request_path(project.namespace, project, @@ -136,7 +136,7 @@ describe 'Merge request', :feature, :js do statuses: [commit_status]) create(:ci_build, :pending, pipeline: pipeline) - merge_request.update(head_pipeline_id: pipeline.id) + merge_request.update(head_pipeline: pipeline) visit namespace_project_merge_request_path(project.namespace, project, merge_request) end diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 8753679e233..3610a0354e8 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -130,7 +130,7 @@ describe 'cycle analytics events' do end before do - merge_request.update(head_pipeline_id: pipeline.id) + merge_request.update(head_pipeline: pipeline) create(:ci_build, pipeline: pipeline, status: :success, author: user) create(:ci_build, pipeline: pipeline, status: :success, author: user) @@ -228,7 +228,7 @@ describe 'cycle analytics events' do end before do - merge_request.update(head_pipeline_id: pipeline.id) + merge_request.update(head_pipeline: pipeline) create(:ci_build, pipeline: pipeline, status: :success, author: user) create(:ci_build, pipeline: pipeline, status: :success, author: user) diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 86ed37b50aa..06e990a0574 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -1045,7 +1045,7 @@ describe Ci::Pipeline, models: true do it "returns merge requests whose `diff_head_sha` matches the pipeline's SHA" do allow_any_instance_of(MergeRequest).to receive(:diff_head_sha) { 'a288a022a53a5a944fae87bcec6efc87b7061808' } - merge_request = create(:merge_request, source_project: project, head_pipeline: pipeline, , source_branch: pipeline.ref) + merge_request = create(:merge_request, source_project: project, head_pipeline: pipeline, source_branch: pipeline.ref) expect(pipeline.merge_requests).to eq([merge_request]) end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 45a5cd049a2..1db1640f5e5 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -1507,6 +1507,8 @@ describe MergeRequest, models: true do status: status) merge_request.update(head_pipeline: pipeline) + + pipeline end let(:project) { create(:project, :public, :repository, only_allow_merge_if_pipeline_succeeds: true) } @@ -1592,7 +1594,7 @@ describe MergeRequest, models: true do context 'with running pipeline' do before do - merge_request.update(head_pipeline: create_pipeline(:running)) + create_pipeline(:running) end it 'is mergeable' do diff --git a/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb b/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb index b0304b3b73f..3ef5135e6a3 100644 --- a/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb +++ b/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb @@ -128,7 +128,7 @@ describe MergeRequests::MergeWhenPipelineSucceedsService do sha: mr_conflict.diff_head_sha, status: 'success') end - before { mr_conflict.update(head_pipeline_id: conflict_pipeline.id) } + before { mr_conflict.update(head_pipeline: conflict_pipeline) } it 'does not merge the merge request' do expect(MergeWorker).not_to receive(:perform_async) diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index e5071c2f447..07f5440cc36 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -179,7 +179,7 @@ describe MergeRequests::UpdateService, services: true do ref: merge_request.source_branch, sha: merge_request.diff_head_sha) - merge_request.update(head_pipeline_id: pipeline.id) + merge_request.update(head_pipeline: pipeline) expect(MergeRequests::MergeWhenPipelineSucceedsService).to receive(:new).with(project, user). and_return(service_mock) diff --git a/spec/workers/pipeline_metrics_worker_spec.rb b/spec/workers/pipeline_metrics_worker_spec.rb index dbf2b7251c6..ef71125c0b6 100644 --- a/spec/workers/pipeline_metrics_worker_spec.rb +++ b/spec/workers/pipeline_metrics_worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe PipelineMetricsWorker do let(:project) { create(:project, :repository) } - let!(:merge_request) { create(:merge_request, source_project: project, source_branch: pipeline.ref, head_pipeline_id: pipeline.id) } + let!(:merge_request) { create(:merge_request, source_project: project, source_branch: pipeline.ref, head_pipeline: pipeline) } let(:pipeline) do create(:ci_empty_pipeline, From 2ccee7161a58ea04c66b216ccb57e522850f5d95 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Fri, 5 May 2017 16:00:18 -0300 Subject: [PATCH 6/6] Small code improvements and add migration spec --- app/services/ci/create_pipeline_service.rb | 5 +-- ...add_head_pipeline_id_to_merge_requests.rb} | 0 ...d_head_pipeline_for_each_merge_request.rb} | 0 db/schema.rb | 3 +- spec/features/cycle_analytics_spec.rb | 6 +-- spec/lib/gitlab/import_export/all_models.yml | 1 + ...ad_pipeline_for_each_merge_request_spec.rb | 33 +++++++++++++++ spec/models/merge_request_spec.rb | 3 +- .../ci/create_pipeline_service_spec.rb | 40 +++++++++++++++---- 9 files changed, 72 insertions(+), 19 deletions(-) rename db/migrate/{20170427205316_add_head_pipeline_id_to_merge_requests.rb => 20170507205316_add_head_pipeline_id_to_merge_requests.rb} (100%) rename db/post_migrate/{20170428170547_add_head_pipeline_for_each_merge_request.rb => 20170508170547_add_head_pipeline_for_each_merge_request.rb} (100%) create mode 100644 spec/migrations/add_head_pipeline_for_each_merge_request_spec.rb diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb index 26b744ae3c4..1f6c1f4a7f6 100644 --- a/app/services/ci/create_pipeline_service.rb +++ b/app/services/ci/create_pipeline_service.rb @@ -119,9 +119,8 @@ module Ci end def update_merge_requests_head_pipeline - merge_requests = MergeRequest.where(source_branch: @pipeline.ref, source_project: @pipeline.project) - - merge_requests.update_all(head_pipeline_id: @pipeline.id) if merge_requests.any? + MergeRequest.where(source_branch: @pipeline.ref, source_project: @pipeline.project). + update_all(head_pipeline_id: @pipeline.id) end def error(message, save: false) diff --git a/db/migrate/20170427205316_add_head_pipeline_id_to_merge_requests.rb b/db/migrate/20170507205316_add_head_pipeline_id_to_merge_requests.rb similarity index 100% rename from db/migrate/20170427205316_add_head_pipeline_id_to_merge_requests.rb rename to db/migrate/20170507205316_add_head_pipeline_id_to_merge_requests.rb diff --git a/db/post_migrate/20170428170547_add_head_pipeline_for_each_merge_request.rb b/db/post_migrate/20170508170547_add_head_pipeline_for_each_merge_request.rb similarity index 100% rename from db/post_migrate/20170428170547_add_head_pipeline_for_each_merge_request.rb rename to db/post_migrate/20170508170547_add_head_pipeline_for_each_merge_request.rb diff --git a/db/schema.rb b/db/schema.rb index d0e10f00ffd..b91b3e6e977 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170506185517) do +ActiveRecord::Schema.define(version: 20170508170547) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -114,7 +114,6 @@ ActiveRecord::Schema.define(version: 20170506185517) do t.string "plantuml_url" t.boolean "plantuml_enabled" t.integer "terminal_max_session_time", default: 0, null: false - t.string "default_artifacts_expire_in", default: "0", null: false t.integer "unique_ips_limit_per_user" t.integer "unique_ips_limit_time_window" t.boolean "unique_ips_limit_enabled", default: false, null: false diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb index 5553687707d..cbeb73d9cae 100644 --- a/spec/features/cycle_analytics_spec.rb +++ b/spec/features/cycle_analytics_spec.rb @@ -9,10 +9,6 @@ feature 'Cycle Analytics', feature: true, js: true do let(:mr) { create_merge_request_closing_issue(issue, commit_message: "References #{issue.to_reference}") } let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha) } - before do - allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([issue]) - end - context 'as an allowed user' do context 'when project is new' do before do @@ -36,8 +32,10 @@ feature 'Cycle Analytics', feature: true, js: true do context "when there's cycle analytics data" do before do + allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([issue]) mr.update(head_pipeline: pipeline) project.add_master(user) + create_cycle deploy_master diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 63797c0fc0e..34f617e23a5 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -103,6 +103,7 @@ pipelines: - manual_actions - artifacts - pipeline_schedule +- merge_requests statuses: - project - pipeline diff --git a/spec/migrations/add_head_pipeline_for_each_merge_request_spec.rb b/spec/migrations/add_head_pipeline_for_each_merge_request_spec.rb new file mode 100644 index 00000000000..bd5f85b901d --- /dev/null +++ b/spec/migrations/add_head_pipeline_for_each_merge_request_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' +require Rails.root.join('db', 'post_migrate', '20170508170547_add_head_pipeline_for_each_merge_request.rb') + +describe AddHeadPipelineForEachMergeRequest do + let(:migration) { described_class.new } + + let!(:project) { create(:empty_project) } + let!(:forked_project_link) { create(:forked_project_link, forked_from_project: project) } + let!(:other_project) { forked_project_link.forked_to_project } + + let!(:pipeline_1) { create(:ci_pipeline, project: project, ref: "branch_1") } + let!(:pipeline_2) { create(:ci_pipeline, project: other_project, ref: "branch_1") } + let!(:pipeline_3) { create(:ci_pipeline, project: other_project, ref: "branch_1") } + let!(:pipeline_4) { create(:ci_pipeline, project: project, ref: "branch_2") } + + let!(:mr_1) { create(:merge_request, source_project: project, target_project: project, source_branch: "branch_1", target_branch: "target_1") } + let!(:mr_2) { create(:merge_request, source_project: other_project, target_project: project, source_branch: "branch_1", target_branch: "target_2") } + let!(:mr_3) { create(:merge_request, source_project: project, target_project: project, source_branch: "branch_2", target_branch: "master") } + let!(:mr_4) { create(:merge_request, source_project: project, target_project: project, source_branch: "branch_3", target_branch: "master") } + + context "#up" do + context "when source_project and source_branch of pipeline are the same of merge request" do + it "sets head_pipeline_id of given merge requests" do + migration.up + + expect(mr_1.reload.head_pipeline_id).to eq(pipeline_1.id) + expect(mr_2.reload.head_pipeline_id).to eq(pipeline_3.id) + expect(mr_3.reload.head_pipeline_id).to eq(pipeline_4.id) + expect(mr_4.reload.head_pipeline_id).to be_nil + end + end + end +end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 1db1640f5e5..ef349530761 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -760,8 +760,7 @@ describe MergeRequest, models: true do describe '#head_pipeline' do describe 'when the source project exists' do it 'returns the latest pipeline' do - sha = "123abc" - pipeline = create(:ci_empty_pipeline, project: subject.source_project, ref: 'master', status: 'running', sha: sha) + pipeline = create(:ci_empty_pipeline, project: subject.source_project, ref: 'master', status: 'running', sha: "123abc") subject.update(head_pipeline: pipeline) expect(subject.head_pipeline).to eq(pipeline) diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb index f2ed66b5e8e..1ff1438ba06 100644 --- a/spec/services/ci/create_pipeline_service_spec.rb +++ b/spec/services/ci/create_pipeline_service_spec.rb @@ -34,16 +34,40 @@ describe Ci::CreatePipelineService, services: true do it { expect(pipeline).to have_attributes(status: 'pending') } it { expect(pipeline.builds.first).to be_kind_of(Ci::Build) } - 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) - merge_request_2 = create(:merge_request, source_branch: 'master', target_branch: "branch_2", source_project: project) - merge_request_3 = create(:merge_request, source_branch: 'other_branch', target_branch: "branch_2", source_project: project) + context '#update_merge_requests_head_pipeline' 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) + merge_request_2 = create(:merge_request, source_branch: 'master', target_branch: "branch_2", source_project: project) - head_pipeline = pipeline + head_pipeline = pipeline - 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_3.reload.head_pipeline).to be_nil + expect(merge_request_1.reload.head_pipeline).to eq(head_pipeline) + expect(merge_request_2.reload.head_pipeline).to eq(head_pipeline) + end + + context 'when there is no pipeline for source branch' do + it "does not update merge request head pipeline" do + merge_request = create(:merge_request, source_branch: 'other_branch', target_branch: "branch_1", source_project: project) + + head_pipeline = pipeline + + expect(merge_request.reload.head_pipeline).not_to eq(head_pipeline) + end + end + + context 'when merge request target project is different from source project' do + let!(:target_project) { create(:empty_project) } + let!(:forked_project_link) { create(:forked_project_link, forked_to_project: project, forked_from_project: target_project) } + + it 'updates head pipeline for merge request' do + merge_request = + create(:merge_request, source_branch: 'master', target_branch: "branch_1", source_project: project, target_project: target_project) + + head_pipeline = pipeline + + expect(merge_request.reload.head_pipeline).to eq(head_pipeline) + end + end end context 'auto-cancel enabled' do