process_pipeline_service.rb 1.97 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
38
        true
      else
Stan Hu's avatar
Stan Hu committed
39
        build.skip
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
        false
      end
    end

    def valid_statuses_for_when(value)
      case value
      when 'on_success'
        %w[success]
      when 'on_failure'
        %w[failed]
      when 'always'
        %w[success failed]
      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
72
73
74
75
76
77
78
79
80
81
82
83
84

    # 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
85
86
  end
end