summaryrefslogtreecommitdiff
path: root/lib/gitlab/ci/yaml_processor/result.rb
blob: 15cc0c28296299b408ae0b919b0ea32caaa36353 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# frozen_string_literal: true

# A data object that wraps `Ci::Config` and any messages
# (errors, warnings) generated by the YamlProcessor.
module Gitlab
  module Ci
    class YamlProcessor
      class Result
        attr_reader :errors, :warnings

        def initialize(ci_config: nil, errors: [], warnings: [])
          @ci_config = ci_config
          @errors = errors || []
          @warnings = warnings || []
        end

        def valid?
          errors.empty?
        end

        def stages_attributes
          stages.uniq.map do |stage|
            seeds = stage_builds_attributes(stage)

            { name: stage, index: stages.index(stage), builds: seeds }
          end
        end

        def builds
          jobs.map do |name, _|
            build_attributes(name)
          end
        end

        def stage_builds_attributes(stage)
          jobs.values
            .select { |job| job[:stage] == stage }
            .map { |job| build_attributes(job[:name]) }
        end

        def workflow_rules
          @workflow_rules ||= hash_config.dig(:workflow, :rules)
        end

        def root_variables
          @root_variables ||= transform_to_yaml_variables(variables)
        end

        def jobs
          @jobs ||= @ci_config.normalized_jobs
        end

        def stages
          @stages ||= @ci_config.stages
        end

        def included_templates
          @included_templates ||= @ci_config.included_templates
        end

        def build_attributes(name)
          job = jobs.fetch(name.to_sym, {})

          { stage_idx: stages.index(job[:stage]),
            stage: job[:stage],
            tag_list: job[:tags],
            name: job[:name].to_s,
            allow_failure: job[:ignore],
            when: job[:when] || 'on_success',
            environment: job[:environment_name],
            coverage_regex: job[:coverage],
            yaml_variables: transform_to_yaml_variables(job[:variables]), # https://gitlab.com/gitlab-org/gitlab/-/issues/300581
            job_variables: transform_to_yaml_variables(job[:job_variables]),
            root_variables_inheritance: job[:root_variables_inheritance],
            needs_attributes: job.dig(:needs, :job),
            interruptible: job[:interruptible],
            only: job[:only],
            except: job[:except],
            rules: job[:rules],
            cache: job[:cache],
            resource_group_key: job[:resource_group],
            scheduling_type: job[:scheduling_type],
            secrets: job[:secrets],
            options: {
              image: job[:image],
              services: job[:services],
              allow_failure_criteria: job[:allow_failure_criteria],
              artifacts: job[:artifacts],
              dependencies: job[:dependencies],
              cross_dependencies: job.dig(:needs, :cross_dependency),
              job_timeout: job[:timeout],
              before_script: job[:before_script],
              script: job[:script],
              after_script: job[:after_script],
              environment: job[:environment],
              retry: job[:retry],
              parallel: job[:parallel],
              instance: job[:instance],
              start_in: job[:start_in],
              trigger: job[:trigger],
              bridge_needs: job.dig(:needs, :bridge)&.first,
              release: release(job)
            }.compact }.compact
        end

        def merged_yaml
          @ci_config&.to_hash&.deep_stringify_keys&.to_yaml
        end

        def variables_with_data
          @ci_config.variables_with_data
        end

        def yaml_variables_for(job_name)
          job = jobs[job_name]

          return [] unless job

          Gitlab::Ci::Variables::Helpers.inherit_yaml_variables(
            from: root_variables,
            to: transform_to_yaml_variables(job[:job_variables]),
            inheritance: job.fetch(:root_variables_inheritance, true)
          )
        end

        def stage_for(job_name)
          jobs.dig(job_name, :stage)
        end

        private

        def variables
          @variables ||= @ci_config.variables
        end

        def hash_config
          @hash_config ||= @ci_config.to_hash
        end

        def release(job)
          job[:release]
        end

        def transform_to_yaml_variables(variables)
          ::Gitlab::Ci::Variables::Helpers.transform_to_yaml_variables(variables)
        end
      end
    end
  end
end