In Azure DevOps pipelines, passing variables between jobs and stages is a fundamental aspect of creating dynamic and flexible workflows. This capability allows data, such as build outputs, version numbers, or environment variables, to be shared between different parts of the pipeline. Whether you’re building, testing, or deploying applications, having a smooth and automated flow of information between stages is essential.
In this blog post, we’ll walk through how to define and pass variables between jobs and stages using both Bash and PowerShell scripts. You’ll also learn how to utilize these techniques to create more dynamic and reusable CI/CD workflows.
Key Concepts
Before diving into examples, let’s cover some key concepts:
Variables in Azure DevOps:
These are values that can be used throughout your pipeline. Variables can be predefined, such as Build.BuildId or System.DefaultWorkingDirectory, or custom variables that you define.Job Outputs:
A job in Azure DevOps can output variables that other jobs can access using a specific syntax. This allows the result of one job (e.g., a generated version number) to be passed to another job without needing manual input.Stage Dependencies
In Azure DevOps, stages represent major phases in your pipeline. You can organize your pipeline into multiple stages, and you can control the execution flow between them using stage dependencies.Purpose:
Stage dependencies help you control the order in which stages run. By default, stages in a pipeline run sequentially, but you can adjust this behavior to make certain stages dependent on the outcome of other stages.Syntax:
Stage dependencies are specified using the dependsOn keyword in a stage’s configuration. You can also use the stageDependencies syntax to pass variables between stages.
Job Dependencies
A job is a set of steps that run on an agent. Just like stages, jobs can also have dependencies to control the order in which they run.Purpose:
Job dependencies allow you to control the execution order of jobs within a stage or across stages. This is useful when one job needs the output or result of another job to proceed.Syntax:
You can specify job dependencies using dependsOn. By default, jobs within a stage run in parallel unless specified otherwise.
Example: Job - Bash
In the first example, we have two jobs (JobA and JobB). JobA generates a variable, and JobB consumes that variable. The following example uses Bash for both jobs:
|
|
Explanation
JobA
generates a variable generatedVar using a Bash script and sets it as an output variable with the ##vso[task.setvariable] syntax
.
JobB
uses dependencies.JobA.outputs
to reference the variable from JobA and prints it in its Bash script.
Job - PowerShell
In this next example, we’ll use PowerShell for the same job structure. The setup is similar, but we’re utilizing PowerShell scripting instead of Bash.
|
|
Explanation
Similar to the Bash example, JobA
generates a variable using PowerShell and outputs it.
JobB
then consumes the output from JobA
and prints it using PowerShell.
Stage - Bash
Now let’s look at how to pass variables between stages. This example uses Bash for both stages.
|
|
Explanation
In the Build stage, BuildJob
generates a variable buildVersion with the value 1.0.0.
In the Deploy stage, DeployJob
consumes the buildVersion variable using stageDependencies and prints it.
Stage - PowerShell
Here’s the same example as above but using PowerShell.
|
|
Explanation
In this PowerShell version, BuildJob
sets the buildVersion
variable using Write-Host.
DeployJob accesses the variable using stageDependencies
and prints it.
Variable Input for Jobs - Bash
In this example, we demonstrate how to define and pass variables across different jobs within an Azure DevOps pipeline using Bash.
Key Components
Parameters:
We start by defining a parametermyName
with adefault
value. This allows the user to input their name when the pipeline is triggered.Setting Variables in Job A:
In the first job, we set the variable using a Bash script. The value ofmyName
is passed from the parameters to the script via the${{ parameters.myName }}
syntax. Once the value is set, we use the##vso[task.setvariable]
command to makemyName
available to other jobs in the pipeline, with theisOutput=true
flag ensuring that the variable can be accessed by downstream jobs.Using Variables in Job B:
The second job,JobB
, depends on the successful completion of theSetVariables
job. We reference the variable set inJobA
by using thedependencies.SetVariables.outputs
syntax. In theJobB
job, we use the$(jobAOutput)
variable to print the output ofJobA
.
|
|
Variable Input for Jobs - PowerShell
Now let’s look at a similar example but using PowerShell. This approach demonstrates how to define and use pipeline parameters, set variables, and reference them in subsequent jobs.
Key Components
Parameters:
As with the Bash example, we define amyName
parameter, which will be passed to the PowerShell script.Setting Variables in Job A:
In the SetVariables job, we use PowerShell to assign the parameter value to the$myName
variable. This is accomplished by reading the environment variablemyName
from the pipeline context($env:myName)
. TheWrite-Host
command prints the message, and again we use the##vso[task.setvariable]
to share the variable as an output.Using Variables in Job B:
Just like in the Bash example,JobB
consumes the output variable fromSetVariables
. ThejobAOutput
variable is populated using thedependencies.SetVariables.outputs
syntax, and we print the value of the variable in thePrint the variable from Job A
step.
|
|
Variable Input for Stages - Bash
In this example, we demonstrate how to define and pass variables across different stages within an Azure DevOps pipeline using Bash.
Key Components
Parameters:
We define a parametermyName
with a default value, allowing the user to input their name when the pipeline is triggered.Setting Variables in Stage 1:
In the first stage(Stage1)
, we set the variable using a Bash script. The value of myName is passed from the parameters to the script via the${{ parameters.myName }}
syntax. The##vso[task.setvariable]
command makesmyName
available to other stages in the pipeline with theisOutput=true
flag ensuring that the variable can be accessed by downstream stages.Using Variables in Stage 2:
The second stage,Stage2
, depends on the successful completion of Stage1. We reference the variable set inStage1
by using thedependencies.Stage1.outputs
syntax. InStage2
, we use the$(stage1Output)
variable to print the output fromStage1
.
|
|
Variable Input for Stages - PowerShell
Now let’s look at a similar example but using PowerShell to define and pass variables across stages.
Key Components
Parameters:
As with the Bash example, we define amyName
parameter that will be passed to the PowerShell script.Setting Variables in Stage 1:
InStage1
, we assign the parameter value to the$myName
variable using PowerShell. TheWrite-Host
command prints the message, and the##vso[task.setvariable]
command shares the variable as an output.Using Variables in Stage 2:
Stage2
consumes the output variable fromStage1
. Thestage1Output
variable is populated usingdependencies.Stage1.outputs
, and we print the value of the variable inStage2
.
|
|
Wrap Up
In this post, we’ve explored how to seamlessly pass variables between jobs and stages in Azure DevOps pipelines. This crucial aspect of pipeline design enables dynamic and flexible workflows, making it easier to automate complex processes.
Key Takeaways
Variables in Azure DevOps can be used to store values that persist across jobs and stages, including predefined and custom variables.
Job Outputs and Stage Dependencies allow you to share data between different parts of the pipeline, using the
##vso[task.setvariable]
syntax for jobs andstageDependencies
for stages.We’ve seen examples of how to pass variables using Bash and PowerShell scripts, demonstrating both job-to-job and stage-to-stage variable passing.
By incorporating these practices into your Azure DevOps pipelines, you can create more modular, maintainable, and dynamic automation flows. Whether you’re working with simple jobs or more complex stages, understanding how to leverage output variables and dependencies will improve your pipeline’s efficiency and scalability.
Keep experimenting with these techniques to build more advanced workflows and harness the full potential of Azure DevOps!