Read about our upcoming Code of Conduct on this issue

create_pipeline_service.rb 3.18 KB
Newer Older
1
2
# frozen_string_literal: true

Kamil Trzcinski's avatar
Kamil Trzcinski committed
3
4
module Ci
  class CreatePipelineService < BaseService
5
    attr_reader :pipeline
6

7
8
    CreateError = Class.new(StandardError)

9
10
    SEQUENCE = [Gitlab::Ci::Pipeline::Chain::Build,
                Gitlab::Ci::Pipeline::Chain::Validate::Abilities,
11
12
                Gitlab::Ci::Pipeline::Chain::Validate::Repository,
                Gitlab::Ci::Pipeline::Chain::Validate::Config,
13
                Gitlab::Ci::Pipeline::Chain::Skip,
14
                Gitlab::Ci::Pipeline::Chain::Populate,
15
                Gitlab::Ci::Pipeline::Chain::Create].freeze
16

Shinya Maeda's avatar
Shinya Maeda committed
17
    def execute(source, ignore_skip_ci: false, save_on_errors: true, trigger_request: nil, schedule: nil, merge_request: nil, &block)
18
19
      @pipeline = Ci::Pipeline.new

20
21
22
23
24
25
26
27
      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],
        trigger_request: trigger_request,
        schedule: schedule,
Shinya Maeda's avatar
Shinya Maeda committed
28
        merge_request: merge_request,
29
30
31
        ignore_skip_ci: ignore_skip_ci,
        save_incompleted: save_on_errors,
        seeds_block: block,
32
        variables_attributes: params[:variables_attributes],
33
34
        project: project,
        current_user: current_user)
35

36
37
      sequence = Gitlab::Ci::Pipeline::Chain::Sequence
        .new(pipeline, command, SEQUENCE)
38

39
      sequence.build! do |pipeline, sequence|
40
        schedule_head_pipeline_update
Lin Jen-Shin's avatar
Lin Jen-Shin committed
41

42
        if sequence.complete?
43
44
          cancel_pending_pipelines if project.auto_cancel_pending_pipelines?
          pipeline_created_counter.increment(source: source)
Shinya Maeda's avatar
init    
Shinya Maeda committed
45

46
          pipeline.process!
Shinya Maeda's avatar
init    
Shinya Maeda committed
47
        end
Lin Jen-Shin's avatar
Lin Jen-Shin committed
48
      end
49
50

      pipeline
Lin Jen-Shin's avatar
Lin Jen-Shin committed
51
52
    end

53
54
55
56
57
58
59
60
    def execute!(*args, &block)
      execute(*args, &block).tap do |pipeline|
        unless pipeline.persisted?
          raise CreateError, pipeline.errors.full_messages.join(',')
        end
      end
    end

Lin Jen-Shin's avatar
Lin Jen-Shin committed
61
62
    private

63
64
65
    def commit
      @commit ||= project.commit(origin_sha || origin_ref)
    end
66

67
68
    def sha
      commit.try(:id)
69
70
    end

71
    def cancel_pending_pipelines
72
      Gitlab::OptimisticLocking.retry_lock(auto_cancelable_pipelines) do |cancelables|
73
        cancelables.find_each do |cancelable|
74
          cancelable.auto_cancel_running(pipeline)
75
76
77
78
        end
      end
    end

79
    # rubocop: disable CodeReuse/ActiveRecord
80
    def auto_cancelable_pipelines
81
      project.ci_pipelines
82
83
        .where(ref: pipeline.ref)
        .where.not(id: pipeline.id)
84
        .where.not(sha: project.commit(pipeline.ref).try(:id))
85
86
        .created_or_pending
    end
87
    # rubocop: enable CodeReuse/ActiveRecord
88

89
    def pipeline_created_counter
90
91
      @pipeline_created_counter ||= Gitlab::Metrics
        .counter(:pipelines_created_total, "Counter of pipelines created")
92
    end
93
94
95
96
97
98
99

    def schedule_head_pipeline_update
      related_merge_requests.each do |merge_request|
        UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id)
      end
    end

100
    # rubocop: disable CodeReuse/ActiveRecord
101
    def related_merge_requests
102
      pipeline.project.source_of_merge_requests.opened.where(source_branch: pipeline.ref)
103
    end
104
    # rubocop: enable CodeReuse/ActiveRecord
Kamil Trzcinski's avatar
Kamil Trzcinski committed
105
  end
Kamil Trzcinski's avatar
Kamil Trzcinski committed
106
end