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