There exists several types of variables that can be added to YAML scripts. I really like the Microsoft page that lays out a table that specifies the type of variable and when its value is computed and set. I have reproduced it below. The Azure documentation is listed in the Links section.
Syntax | Example | When is it processed? | Where does it expand in a pipeline definition? | How does it render when not found? |
---|---|---|---|---|
macro | $(var) | runtime before a task executes | value (right side) | prints $(var) |
template expression | ${{variables.var}} | compile time | key or value (left or right side) | empty string |
runtime expression | $[variables.var] | runtime | value (right side) | empty string |
Variable Naming Restrictions
User-defined and environment variables can consist of letters, numbers, ., and _ characters. Don’t use variable prefixes reserved by the system. These are: endpoint
, input
, secret
, path
, and securefile
. Any variable that begins with one of these strings (regardless of capitalization) won’t be available to your tasks and scripts.
PowerShell: Accessing Variables and the Environment
The variables that are defined in the YAML are also available from the environment. In the example below, we define variable cg_RootFolder
in the variables section so it will be available to all jobs in the pipeline.
Note that variable substitution that occurs with “${}” is using PowerShell complex variable escaping that allows a variable value that may include spaces or special characters (items 12-13).
variables: # Top level repo folder location on build agent. Looks like "D:\A\1\S\{repo}" cg_RootFolder: $(Build.SourcesDirectory)\$(Build.Repository.Name) jobs: - job: workspace: clean: all pool: vmImage: 'windows-2019' # Generic VM without any Select Product/SDK version installed. steps: # Perform PowerShell commands. - task: PowerShell@2 displayName: PowerShell examples inputs: targetType: inline script: | Write-Host "Examples of Azure variables being inserted before PowerShell task executes..." Write-Host "(1) cg_RootFolder:" $(cg_RootFolder) Write-Host "(2) cg_RootFolder: $(cg_RootFolder)" Write-Host '(3) cg_RootFolder: $(cg_RootFolder)' Write-Host "(4) cg_RootFolder:" $env:cg_RootFolder Write-Host "(5) cg_RootFolder: $env:cg_RootFolder" Write-Host '(6) cg_RootFolder: $env:cg_RootFolder' Write-Host "(7) AZURE_EXTENSION_DIR:" $env:AZURE_EXTENSION_DIR Write-Host "`nExamples of Azure variable loaded into PowerShell variable..." $a = $env:AZURE_EXTENSION_DIR Write-Host "(10) a: $a" Write-Host "(11) a:" $a $b = ${env:AZURE_EXTENSION_DIR} Write-Host "(12) b: $b" Write-Host "(13) b:" $b
Results in the following Azure pipeline output. In lines 1 through 3, the pipeline inserts the value of cg_RootFolder
into the script immediately BEFORE the script runs. In the remaining lines, PowerShell loads the value from the environment at runtime.
Notice that the variable was not expanded in line 6 because it was enclosed in single quotes.
Examples of Azure variables being inserted before PowerShell task executes... (1) cg_RootFolder: D:\a\1\s\SoftPro-Select-DefaultDocFolder (2) cg_RootFolder: D:\a\1\s\SoftPro-Select-DefaultDocFolder (3) cg_RootFolder: D:\a\1\s\SoftPro-Select-DefaultDocFolder (4) cg_RootFolder: D:\a\1\s\SoftPro-Select-DefaultDocFolder (5) cg_RootFolder: D:\a\1\s\SoftPro-Select-DefaultDocFolder (6) cg_RootFolder: $env:cg_RootFolder (7) AZURE_EXTENSION_DIR: C:\Program Files\Common Files\AzureCliExtensionDirectory Examples of Azure variable loaded into PowerShell variable... ( 8) a: C:\Program Files\Common Files\AzureCliExtensionDirectory ( 9) a: C:\Program Files\Common Files\AzureCliExtensionDirectory (10) b: C:\Program Files\Common Files\AzureCliExtensionDirectory (11) b: C:\Program Files\Common Files\AzureCliExtensionDirectory
PowerShell: Changing Variable Values
We often need to create or change a variable value. The example below builds on the prior code to change the variable value with task.setvariable
.
variables: # Top level repo folder location on build agent. Looks like "D:\A\1\S\{repo}" cg_RootFolder: $(Build.SourcesDirectory)\$(Build.Repository.Name) <snip> # Write current value of variable then change it to "This is a new value." - powershell: | Write-Host "(1) Before: $env:cg_RootFolder" Write-Host "(2) Before: $(cg_RootFolder)" Write-Host "##vso[task.setvariable variable=cg_RootFolder]This is a new value." Write-Host "(3) Inside same task: $env:cg_RootFolder" Write-Host "(4) Inside same task: $(cg_RootFolder)" # Write new value of variable and get original value, too. - powershell: | Write-Host "(5) Inside different task: $env:cg_RootFolder" Write-Host "(6) Inside different task: $(cg_RootFolder)" Write-Host "(7) Pipeline compile time value: ${{variables.cg_RootFolder}}"
The results in the following Azure pipeline output. In lines 3-4, notice that the new value is not available – it will be available until the next task starts (since values are loaded immediately before the task executes). Once the next task loads (lines 5-7) the variable will be updated.
There is a trick you can use to get the original unmodified value – use the ${{variables.varname}}
format. This works because the pipeline sets this value at compile time before any code runs.
(1) Before: D:\a\1\s\SoftPro-Select-DefaultDocFolder (2) Before: D:\a\1\s\SoftPro-Select-DefaultDocFolder (3) Inside same task: D:\a\1\s\SoftPro-Select-DefaultDocFolder (4) Inside same task: D:\a\1\s\SoftPro-Select-DefaultDocFolder (5) Inside different task: This is a new value. (6) Inside different task: This is a new value. (7) Pipeline compile time value: D:\a\1\s\SoftPro-Select-DefaultDocFolder
Links
There are many rules and capabilities with variables in addition to those presented. Click here for further information.