Set variables in scripts

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

When you use PowerShell and Bash scripts in your pipelines, it's often useful to be able to set variables that you can then use in future tasks. Newly set variables aren't available in the same task.

Scripts are great for when you want to do something that isn't supported by a task like calling a custom REST API and parsing the response.

You'll use the task.setvariable logging command to set variables in PowerShell and Bash scripts.

Note

Deployment jobs use a different syntax for output variables. To learn more about support for output variables in deployment jobs, see Deployment jobs.

To use a variable with a condition in a pipeline, see Specify conditions.

About task.setvariable

When you add a variable with task.setvariable, the following tasks can use the variable using macro syntax $(myVar). The variable will only be available to tasks in the same job by default. If you add the parameter isoutput, the syntax to call your variable changes. See Set an output variable for use in the same job.

Set the variable myVar with the value foo.

- bash: |
    echo "##vso[task.setvariable variable=myVar;]foo"

Read the variable myVar:

- bash: |
    echo "You can use macro syntax for variables: $(myVar)"

Set variable properties

The task.setvariable command includes properties for setting a variable as secret, as an output variable, and as read only. The available properties include:

  • variable = variable name (Required)
  • issecret = boolean (Optional, defaults to false)
  • isoutput = boolean (Optional, defaults to false)
  • isreadonly = boolean (Optional, defaults to false)

To use the variable in the next stage, set the isoutput property to true. To reference a variable with the isoutput set to true, you'll include the task name. For example, $(TaskName.myVar).

When you set a variable as read only, it can't be overwritten by downstream tasks. Set isreadonly to true. Setting a variable as read only enhances security by making that variable immutable.

Set a variable as secret

When issecret is set to true, the value of the variable will be saved as secret and masked out from logs.

Note

Azure Pipelines makes an effort to mask secrets when emitting data to pipeline logs, so you may see additional variables and data masked in output and logs that are not set as secrets.

Set the secret variable mySecretVal.

- bash: |
    echo "##vso[task.setvariable variable=mySecretVal;issecret=true]secretvalue"

Get the secret variable mySecretVal.

- bash: |
    echo "##vso[task.setvariable variable=mySecretVal;issecret=true]secretvalue"
- bash: |
    echo $(mySecretVal)

Secret variable output in bash.

Screenshot of bash variable output.

Levels of output variables

There are four different types of output variables with distinct syntaxes:

Set an output variable for use in the same job

When you use an output variable in the same job, you don't have to use the isoutput property. By default, the variable will be available to downstream steps within the same job. However, if you do add the isoutput property, you'll need to reference the variable with the task name.

The script here sets the same-job output variable myJobVar without specifying isoutput and sets myOutputJobVar with isoutput=true.

jobs:
- job: A
  steps:
  - bash: |
     echo "##vso[task.setvariable variable=myJobVar]this is the same job"
  - bash: |
     echo "##vso[task.setvariable variable=myOutputJobVar;isoutput=true]this is the same job too"
    name: setOutput

This script gets the same-job variables myJobVar and myOutputJobVar. Notice that the syntax changes for referencing an output variable once isoutput=true is added.

jobs:
- job: A
  steps:
  - bash: |
     echo "##vso[task.setvariable variable=myJobVar]this is the same job"
  - bash: |
     echo "##vso[task.setvariable variable=myOutputJobVar;isoutput=true]this is the same job too"
    name: setOutput
  - bash: |
     echo $(myJobVar) 
  - bash: |
     echo $(setOutput.myOutputJobVar)

Set an output variable for use in future jobs

When you use output variables across jobs, you'll reference them with dependencies. The syntax for accessing an output variable in a future job or stage varies based on the relationship between the setter and consumer of the variable. Learn about each case in dependencies.

First, set the output variable myOutputVar.

jobs:
- job: A
  steps:
  - bash: |
     echo "##vso[task.setvariable variable=myOutputVar;isoutput=true]this is from job A"
    name: passOutput

Next, access myOutputVar in a future job and output the variable as myVarFromJobA. To use dependencies, you need to set the dependsOn property on the future job using the name of the past job in which the output variable was set.

jobs:
- job: A
  steps:
  - bash: |
     echo "##vso[task.setvariable variable=myOutputVar;isoutput=true]this is from job A"
    name: passOutput
- job: B
  dependsOn: A
  variables:
    myVarFromJobA: $[ dependencies.A.outputs['passOutput.myOutputVar'] ]  
  steps:
  - bash: |
     echo $(myVarFromJobA)

Set an output variable for use in future stages

Output variables can be used across stages in pipelines. You can use output variables to pass useful information, such as the ID of a generated output, from one stage to the next.

When you set a variable with the isoutput property, you can reference that variable in later stages with the task name and the stageDependencies syntax. Learn more about dependencies.

Output variables are only available in the next downstream stage. If multiple stages consume the same output variable, use the dependsOn condition.

First, set the output variable myStageVal.

steps:
  - bash: echo "##vso[task.setvariable variable=myStageVal;isOutput=true]this is a stage output variable"
    name: MyOutputVar

Then, in a future stage, map the output variable myStageVal to a stage, job, or task-scoped variable as, for example, myStageAVar. Note the mapping syntax uses a runtime expression $[] and traces the path from stageDependencies to the output variable using both the stage name (A) and the job name (A1) to fully qualify the variable.

stages:
- stage: A
  jobs:
  - job: A1
    steps:
     - bash: echo "##vso[task.setvariable variable=myStageVal;isOutput=true]this is a stage output variable"
       name: MyOutputVar
- stage: B
  dependsOn: A
  jobs:
  - job: B1
    variables:
      myStageAVar: $[stageDependencies.A.A1.outputs['MyOutputVar.myStageVal']]
    steps:
      - bash: echo $(myStageAVar)

In case your value contains newlines, you can escape them and the agent will automatically unescape it:

steps:
- bash: |
    escape_data() {
      local data=$1
      data="${data//'%'/'%AZP25'}"
      data="${data//$'\n'/'%0A'}"
      data="${data//$'\r'/'%0D'}"
      echo "$data"
    }
    echo "##vso[task.setvariable variable=myStageVal;isOutput=true]$(escape_data $'foo\nbar')"
  name: MyOutputVar

FAQ

My output variable isn't rendering. What is going wrong?

There are a few reasons why your output variable may not appear.

  • Output variables set with isoutput aren't available in the same job and instead are only available in downstream jobs.
  • Depending on what variable syntax you use, a variable that sets an output variable's value may not be available at runtime. For example, variables with macro syntax ($(var)) get processed before a task runs. In contrast, variables with template syntax are processed at runtime ($[variables.var]). You'll usually want to use runtime syntax when setting output variables. For more information on variable syntax, see Define variables.
  • There may be extra spaces within your expression. If your variable isn't rendering, check for extra spaces surrounding isOutput=true.

You can troubleshoot the dependencies output for a pipeline job or stage by adding a variable for the dependencies and then printing that variable. For example, in this pipeline job A sets the output variable MyTask. The second job (B) depends on job A. A new variable, deps holds the JSON representation of the job dependencies. The second step in Job B uses PowerShell to print out deps so that you can see the job dependencies.

trigger:
- '*'

pool:
  vmImage: 'ubuntu-latest'
 
jobs:
- job: A
  steps:
    - script: |
        echo "##vso[task.setvariable variable=MyTask;isOutput=true]theoutputval"
      name: ProduceVar  
- job: B
  dependsOn: A
  variables:
    varFromA: $[ dependencies.A.outputs['ProduceVar.MyTask'] ]
    deps: $[convertToJson(dependencies)] # create a variable with the job dependencies
  steps:
  - script: echo $(varFromA) # 
  - powershell: Write-Host "$(deps)"