We have pipelines that are mostly started manually, and the user can set a various options:
The above parameters are defined in the top level YAML, like this:
parameters:
- name: reasonForManualBuild
displayName: Reason for manual run
type: string
default: ''
- name: cleanAgents
displayName: Wipe agents before build
type: boolean
default: false
values:
- false
- true
- name: buildSoftware
displayName: Build software
type: boolean
default: true
values:
- false
- true
- name: runAnalysis
displayName: Run static code analysis
type: boolean
default: true
values:
- false
- true
This works very well, but, at the moment, I'm passing most of the parameters to templates that call templates with the same parameters etc. Not very nice.
It would be great if I could define global variables from these parameters, like this:
variables:
- name: cleanAgents
value: ${{ parameters.cleanAgents }}
- name: buildSoftware
value: ${{ parameters.buildSoftware }}
and then use them within the templates, as $(cleanagents)
, $(buildSoftware)
, etc.
As far as I understand the documentation, this should work, but it doesn't, when I run the pipeline, they appear empty.
As an alternative I tried passing parameter objects, which doesn't seem to work either.
Am I making a mistake, or is there a correct way to do it, or is it just not possible?
The main product pipeline, where I'm just calling the product "Foo":
parameters:
- name: reasonForManualBuild
displayName: Reason for manual run
type: string
default: ''
- name: cleanAgents
displayName: Wipe agents before build
type: boolean
default: false
values:
- false
- true
- name: buildSoftware
displayName: Build software
type: boolean
default: true
values:
- false
- true
- name: runAnalysis
displayName: Run static code analysis
type: boolean
default: true
values:
- false
- true
- name: runUnitTests
displayName: Run unit tests
type: boolean
default: true
values:
- false
- true
- name: runFunctionalTests
displayName: Run functional tests
type: boolean
default: false
values:
- false
- true
- name: continueOnError
displayName: Continue on error
type: boolean
default: false
values:
- false
- true
- name: productVersion
displayName: Product version number
type: string
default: 5.0.0.1
name: QEC-${{ parameters.productVersion }}-$(Date:yyMMdd)$(Rev:rr)
variables:
- name: productName
value: FOO
- name: productVersion
value: ${{ parameters.productVersion }}
- name: cleanAgents
value: ${{ parameters.cleanAgents }}
- name: buildSoftware
value: ${{ parameters.buildSoftware }}
- name: runAnalysis
value: ${{ parameters.runAnalysis }}
- name: runUnitTests
value: ${{ parameters.runUnitTests }}
- name: runFunctionalTests
value: ${{ parameters.runFunctionalTests }}
- name: continueOnError
value: ${{ parameters.continueOnError }}
resources:
repositories:
# skipping resources block as not relevant here
extends:
template: /BaseTest-pipeline.yml
The BaseTest-pipeline.yml:
stages:
- stage: stage_Test
displayName: "Build $(productName), no analysis"
jobs:
- job: jobShow
displayName: 'Job with $(productName)'
steps:
- script: |
echo "productName = $(productName)"
echo "productVersion = $(productVersion)"
echo "cleanAgents = $(cleanAgents)"
shows, as displayname: Job with $(productName)
But then correctly shows three variables, including productName, correctly:
"productName = FOO"
"productVersion = 5.0.0.1"
"cleanAgents = False"
EDIT:
I attempted on my side, and it can work fine to use the parameters to set global variables. See below example as reference.
The YAML files.
The file azure-pipelines.yml
# azure-pipelines.yml
parameters:
- name: param01
type: boolean
default: true
- name: param02
type: boolean
default: false
variables:
- name: varParam01
value: ${{ parameters.param01 }}
- name: varParam02
value: ${{ parameters.param02 }}
steps:
- script: |
echo "This steps is from the main YAML azure-pipelines.yml"
echo "param01 = ${{ parameters.param01 }}"
echo "param01 = ${{ parameters.param02 }}"
echo "varParam01 = $(varParam01)"
echo "varParam02 = $(varParam02)"
- template: /templates/temp-steps01.yml
The template YAML /templates/temp-steps01.yml
# /templates/temp-steps01.yml
steps:
- script: |
echo "This steps is from template YAML temp-steps01.yml"
echo "varParam01 = $(varParam01)"
echo "varParam02 = $(varParam02)"
- template: /templates/temp-steps02.yml
The nested template YAML /templates/temp-steps02.yml
# /templates/temp-steps02.yml
steps:
- script: |
echo "This steps is from the nested template YAML temp-steps02.yml"
echo "varParam01 = $(varParam01)"
echo "varParam02 = $(varParam02)"
The result.
EDIT_2:
For boolean type parameter, the available values are only true
and false
. So, you do not need to use the 'values
' key to provide a list of all the available values. But you must provide the default value (true
or false
) using the 'default
' key. Just like as the sample I shared above.
For the string type parameter, you are correct, you can provide an empty value to the 'default
' key.
When users manually trigger the pipeline, for the boolean type parameter, the users can manually check or uncheck the option on the UI to change the value to be true
(check) or false
(uncheck). For the string type parameter, the users can manually enter the the value in the field on the UI.
After users manually set/enter the parameter values and click "Run
" on the UI to trigger a new run, the pipeline gets compiled with the parameter values set/entered by users.
See below example.
azure-pipelines.yml
. Updated based on above sample.# azure-pipelines.yml
parameters:
- name: param01
type: boolean
default: true
- name: param02
type: boolean
default: false
- name: param03
type: string
default: ''
variables:
- name: varParam01
value: ${{ parameters.param01 }}
- name: varParam02
value: ${{ parameters.param02 }}
- name: varParam03
value: ${{ parameters.param03 }}
steps:
. . .
EDIT_3:
The azure-pipelines.yml
parameters:
- name: param01
type: boolean
default: true
- name: param02
type: boolean
default: false
- name: param03
type: string
default: ''
variables:
- name: varParam01
value: ${{ parameters.param01 }}
- name: varParam02
value: ${{ parameters.param02 }}
- name: varParam03
value: ${{ parameters.param03 }}
extends:
template: /templates/temp-steps01.yml
The /templates/temp-steps01.yml
extends:
template: /templates/temp-steps02.yml
The /templates/temp-steps02.yml
steps:
- script: |
echo "This steps is from the nested template YAML temp-steps02.yml"
echo "varParam01 = $(varParam01)"
echo "varParam02 = $(varParam02)"
echo "varParam03 = $(varParam03)"
Result.
EDIT_4:
# azure-pipelines.yml
variables:
myVar01: '123'
stages:
- stage: A
variables:
myVar02: '456'
jobs:
- job: A1
variables:
myVar03: '789'
steps:
. . .
- job: A2
variables:
steps:
. . .
- stage: B
. . .
The variable myVar01
is a global variable that can be available for all the stages and jobs in this pipeline.
The variable myVar02
is a stage-level variable defined in stage A
. It can be available only within stage A
, and not available for stage B
.
The variable myVar03
is a job-level variable defined in job A1
. It can be available only within job A1
, and not available for job A2
and stage B
.
EDIT_5:
The '$(varName)
' is a runtime expression that is evaluated at runtime before tasks start running. So, it generally is used as the input of tasks.
The stage name and job name are evaluated at compile-time before runtime. So, when using the expression '$(varName)
' on stage name and job name, it will return the expression itself.
You need to use the template expression "${{ variables.varName }}
" to pass pipeline variables to the stage name and job name, because this expression is evaluated at compile-time.
However, when using template expression to pass pipeline variables in template YAML, only some of the predefined variables are available, the user-defined variables are not available. All the variables you defined under the 'variables
' key are user-defined variables.