Define variables
TFS 2018
Note
Microsoft Visual Studio Team Foundation Server 2018 and earlier versions have the following differences in naming:
- Pipelines for build and release are called definitions
- Runs are called builds
- Service connections are called service endpoints
- Stages are called environments
- Jobs are called phases
Variables give you a convenient way to get key bits of data into various parts of the pipeline. The most common use of variables is to define a value that you can then use in your pipeline. All variables are strings and are mutable. The value of a variable can change from run to run or job to job of your pipeline.
When you define the same variable in multiple places with the same name, the most locally scoped variable wins. So, a variable defined at the job level can override a variable set at the stage level. A variable defined at the stage level overrides a variable set at the pipeline root level. A variable set in the pipeline root level overrides a variable set in the Pipeline settings UI.
You can use variables with expressions to conditionally assign values and further customize pipelines.
User-defined variables
When you define a variable, you can use different syntaxes (macro, template expression, or runtime) and what syntax you use determines where in the pipeline your variable renders.
In YAML pipelines, you can set variables at the root, stage, and job level. You can also specify variables outside of a YAML pipeline in the UI. When you set a variable in the UI, that variable can be encrypted and set as secret.
User-defined variables can be set as read-only. There are naming restrictions for variables (example: you can't use secret
at the start of a variable name).
You can use a variable group to make variables available across multiple pipelines.
Use templates to define variables in one file that are used in multiple pipelines.
User-defined multi-line variables
Azure DevOps supports multi-line variables but there are a few limitations.
Downstream components such as pipeline tasks might not handle the variable values correctly.
Azure DevOps won't alter user-defined variable values. Variable values need to be formatted correctly before being passed as multi-line variables. When formatting your variable, avoid special characters, don't use restricted names, and make sure you use a line ending format that works for the operating system of your agent.
Multi-line variables behave differently depending on the operating system. To avoid this, make sure that you format multi-line variables correctly for the target operating system.
Azure DevOps never alters variable values, even if you provide unsupported formatting.
System variables
In addition to user-defined variables, Azure Pipelines has system variables with predefined values. If you're using YAML or classic build pipelines, see predefined variables for a comprehensive list of system variables. If you're using classic release pipelines, see release variables.
System variables get set with their current value when you run the pipeline. Some variables are set automatically. As a pipeline author or end user, you change the value of a system variable before the pipeline runs.
System variables are read-only.
Environment variables
Environment variables are specific to the operating system you're using. They're injected into a pipeline in platform-specific ways. The format corresponds to how environment variables get formatted for your specific scripting platform.
On UNIX systems (macOS and Linux), environment variables have the format $NAME
. On Windows, the format is %NAME%
for batch and $env:NAME
in PowerShell.
System and user-defined variables also get injected as environment variables for your platform. When variables convert into environment variables, variable names become uppercase, and periods turn into underscores. For example, the variable name any.variable
becomes the variable name $ANY_VARIABLE
.
There are variable naming restrictions for environment variables (example: you can't use secret
at the start of a variable name).
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.
Understand variable syntax
Azure Pipelines supports three different ways to reference variables: macro, template expression, and runtime expression. You can use each syntax for a different purpose and each have some limitations.
In a pipeline, template expression variables (${{ variables.var }}
) get processed at compile time, before runtime starts. Macro syntax variables ($(var)
) get processed during runtime before a task runs. Runtime expressions ($[variables.var]
) also get processed during runtime but are intended to be used with conditions and expressions. When you use a runtime expression, it must take up the entire right side of a definition.
In this example, you can see that the template expression still has the initial value of the variable after the variable is updated. The value of the macro syntax variable updates. The template expression value doesn't change because all template expression variables get processed at compile time before tasks run. In contrast, macro syntax variables evaluate before each task runs.
variables:
- name: one
value: initialValue
steps:
- script: |
echo ${{ variables.one }} # outputs initialValue
echo $(one)
displayName: First variable pass
- bash: echo "##vso[task.setvariable variable=one]secondValue"
displayName: Set new variable value
- script: |
echo ${{ variables.one }} # outputs initialValue
echo $(one) # outputs secondValue
displayName: Second variable pass
Macro syntax variables
Most documentation examples use macro syntax ($(var)
). Macro syntax is designed to interpolate variable values into task inputs and into other variables.
Variables with macro syntax get processed before a task executes during runtime. Runtime happens after template expansion. When the system encounters a macro expression, it replaces the expression with the contents of the variable. If there's no variable by that name, then the macro expression does not change. For example, if $(var)
can't be replaced, $(var)
won't be replaced by anything.
Macro syntax variables remain unchanged with no value because an empty value like $()
might mean something to the task you're running and the agent shouldn't assume you want that value replaced. For example, if you use $(foo)
to reference variable foo
in a Bash task, replacing all $()
expressions in the input to the task could break your Bash scripts.
Macro variables are only expanded when they're used for a value, not as a keyword. Values appear on the right side of a pipeline definition. The following is valid: key: $(value)
. The following isn't valid: $(key): value
. Macro variables aren't expanded when used to display a job name inline. Instead, you must use the displayName
property.
Note
Macro syntax variables are only expanded for stages
, jobs
, and steps
.
You cannot, for example, use macro syntax inside a resource
or trigger
.
This example uses macro syntax with Bash, PowerShell, and a script task. The syntax for calling a variable with macro syntax is the same for all three.
variables:
- name: projectName
value: contoso
steps:
- bash: echo $(projectName)
- powershell: echo $(projectName)
- script: echo $(projectName)
Template expression syntax
You can use template expression syntax to expand both template parameters and variables (${{ variables.var }}
). Template variables process at compile time, and get replaced before runtime starts. Template expressions are designed for reusing parts of YAML as templates.
Template variables silently coalesce to empty strings when a replacement value isn't found. Template expressions, unlike macro and runtime expressions, can appear as either keys (left side) or values (right side). The following is valid: ${{ variables.key }} : ${{ variables.value }}
.
Runtime expression syntax
You can use runtime expression syntax for variables that are expanded at runtime ($[variables.var]
). Runtime expression variables silently coalesce to empty strings when a replacement value isn't found. Use runtime expressions in job conditions, to support conditional execution of jobs, or whole stages.
Runtime expression variables are only expanded when they're used for a value, not as a keyword. Values appear on the right side of a pipeline definition. The following is valid: key: $[variables.value]
. The following isn't valid: $[variables.key]: value
. The runtime expression must take up the entire right side of a key-value pair. For example, key: $[variables.value]
is valid but key: $[variables.value] foo
isn't.
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 |
What syntax should I use?
Use macro syntax if you're providing input for a task.
Choose a runtime expression if you're working with conditions and expressions. However, don't use a runtime expression if you don't want your empty variable to print (example: $[variables.var]
). For example, if you have conditional logic that relies on a variable having a specific value or no value. In that case, you should use a macro expression.
If you're defining a variable in a template, use a template expression.
Set variables in pipeline
YAML isn't supported in TFS.
Set secret variables
YAML isn't supported in TFS.
Share variables across pipelines
To share variables across multiple pipelines in your project, use the web interface. Under Library, use variable groups.
Use output variables from tasks
Some tasks define output variables, which you can consume in downstream steps within the same job.
- To reference a variable from a different task within the same job, use
TASK.VARIABLE
. - To reference a variable from a task from a different job, use
dependencies.JOB.outputs['TASK.VARIABLE']
.
Note
By default, each stage in a pipeline depends on the one just before it in the YAML file. If you need to refer to a stage that isn't immediately prior to the current one, you can override this automatic default by adding a dependsOn
section to the stage.
Note
The following examples use standard pipeline syntax. If you're using deployment pipelines, both variable and conditional variable syntax will differ. For information about the specific syntax to use, see Deployment jobs.
For these examples, assume we have a task called MyTask
, which sets an output variable called MyVar
.
Learn more about the syntax in Expressions - Dependencies.
Use outputs in the same job
steps:
- task: MyTask@1 # this step generates the output variable
name: ProduceVar # because we're going to depend on it, we need to name the step
- script: echo $(ProduceVar.MyVar) # this step uses the output variable
Use outputs in a different job
jobs:
- job: A
steps:
# assume that MyTask generates an output variable called "MyVar"
# (you would learn that from the task's documentation)
- task: MyTask@1
name: ProduceVar # because we're going to depend on it, we need to name the step
- job: B
dependsOn: A
variables:
# map the output variable from A into this job
varFromA: $[ dependencies.A.outputs['ProduceVar.MyVar'] ]
steps:
- script: echo $(varFromA) # this step uses the mapped-in variable
Set variables in scripts
Scripts can define variables that are later consumed in subsequent steps in the pipeline. All variables set by this method are treated as strings. To set a variable from a script, you use a command syntax and print to stdout.
YAML isn't supported in TFS.
Set variables by using expressions
YAML is not supported in TFS.
Allow at queue time
YAML is not supported in TFS.
Expansion of variables
YAML is not supported in TFS.