Azure Pipelines, the continuous integration and continuous deployment feature of Azure DevOps, has the concept of variables. For scripts and tasks, they behave just like environment variables. There’s a bunch that are predefined that you might have used before, like
In YAML pipelines, you can define your own variables in:
variableblock in YAML
variables: one: initialValue
This variable block can also reference previously defined variable groups. Variable groups are managed in the Library tab under the Pipelines menu of your Azure DevOps project.
variables: - group: "Contoso Variable Group" - name: anothervariable value: 'Hi there'
The UI for the YAML pipeline.
- bash: | echo "##vso[task.setvariable variable=myVar;]foo" - bash: | echo "You can use macro syntax for variables: $(myVar)"
It’s this last case (using
task.setvariable) that can be interesting, as by default that variable is only available to subsequent tasks in the same job. To access the variable from other jobs or stages, you need to add
isoutput=true and give the step a name. eg.
- bash: | echo "##vso[task.setvariable variable=myOutputJobVar;isoutput=true]this is the same job too" name: setOutput
And here’s where it gets interesting. Depending on whether the task that is setting the variable (often referred to as an ‘output variable’) is in a regular job or a deployment job, and whether you’re wanting to reference the variable from another job in the same stage or a job in a subsequent stage, the syntax varies.
Most of the existing examples for referencing output variables are listed in the documentation Set variables in scripts, but as deployment jobs have a different syntax, there’s another section under Deployment jobs. Unfortunately, between these two pages, not all the possibilities seem to be covered.
So I came up with a pipeline workflow that correctly demonstrates these options:
- Deployment Job to another Job in the same stage
- Deployment Job to another Job in a different stage
- Deployment Job to another Deployment Job in a different stage
- Job to another Job in a different stage
Here’s the entire YAML pipeline definition (source on GitHub)
trigger: - master pool: vmImage: 'ubuntu-latest' stages: - stage: Stage1 displayName: Stage 1 jobs: - deployment: Stage1DeploymentJob1 displayName: Stage 1 Deployment Job 1 environment: Environment1 strategy: runOnce: deploy: steps: - bash: echo "##vso[task.setvariable variable=my_Stage1DeploymentJob1_OutputVar;isOutput=true]Variable from $(Agent.JobName)" name: stepVar_Stage1DeploymentJob1 displayName: Set my_Stage1DeploymentJob1_OutputVar - stage: Stage2 displayName: Stage 2 dependsOn: Stage1 jobs: - deployment: Stage2DeploymentJob1 displayName: Stage 2 Deployment Job 1 environment: Environment2 strategy: runOnce: deploy: steps: - bash: echo "##vso[task.setvariable variable=my_Stage2DeploymentJob1_OutputVar;isOutput=true]Variable from $(Agent.JobName)" name: stepVar_Stage2DeploymentJob1 displayName: Set my_Stage2DeploymentJob1_OutputVar - job: Stage2Job2 displayName: Stage 2 Job 2 dependsOn: Stage2DeploymentJob1 variables: varFrom_Stage2DeploymentJob1: $[ dependencies.Stage2DeploymentJob1.outputs['Stage2DeploymentJob1.stepVar_Stage2DeploymentJob1.my_Stage2DeploymentJob1_OutputVar'] ] steps: - checkout: none - bash: echo $(varFrom_Stage2DeploymentJob1) displayName: Display varFrom_Stage2DeploymentJob1 - stage: Stage3 displayName: Stage 3 dependsOn: Stage1 variables: varFrom_Stage1DeploymentJob1: $[ stageDependencies.Stage1.Stage1DeploymentJob1.outputs['Stage1DeploymentJob1.stepVar_Stage1DeploymentJob1.my_Stage1DeploymentJob1_OutputVar'] ] jobs: - deployment: Stage3DeploymentJob1 displayName: Stage 3 Deployment Job 1 environment: Environment3 strategy: runOnce: deploy: steps: - bash: echo $(varFrom_Stage1DeploymentJob1) displayName: Display varFrom_Stage1DeploymentJob1 - bash: printenv displayName: printenv - job: Stage3Job2 displayName: Stage 3 Job 2 steps: - checkout: none - bash: echo "##vso[task.setvariable variable=my_Stage3Job2_OutputVar;isOutput=true]Variable from $(Agent.JobName)" name: stepVar_Stage3Job2 displayName: Set my_Stage3Job2_OutputVar - stage: Stage4 displayName: Stage 4 dependsOn: # Need to mention stage here to be able to reference variables from it, even though the dependency is implied by Stage2 and Stage3 - Stage1 - Stage3 - Stage2 jobs: - job: Stage4Job1 displayName: Stage 4 Job 1 variables: varFrom_Stage1DeploymentJob1: $[ stageDependencies.Stage1.Stage1DeploymentJob1.outputs['Stage1DeploymentJob1.stepVar_Stage1DeploymentJob1.my_Stage1DeploymentJob1_OutputVar'] ] varFrom_Stage2DeploymentJob1: $[ stageDependencies.Stage2.Stage2DeploymentJob1.outputs['Stage2DeploymentJob1.stepVar_Stage2DeploymentJob1.my_Stage2DeploymentJob1_OutputVar'] ] varFrom_Stage3Job2: $[ stageDependencies.Stage3.Stage3Job2.outputs['stepVar_Stage3Job2.my_Stage3Job2_OutputVar'] ] steps: - checkout: none - bash: | echo "varFrom_Stage1DeploymentJob1: $(varFrom_Stage1DeploymentJob1)" echo "varFrom_Stage2DeploymentJob1: $(varFrom_Stage2DeploymentJob1)" echo "varFrom_Stage3Job2: $(varFrom_Stage3Job2)" displayName: Display variables - bash: printenv displayName: printenv
The stage dependencies result in the following flow:
Here’s the output from the
Stage4Job1’s Display variables step:
Starting: Display variables ============================================================================== Task : Bash Description : Run a Bash script on macOS, Linux, or Windows Version : 3.201.1 Author : Microsoft Corporation Help : https://docs.microsoft.com/azure/devops/pipelines/tasks/utility/bash ============================================================================== Generating script. ========================== Starting Command Output =========================== /usr/bin/bash /home/vsts/work/_temp/8ce87e72-545d-4804-8461-3910a1412c90.sh varFrom_Stage1DeploymentJob1: Variable from Stage 1 Deployment Job 1 varFrom_Stage2DeploymentJob1: Variable from Stage 2 Deployment Job 1 varFrom_Stage3Job2: Variable from Stage 3 Job 2 Finishing: Display variables
Some things to note:
- The format for referencing a deployment job from a different stage is
$[ stageDependencies.<StageName>.<DeploymentJobName>.outputs['<DeploymentJobName>.<StepName>.<VariableName>'] ]- I’ve seen some online posts suggesting the environment name be used instead of the second
DeploymentJobName, but I think that is incorrect - this format works for me.
- As the comment in the YAML mentions, if you want to reference a variable from a job or stage, then you have to add that to your
dependsOnlist. The fact that Stage 1 is ‘upstream’ from Stage 4 (because Stage 4 explicitly depends on Stage 2 and Stage 3) isn’t enough.
In this post, we saw how to reference variables from previous Jobs or Deployment Jobs in either the same or different stages of an Azure Pipeline.
Categories: Azure Pipelines