Welcome to mirror list, hosted at ThFree Co, Russian Federation.

builder.rb « variables « ci « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9ef6e7f5fa9b5c0d945a5e4420ab376dc2fa987a (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
151
152
153
154
# frozen_string_literal: true

module Gitlab
  module Ci
    module Variables
      class Builder
        include ::Gitlab::Utils::StrongMemoize

        def initialize(pipeline)
          @pipeline = pipeline
          @instance_variables_builder = Builder::Instance.new
          @project_variables_builder = Builder::Project.new(project)
        end

        def scoped_variables(job, environment:, dependencies:)
          Gitlab::Ci::Variables::Collection.new.tap do |variables|
            variables.concat(predefined_variables(job))
            variables.concat(project.predefined_variables)
            variables.concat(pipeline.predefined_variables)
            variables.concat(job.runner.predefined_variables) if job.runnable? && job.runner
            variables.concat(kubernetes_variables(job))
            variables.concat(deployment_variables(environment: environment, job: job))
            variables.concat(job.yaml_variables)
            variables.concat(user_variables(job.user))
            variables.concat(job.dependency_variables) if dependencies
            variables.concat(secret_instance_variables)
            variables.concat(secret_group_variables(environment: environment, ref: job.git_ref))
            variables.concat(secret_project_variables(environment: environment, ref: job.git_ref))
            variables.concat(job.trigger_request.user_variables) if job.trigger_request
            variables.concat(pipeline.variables)
            variables.concat(pipeline.pipeline_schedule.job_variables) if pipeline.pipeline_schedule
          end
        end

        def kubernetes_variables(job)
          ::Gitlab::Ci::Variables::Collection.new.tap do |collection|
            # Should get merged with the cluster kubeconfig in deployment_variables, see
            # https://gitlab.com/gitlab-org/gitlab/-/issues/335089
            template = ::Ci::GenerateKubeconfigService.new(job).execute

            if template.valid?
              collection.append(key: 'KUBECONFIG', value: template.to_yaml, public: false, file: true)
            end
          end
        end

        def deployment_variables(environment:, job:)
          return [] unless environment

          project.deployment_variables(
            environment: environment,
            kubernetes_namespace: job.expanded_kubernetes_namespace
          )
        end

        def user_variables(user)
          Gitlab::Ci::Variables::Collection.new.tap do |variables|
            break variables if user.blank?

            variables.append(key: 'GITLAB_USER_ID', value: user.id.to_s)
            variables.append(key: 'GITLAB_USER_EMAIL', value: user.email)
            variables.append(key: 'GITLAB_USER_LOGIN', value: user.username)
            variables.append(key: 'GITLAB_USER_NAME', value: user.name)
          end
        end

        def secret_instance_variables
          strong_memoize(:secret_instance_variables) do
            instance_variables_builder
              .secret_variables(protected_ref: protected_ref?)
          end
        end

        def secret_group_variables(environment:, ref:)
          return [] unless project.group

          project.group.ci_variables_for(ref, project, environment: environment)
        end

        def secret_project_variables(environment:, ref:)
          if memoize_secret_variables?
            memoized_secret_project_variables(environment: environment)
          else
            project.ci_variables_for(ref: ref, environment: environment)
          end
        end

        private

        attr_reader :pipeline
        attr_reader :instance_variables_builder
        attr_reader :project_variables_builder
        delegate :project, to: :pipeline

        def predefined_variables(job)
          Gitlab::Ci::Variables::Collection.new.tap do |variables|
            variables.append(key: 'CI_JOB_NAME', value: job.name)
            variables.append(key: 'CI_JOB_STAGE', value: job.stage)
            variables.append(key: 'CI_JOB_MANUAL', value: 'true') if job.action?
            variables.append(key: 'CI_PIPELINE_TRIGGERED', value: 'true') if job.trigger_request

            variables.append(key: 'CI_NODE_INDEX', value: job.options[:instance].to_s) if job.options&.include?(:instance)
            variables.append(key: 'CI_NODE_TOTAL', value: ci_node_total_value(job).to_s)

            # legacy variables
            variables.append(key: 'CI_BUILD_NAME', value: job.name)
            variables.append(key: 'CI_BUILD_STAGE', value: job.stage)
            variables.append(key: 'CI_BUILD_TRIGGERED', value: 'true') if job.trigger_request
            variables.append(key: 'CI_BUILD_MANUAL', value: 'true') if job.action?
          end
        end

        def memoized_secret_project_variables(environment:)
          strong_memoize_with(:secret_project_variables, environment) do
            project_variables_builder
              .secret_variables(
                environment: environment,
                protected_ref: protected_ref?)
          end
        end

        def ci_node_total_value(job)
          parallel = job.options&.dig(:parallel)
          parallel = parallel.dig(:total) if parallel.is_a?(Hash)
          parallel || 1
        end

        def protected_ref?
          strong_memoize(:protected_ref) do
            project.protected_for?(pipeline.jobs_git_ref)
          end
        end

        def memoize_secret_variables?
          strong_memoize(:memoize_secret_variables) do
            ::Feature.enabled?(:ci_variables_builder_memoize_secret_variables,
              project,
              default_enabled: :yaml)
          end
        end

        def strong_memoize_with(name, *args)
          container = strong_memoize(name) { {} }

          if container.key?(args)
            container[args]
          else
            container[args] = yield
          end
        end
      end
    end
  end
end