← Back to Articles         
Azure DevOps: Passing Variables and Output Values Between Jobs and Stages

Azure DevOps: Passing Variables and Output Values Between Jobs and Stages

Published on 08 Oct 2026     8 min read Azure DevOps
YAML Pipelines

1. What are Output Variables in Azure DevOps?

In Azure DevOps YAML Pipelines, output variables allow us to pass values generated during pipeline execution from one step, job, or stage to another.

For example, suppose an ASP.NET Core Web API pipeline has three stages:

  • Build: Builds the application and generates a version number.

  • UAT: Uses the generated version number during deployment.

  • Production: Uses the same version number for production deployment.

Instead of hardcoding the version number, we can generate it during the Build stage and pass it to subsequent stages.

How does it work?

Azure Pipeline
      |
      v
Build Stage
      |
      | Generate Version = 1.0.25
      |
      v
Set Output Variable
      |
      | appVersion = 1.0.25
      |
      v
UAT Stage
      |
      | Read appVersion
      | Deploy Version 1.0.25
      |
      v
Production Stage
      |
      | Read appVersion
      | Deploy Version 1.0.25
      |
      v
Pipeline Completed

Important: Variables are not automatically shared across all jobs and stages. We must use output variables and dependency expressions to access values across execution boundaries.

2. How to Set an Output Variable

Azure DevOps provides a special logging command:

##vso[task.setvariable variable=variableName;isOutput=true]value

Example:

steps:
- bash: |
    echo "##vso[task.setvariable variable=appVersion;isOutput=true]1.0.25"
  name: SetVersion

Explanation:

Property

Description

task.setvariable

Creates or updates a pipeline variable

variable=appVersion

Variable name

isOutput=true

Marks the variable as an output

1.0.25

Variable value

name: SetVersion

Step reference name used by downstream consumers

The name property is important because other jobs or stages use it to identify the output.

3. Passing Variables Between Steps in the Same Job

When steps belong to the same job, passing values is straightforward.

Example

jobs:
- job: BuildJob
  steps:

  - bash: |
      echo "##vso[task.setvariable variable=appVersion]1.0.25"
    displayName: 'Set Version'

  - bash: |
      echo "Application Version: $(appVersion)"
    displayName: 'Display Version'

Output:

Application Version: 1.0.25

How does it work?

BuildJob
   |
   v
Step 1: Generate Version
   |
   | appVersion = 1.0.25
   |
   v
Step 2: Read Version
   |
   | $(appVersion)
   |
   v
Output: 1.0.25

Here, isOutput=true is not required because both steps belong to the same job.

The updated variable becomes available to subsequent steps, not earlier steps or the same script process that sets it.

4. Passing Output Variables Between Jobs

Suppose we have two jobs:

  • BuildJob generates the application version.

  • DeployJob reads the version.

We use dependencies to access output variables from another job.

YAML example

jobs:

# Job 1: Generate Version
- job: BuildJob
  steps:
  - bash: |
      echo "##vso[task.setvariable variable=appVersion;isOutput=true]1.0.25"
    name: SetVersion

# Job 2: Read Version
- job: DeployJob
  dependsOn: BuildJob

  variables:
    versionFromBuild: $[ dependencies.BuildJob.outputs['SetVersion.appVersion'] ]

  steps:
  - bash: |
      echo "Deploying Version: $(versionFromBuild)"

Explanation

Step 1: BuildJob generates appVersion = 1.0.25.

Step 2: SetVersion identifies the step that produces the output.

Step 3: DeployJob depends on BuildJob.

Step 4: The following expression reads the output:

$[ dependencies.BuildJob.outputs['SetVersion.appVersion'] ]

Step 5: The output is assigned to a local variable named versionFromBuild.

Step 6: DeployJob accesses the variable using:

$(versionFromBuild)

Execution flow

BuildJob
   |
   | Generate appVersion = 1.0.25
   |
   v
SetVersion Step
   |
   | isOutput=true
   |
   v
BuildJob Completed
   |
   v
DeployJob
   |
   | dependsOn: BuildJob
   |
   v
Read Output Using dependencies
   |
   | versionFromBuild = 1.0.25
   |
   v
Deploy Version 1.0.25

Key point: To access output variables from another job in the same stage, use:

$[ dependencies.JobName.outputs['StepName.VariableName'] ]

5. Passing Output Variables Between Stages

In enterprise applications, pipelines usually contain multiple stages.

For example:

Build Stage
     |
     v
UAT Stage
     |
     v
Production Stage

To pass output variables between stages, we use stageDependencies.

YAML example

stages:

# Stage 1: Build
- stage: Build
  jobs:
  - job: BuildJob
    steps:
    - bash: |
        echo "##vso[task.setvariable variable=appVersion;isOutput=true]1.0.25"
      name: SetVersion

# Stage 2: UAT
- stage: UAT
  dependsOn: Build

  jobs:
  - job: DeployUAT

    variables:
      versionFromBuild: $[ stageDependencies.Build.BuildJob.outputs['SetVersion.appVersion'] ]

    steps:
    - bash: |
        echo "Deploying Version: $(versionFromBuild)"

Explanation

The Build stage generates the application version.

The UAT stage depends on the Build stage and reads its output using:

$[ stageDependencies.Build.BuildJob.outputs['SetVersion.appVersion'] ]

Part

Meaning

Build

Source stage name

BuildJob

Source job name

SetVersion

Step that created the output

appVersion

Output variable name

Execution flow

Build Stage
    |
    v
BuildJob
    |
    | Generate appVersion = 1.0.25
    |
    v
SetVersion Step
    |
    | Set Output Variable
    |
    v
Build Stage Completed
    |
    v
UAT Stage
    |
    | dependsOn: Build
    |
    v
DeployUAT Job
    |
    | Read stageDependencies
    |
    v
Deploy Version 1.0.25

Important: Output variables are intended for downstream stages. If a stage needs an output from an earlier, non-immediately preceding stage, explicitly include the source stage in dependsOn.

6. Complete Example: Build → UAT → Production

Let's create a simplified ASP.NET Core deployment pipeline that generates an application version and passes it to both UAT and Production.

trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

stages:

# Stage 1: Build
- stage: Build
  jobs:
  - job: BuildJob
    steps:
    - bash: |
        echo "Building Web API"
        echo "##vso[task.setvariable variable=appVersion;isOutput=true]1.0.25"
      name: SetVersion

# Stage 2: UAT
- stage: UAT
  dependsOn: Build

  jobs:
  - job: DeployUAT

    variables:
      appVersion: $[ stageDependencies.Build.BuildJob.outputs['SetVersion.appVersion'] ]

    steps:
    - bash: |
        echo "UAT Deployment Version: $(appVersion)"

# Stage 3: Production
- stage: Production
  dependsOn:
  - Build
  - UAT

  jobs:
  - job: DeployProduction

    variables:
      appVersion: $[ stageDependencies.Build.BuildJob.outputs['SetVersion.appVersion'] ]

    steps:
    - bash: |
        echo "Production Deployment Version: $(appVersion)"

How does it work?

Developer Pushes Code
         |
         v
Build Stage
         |
         | Generate appVersion = 1.0.25
         |
         v
BuildJob Completed
         |
         v
UAT Stage
         |
         | Read Build Output
         | Version = 1.0.25
         |
         v
UAT Completed
         |
         v
Production Stage
         |
         | Read Build Output
         | Version = 1.0.25
         |
         v
Pipeline Completed

Both deployment stages explicitly depend on the Build stage, and Production also depends on UAT.

This example demonstrates output-variable passing. It does not perform actual application deployment. In a production pipeline, the same build artifact should be promoted across environments rather than rebuilding separately.

7. Difference Between dependencies and stageDependencies

This is an important Azure DevOps interview question.

Feature

dependencies

stageDependencies

Purpose

Access dependency results and outputs

Access outputs from jobs in previous stages

Same-stage job output

Yes

No

Cross-stage output

Yes, in stage-level conditions

Yes, for mapping outputs into variables

Common usage

Job-to-job values, conditions

Stage-to-stage variable passing

Job-to-job syntax

$[ dependencies.BuildJob.outputs['SetVersion.appVersion'] ]

Stage-to-stage syntax

$[ stageDependencies.Build.BuildJob.outputs['SetVersion.appVersion'] ]

Cross-stage condition syntax

For a condition on a stage, the common syntax is:

condition: eq(dependencies.Build.outputs['BuildJob.SetVersion.appVersion'], '1.0.25')

This differs from the expression used to map an output into a job variable.

8. Important Considerations

1. Use isOutput=true for cross-job and cross-stage outputs.

Without it, the value is not exposed using the output-variable dependency syntax.

2. Give the producing step a name.

name: SetVersion

This allows downstream jobs to reference the output reliably.

3. Use runtime expressions to map output variables.

variables:
  appVersion: $[ dependencies.BuildJob.outputs['SetVersion.appVersion'] ]

4. Use dependsOn to establish dependencies.

A downstream job or stage must have the appropriate dependency relationship to access the output.

5. Do not use ordinary output variables for large data.

For large files, deployment packages, or build outputs, use Pipeline Artifacts instead.

6. Avoid exposing sensitive information.

Use secret variables, secure files, Azure Key Vault, or other approved secret-management mechanisms rather than printing secrets in scripts.

9. Interview Questions and Answers

Q1. What is an output variable in Azure DevOps?

An output variable is a value generated by a pipeline step that can be accessed by downstream steps, jobs, or stages.

Q2. How do you create an output variable?

Using the task.setvariable logging command with isOutput=true.

echo "##vso[task.setvariable variable=version;isOutput=true]1.0"

Q3. How do you pass variables between jobs?

Use isOutput=true in the producing step and access the output using dependencies.

Q4. How do you pass variables between stages?

Use stageDependencies to map an output variable from a previous stage into the consuming job.

Q5. What is the purpose of dependsOn?

It defines execution dependencies between jobs or stages, controlling ordering and establishing relationships needed to access outputs.

Q6. Can a variable generated in the Build stage be used in Production?

Yes. The Production stage can access the Build stage output when the appropriate dependency relationship exists.

Q7. What is the difference between pipeline variables and output variables?

Pipeline variables store configuration values, while output variables specifically expose values generated during execution to downstream consumers.

Q8. Can we pass files between jobs using output variables?

No. Output variables are suitable for small text values. Use Pipeline Artifacts to transfer files between jobs or stages.

10. Key Points for Interview

  • Same job: Use $(variableName) in subsequent steps.

  • Different jobs: Use dependencies.

  • Different stages: Use stageDependencies.

  • Output variable: Set isOutput=true.

  • Step name: Required for referencing named output variables.

  • Execution order: Use dependsOn.

  • Files and packages: Use Pipeline Artifacts rather than output variables.

Interview-ready answer

"In Azure DevOps YAML Pipelines, we use output variables to pass dynamically generated values between jobs and stages. We create an output variable using the task.setvariable logging command with isOutput=true. To access an output from another job in the same stage, we use the dependencies expression. To access outputs across stages, we commonly use stageDependencies. We also configure dependsOn to establish the required execution order. For example, a Build stage can generate an application version and pass it to UAT and Production deployment stages, ensuring both use the same version."

Official documentation: Set Variables in Scripts — Microsoft Learn

← Back to Articles