process_pipeline_service.rb 1.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
module Ci
  class ProcessPipelineService < BaseService
    attr_reader :pipeline

    def execute(pipeline)
      @pipeline = pipeline

      # This method will ensure that our pipeline does have all builds for all stages created
      if created_builds.empty?
        create_builds!
      end

K
Kamil Trzcinski 已提交
13 14 15 16
      new_builds =
        stage_indexes_of_created_builds.map do |index|
          process_stage(index)
        end
17

K
Kamil Trzcinski 已提交
18
      @pipeline.update_status
19

K
Kamil Trzcinski 已提交
20
      new_builds.flatten.any?
21 22 23 24 25 26 27 28 29 30 31
    end

    private

    def create_builds!
      Ci::CreatePipelineBuildsService.new(project, current_user).execute(pipeline)
    end

    def process_stage(index)
      current_status = status_for_prior_stages(index)

K
Kamil Trzcinski 已提交
32 33
      if HasStatus::COMPLETED_STATUSES.include?(current_status)
        created_builds_in_stage(index).select do |build|
34 35
          Gitlab::OptimisticLocking.retry_lock(build) do |subject|
            process_build(subject, current_status)
K
Kamil Trzcinski 已提交
36
          end
37
        end
38 39 40 41 42
      end
    end

    def process_build(build, current_status)
      if valid_statuses_for_when(build.when).include?(current_status)
S
Stan Hu 已提交
43
        build.enqueue
44 45
        true
      else
S
Stan Hu 已提交
46
        build.skip
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 72 73 74 75 76 77 78 79 80
        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
  end
end