diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md index 25ce42598830da64bc05f703f7a5bb2c147ab410..beb35645492406694e2224abf6302ea717d88aab 100644 --- a/doc/ci/variables/where_variables_can_be_used.md +++ b/doc/ci/variables/where_variables_can_be_used.md @@ -43,6 +43,7 @@ There are two places defined variables can be used. On the: | [`tags`](../yaml/index.md#tags) | yes | GitLab | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35742) in GitLab 14.1. | | [`trigger` and `trigger:project`](../yaml/index.md#trigger) | yes | GitLab | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab. Variable expansion for `trigger:project` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/367660) in GitLab 15.3. | | [`variables`](../yaml/index.md#variables) | yes | GitLab/Runner | The variable expansion is first made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab, and then any unrecognized or unavailable variables are expanded by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism). | +| [`workflow:name`](../yaml/index.md#workflowname) | yes | GitLab | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab.

Supported are all variables available in `workflow`:
- Project/Group variables.
- Global `variables` and `workflow:rules:variables` (when matching the rule).
- Variables inherited from parent pipelines.
- Variables from triggers.
- Variables from pipeline schedules.

Not supported are variables defined in the GitLab Runner `config.toml`, variables defined in jobs, or [Persisted variables](#persisted-variables). | ### `config.toml` file diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md index 3882bc67199851a3fa361bd00db53d0718e88ecc..cdb6dc88446835eaf8d142c82fcf95f3671fdc79 100644 --- a/doc/ci/yaml/index.md +++ b/doc/ci/yaml/index.md @@ -414,12 +414,33 @@ All pipelines are assigned the defined name. Any leading or trailing spaces in t **Possible inputs**: - A string. +- [CI/CD variables](../variables/where_variables_can_be_used.md#gitlab-ciyml-file). +- A combination of both. + +**Examples of `workflow:name`**: + +A simple pipeline name with a predefined variable: + +```yaml +workflow: + name: 'Pipeline for branch: $CI_COMMIT_BRANCH' +``` -**Example of `workflow:name`**: +A configuration with different pipeline names depending on the pipeline conditions: ```yaml +variables: + PIPELINE_NAME: 'Default pipeline name' + workflow: - name: 'Pipeline name' + name: '$PIPELINE_NAME' + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + variables: + PIPELINE_NAME: 'MR pipeline: $CI_COMMIT_BRANCH' + - if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-in-ruby3/' + variables: + PIPELINE_NAME: 'Ruby 3 pipeline' ``` #### `workflow:rules` diff --git a/lib/gitlab/ci/pipeline/chain/populate.rb b/lib/gitlab/ci/pipeline/chain/populate.rb index d1f57ca68e794788561931fa6652bc65c67d840b..3f8745b4ab11b52250561c5a0cc1dc0b64e3c9db 100644 --- a/lib/gitlab/ci/pipeline/chain/populate.rb +++ b/lib/gitlab/ci/pipeline/chain/populate.rb @@ -41,10 +41,16 @@ def set_pipeline_name @command.yaml_processor_result.workflow_name.blank? name = @command.yaml_processor_result.workflow_name + name = ExpandVariables.expand(name, -> { global_context.variables.sort_and_expand_all }) pipeline.build_pipeline_metadata(project: pipeline.project, name: name) end + def global_context + Gitlab::Ci::Build::Context::Global.new( + pipeline, yaml_variables: @command.pipeline_seed.root_variables) + end + def stage_names # We filter out `.pre/.post` stages, as they alone are not considered # a complete pipeline: diff --git a/lib/gitlab/ci/pipeline/seed/pipeline.rb b/lib/gitlab/ci/pipeline/seed/pipeline.rb index e1a15fb8d5bc1aa906dbc2f320acc24c3596abae..9e609debeed54a6c14e36ab457d118952ab47b8e 100644 --- a/lib/gitlab/ci/pipeline/seed/pipeline.rb +++ b/lib/gitlab/ci/pipeline/seed/pipeline.rb @@ -32,6 +32,10 @@ def deployments_count end end + def root_variables + @context.root_variables + end + private def stage_seeds diff --git a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb index 4161e92dfe25b84d3e953eadd4a27aa433a34778..67b2498488f59401f9a466eda0957f678f86026b 100644 --- a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb @@ -277,6 +277,25 @@ def run_chain expect(pipeline.pipeline_metadata).to be_nil end end + + context 'with variables' do + let(:config) do + { + variables: { ROOT_VAR: 'value $WORKFLOW_VAR1' }, + workflow: { + name: 'Pipeline $ROOT_VAR $WORKFLOW_VAR2 $UNKNOWN_VAR', + rules: [{ variables: { WORKFLOW_VAR1: 'value1', WORKFLOW_VAR2: 'value2' } }] + }, + rspec: { script: 'rspec' } + } + end + + it 'substitutes variables' do + run_chain + + expect(pipeline.pipeline_metadata.name).to eq('Pipeline value value1 value2 ') + end + end end end end diff --git a/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb index a76b4874ecad6495dc702f4b88b097ba85d4e445..55980ae72a06381a62a49a0d03af44d14fb4551d 100644 --- a/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/seed/pipeline_spec.rb @@ -6,7 +6,9 @@ let_it_be(:project) { create(:project, :repository) } let_it_be(:pipeline) { create(:ci_pipeline, project: project) } - let(:seed_context) { Gitlab::Ci::Pipeline::Seed::Context.new(pipeline, root_variables: []) } + let(:root_variables) { [] } + + let(:seed_context) { Gitlab::Ci::Pipeline::Seed::Context.new(pipeline, root_variables: root_variables) } let(:stages_attributes) do [ @@ -75,4 +77,12 @@ expect(seed.deployments_count).to eq(2) end end + + describe '#root_variables' do + let(:root_variables) { %w[var1 value1] } + + it 'returns root_variables' do + expect(seed.root_variables).to eq(root_variables) + end + end end diff --git a/spec/services/ci/create_pipeline_service/rules_spec.rb b/spec/services/ci/create_pipeline_service/rules_spec.rb index c737b8cc32901ce6efcdda6bc14359a9cad854fd..5fdefb2b306af06cec5bd8cd5f3d64eff00dcdd8 100644 --- a/spec/services/ci/create_pipeline_service/rules_spec.rb +++ b/spec/services/ci/create_pipeline_service/rules_spec.rb @@ -1425,5 +1425,43 @@ def find_job(name) it_behaves_like 'comparing file changes with workflow rules' end end + + context 'workflow name with rules' do + let(:ref) { 'refs/heads/feature' } + + let(:variables) do + [{ key: 'SOME_VARIABLE', secret_value: 'SOME_VAL' }] + end + + let(:pipeline) do + execute_service do |pipeline| + pipeline.variables.build(variables) + end.payload + end + + let(:config) do + <<-EOY + workflow: + name: '$PIPELINE_NAME $SOME_VARIABLE' + rules: + - if: $CI_COMMIT_REF_NAME =~ /master/ + variables: + PIPELINE_NAME: 'Name 1' + - if: $CI_COMMIT_REF_NAME =~ /feature/ + variables: + PIPELINE_NAME: 'Name 2' + + job: + stage: test + script: echo 'hello' + EOY + end + + it 'substitutes variables in pipeline name' do + expect(response).not_to be_error + expect(pipeline).to be_persisted + expect(pipeline.name).to eq('Name 2 SOME_VAL') + end + end end end