Introduce service for merge request pipeline creation

We don't have a way to create MR pipeline today, this is one
of the headaches for users.
This change is a preliminary work for the capability.
This commit is contained in:
Shinya Maeda 2019-05-27 19:26:39 +07:00
parent 1bec362138
commit 31afb0e8ad
3 changed files with 109 additions and 25 deletions

View File

@ -60,31 +60,7 @@ module MergeRequests
end
def create_pipeline_for(merge_request, user)
return unless can_create_pipeline_for?(merge_request)
create_detached_merge_request_pipeline(merge_request, user)
end
def create_detached_merge_request_pipeline(merge_request, user)
if can_use_merge_request_ref?(merge_request)
Ci::CreatePipelineService.new(merge_request.source_project, user,
ref: merge_request.ref_path)
.execute(:merge_request_event, merge_request: merge_request)
else
Ci::CreatePipelineService.new(merge_request.source_project, user,
ref: merge_request.source_branch)
.execute(:merge_request_event, merge_request: merge_request)
end
end
def can_create_pipeline_for?(merge_request)
##
# UpdateMergeRequestsWorker could be retried by an exception.
# pipelines for merge request should not be recreated in such case.
return false if merge_request.find_actual_head_pipeline&.triggered_by_merge_request?
return false if merge_request.has_no_commits?
true
MergeRequests::CreatePipelineService.new(project, user).execute(merge_request)
end
def can_use_merge_request_ref?(merge_request)

View File

@ -0,0 +1,37 @@
# frozen_string_literal: true
module MergeRequests
class CreatePipelineService < MergeRequests::BaseService
def execute(merge_request)
return unless can_create_pipeline_for?(merge_request)
create_detached_merge_request_pipeline(merge_request)
end
def create_detached_merge_request_pipeline(merge_request)
if can_use_merge_request_ref?(merge_request)
Ci::CreatePipelineService.new(merge_request.source_project, current_user,
ref: merge_request.ref_path)
.execute(:merge_request_event, merge_request: merge_request)
else
Ci::CreatePipelineService.new(merge_request.source_project, current_user,
ref: merge_request.source_branch)
.execute(:merge_request_event, merge_request: merge_request)
end
end
def can_create_pipeline_for?(merge_request)
##
# UpdateMergeRequestsWorker could be retried by an exception.
# pipelines for merge request should not be recreated in such case.
return false if !allow_duplicate && merge_request.find_actual_head_pipeline&.triggered_by_merge_request?
return false if merge_request.has_no_commits?
true
end
def allow_duplicate
params[:allow_duplicate]
end
end
end

View File

@ -0,0 +1,71 @@
# frozen_string_literal: true
require 'spec_helper'
describe MergeRequests::CreatePipelineService do
set(:project) { create(:project, :repository) }
set(:user) { create(:user) }
let(:service) { described_class.new(project, user, params) }
let(:params) { {} }
before do
project.add_developer(user)
end
describe '#execute' do
subject { service.execute(merge_request) }
before do
stub_ci_pipeline_yaml_file(YAML.dump(config))
end
let(:config) do
{ rspec: { script: 'echo', only: ['merge_requests'] } }
end
let(:merge_request) do
create(:merge_request,
source_branch: 'feature',
source_project: project,
target_branch: 'master',
target_project: project)
end
it 'creates a detached merge request pipeline' do
expect { subject }.to change { Ci::Pipeline.count }.by(1)
expect(subject).to be_persisted
expect(subject).to be_detached_merge_request_pipeline
end
context 'when service is called multiple times' do
it 'creates a pipeline once' do
expect do
service.execute(merge_request)
service.execute(merge_request)
end.to change { Ci::Pipeline.count }.by(1)
end
context 'when allow_duplicate option is true' do
let(:params) { { allow_duplicate: true } }
it 'creates pipelines multiple times' do
expect do
service.execute(merge_request)
service.execute(merge_request)
end.to change { Ci::Pipeline.count }.by(2)
end
end
end
context 'when .gitlab-ci.yml does not have only: [merge_requests] keyword' do
let(:config) do
{ rspec: { script: 'echo' } }
end
it 'does not create a pipeline' do
expect { subject }.not_to change { Ci::Pipeline.count }
end
end
end
end