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.