process_pipeline_service.rb 2.04 KB
Newer Older
1
2
3
4
5
6
7
module Ci
  class ProcessPipelineService < BaseService
    attr_reader :pipeline

    def execute(pipeline)
      @pipeline = pipeline

8
9
      ensure_created_builds! # TODO, remove me in 9.0

Kamil Trzcinski's avatar
Kamil Trzcinski committed
10
11
12
13
      new_builds =
        stage_indexes_of_created_builds.map do |index|
          process_stage(index)
        end
14

Kamil Trzcinski's avatar
Kamil Trzcinski committed
15
      @pipeline.update_status
16

Kamil Trzcinski's avatar
Kamil Trzcinski committed
17
      new_builds.flatten.any?
18
19
20
21
22
23
24
    end

    private

    def process_stage(index)
      current_status = status_for_prior_stages(index)

Kamil Trzcinski's avatar
Kamil Trzcinski committed
25
26
      if HasStatus::COMPLETED_STATUSES.include?(current_status)
        created_builds_in_stage(index).select do |build|
27
28
          Gitlab::OptimisticLocking.retry_lock(build) do |subject|
            process_build(subject, current_status)
Kamil Trzcinski's avatar
Kamil Trzcinski committed
29
          end
30
        end
31
32
33
34
35
      end
    end

    def process_build(build, current_status)
      if valid_statuses_for_when(build.when).include?(current_status)
Stan Hu's avatar
Stan Hu committed
36
        build.enqueue
37
        true
38
      elsif build.barrier?
Kamil Trzcinski's avatar
Kamil Trzcinski committed
39
        build.block
40
        false
41
      else
Stan Hu's avatar
Stan Hu committed
42
        build.skip
43
44
45
46
47
48
49
        false
      end
    end

    def valid_statuses_for_when(value)
      case value
      when 'on_success'
50
        %w[success skipped]
51
52
53
      when 'on_failure'
        %w[failed]
      when 'always'
54
        %w[success failed skipped]
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
      else
        []
      end
    end

    def status_for_prior_stages(index)
      pipeline.builds.where('stage_idx < ?', index).latest.status || 'success'
    end

    def stage_indexes_of_created_builds
      created_builds.order(:stage_idx).pluck('distinct stage_idx')
    end

    def created_builds_in_stage(index)
      created_builds.where(stage_idx: index)
    end

    def created_builds
      pipeline.builds.created
    end
75
76
77
78
79
80
81
82
83
84
85
86
87

    # This method is DEPRECATED and should be removed in 9.0.
    #
    # We need it to maintain backwards compatibility with  previous versions
    # when builds were not created within one transaction with the pipeline.
    #
    def ensure_created_builds!
      return if created_builds.any?

      Ci::CreatePipelineBuildsService
        .new(project, current_user)
        .execute(pipeline)
    end
88
89
  end
end