gitlab-org--gitlab-foss/app/services/ci/create_pipeline_service.rb
Shinya Maeda 7c2b1cb0c3 Fix schedule head pipeline update
Currently, schedule head pipeline update method which executed after
pipeline creation does not take into account of merge reqeust
pipelines. We should use dedicated `all_merge_requests` method
in this case.
2019-05-06 19:18:27 +07:00

121 lines
4.1 KiB
Ruby

# frozen_string_literal: true
module Ci
class CreatePipelineService < BaseService
attr_reader :pipeline
CreateError = Class.new(StandardError)
SEQUENCE = [Gitlab::Ci::Pipeline::Chain::Build,
Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs,
Gitlab::Ci::Pipeline::Chain::Validate::Abilities,
Gitlab::Ci::Pipeline::Chain::Validate::Repository,
Gitlab::Ci::Pipeline::Chain::Validate::Config,
Gitlab::Ci::Pipeline::Chain::Skip,
Gitlab::Ci::Pipeline::Chain::Limit::Size,
Gitlab::Ci::Pipeline::Chain::Populate,
Gitlab::Ci::Pipeline::Chain::Create,
Gitlab::Ci::Pipeline::Chain::Limit::Activity].freeze
def execute(source, ignore_skip_ci: false, save_on_errors: true, trigger_request: nil, schedule: nil, merge_request: nil, **options, &block)
@pipeline = Ci::Pipeline.new
command = Gitlab::Ci::Pipeline::Chain::Command.new(
source: source,
origin_ref: params[:ref],
checkout_sha: params[:checkout_sha],
after_sha: params[:after],
before_sha: params[:before], # The base SHA of the source branch (i.e merge_request.diff_base_sha).
source_sha: params[:source_sha], # The HEAD SHA of the source branch (i.e merge_request.diff_head_sha).
target_sha: params[:target_sha], # The HEAD SHA of the target branch.
trigger_request: trigger_request,
schedule: schedule,
merge_request: merge_request,
ignore_skip_ci: ignore_skip_ci,
save_incompleted: save_on_errors,
seeds_block: block,
variables_attributes: params[:variables_attributes],
project: project,
current_user: current_user,
push_options: params[:push_options] || {},
chat_data: params[:chat_data],
**extra_options(options))
sequence = Gitlab::Ci::Pipeline::Chain::Sequence
.new(pipeline, command, SEQUENCE)
sequence.build! do |pipeline, sequence|
schedule_head_pipeline_update
if sequence.complete?
cancel_pending_pipelines if project.auto_cancel_pending_pipelines?
pipeline_created_counter.increment(source: source)
pipeline.process!
end
end
# If pipeline is not persisted, try to recover IID
pipeline.reset_project_iid unless pipeline.persisted? ||
Feature.disabled?(:ci_pipeline_rewind_iid, project, default_enabled: true)
pipeline
end
def execute!(*args, &block)
execute(*args, &block).tap do |pipeline|
unless pipeline.persisted?
raise CreateError, pipeline.errors.full_messages.join(',')
end
end
end
private
def commit
@commit ||= project.commit(origin_sha || origin_ref)
end
def sha
commit.try(:id)
end
def cancel_pending_pipelines
Gitlab::OptimisticLocking.retry_lock(auto_cancelable_pipelines) do |cancelables|
cancelables.find_each do |cancelable|
cancelable.auto_cancel_running(pipeline)
end
end
end
# rubocop: disable CodeReuse/ActiveRecord
def auto_cancelable_pipelines
project.ci_pipelines
.where(ref: pipeline.ref)
.where.not(id: pipeline.id)
.where.not(sha: project.commit(pipeline.ref).try(:id))
.created_or_pending
end
# rubocop: enable CodeReuse/ActiveRecord
def pipeline_created_counter
@pipeline_created_counter ||= Gitlab::Metrics
.counter(:pipelines_created_total, "Counter of pipelines created")
end
def schedule_head_pipeline_update
pipeline.all_merge_requests.opened.each do |merge_request|
UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id)
end
end
def extra_options(options = {})
# In Ruby 2.4, even when options is empty, f(**options) doesn't work when f
# doesn't have any parameters. We reproduce the Ruby 2.5 behavior by
# checking explicitly that no arguments are given.
raise ArgumentError if options.any?
{} # overridden in EE
end
end
end