79

I am trying to figure out how to share custom variables across ADO pipelines in my script. Below is my script with 2 stages.

I am setting the curProjVersion as an output variable and trying to access it from a different stage. Am I doing it right?

stages:
- stage: Build
  displayName: Build stage
  jobs:
  - job: VersionCheck
    pool:
      vmImage: 'ubuntu-latest'
    displayName: Version Check
    continueOnError: false
    steps:

      - script: |
          echo "##vso[task.setvariable variable=curProjVersion;isOutput=true]1.4.5"
        name: setCurProjVersion
        displayName: "Collect Application Version ID"

- stage: Deploy
  displayName: Deploy stage
  dependsOn: Build
  variables:
    curProjVersion1: $[ dependencies.Build.VersionCheck.outputs['setCurProjVersion.curProjVersion'] ]
  jobs:
  - job: 
    steps: 
      - script: |
          echo $(curProjVersion1)
1
  • more detailed explanation with sample source code explained here Commented May 27, 2022 at 4:19

10 Answers 10

75

Updated:

Share variables across stages feature has been released in Sprint 168 now.

Please use below format to access output variables from previous stage:

stageDependencies.{stageName}.{jobName}.outputs['{stepName}.{variableName}'] 

Original:

Share variables across stages in Azure DevOps Pipelines

I'm afraid to say that it does not supported to share the variable which defined in one stage and pass it into another stage.

This is the feature we are plan to add, but until now, it does not supported. You can follow this Github issue, many people has the same demand with you. You can follow track that.

Until now, we only support set a multi-job output variable, but this only support YAML. For Classic Editor, there's no any plan to add this feature in release.

For work around, you can predefined the variables before the stages. But one important thing is if you change its value in one stage. The new value could not be passed to the next stage. The lifetime of variable with new value only exists in stage.

Sign up to request clarification or add additional context in comments.

9 Comments

it works for jobs but not for deployment jobs - any chance of looking at it?
The initially documented syntax DOES NOT work for stage conditions. The correct syntax (for stage conditions) is stageDependencies.{stageName}.outputs['{jobName}.{stepName}.{variableName}']. See github issue on cross-stage variables for more info.
I have multiple templates linked to the main pipeline yml. Each template contains a stage and at least a job. One thing I noticed in this scenario is stage dependencies will only read output variables in previous template
more detailed explanation with sample source code explained here
@scorpio for deployment jobs you have slightly different syntax! You need to add job name again. Details: learn.microsoft.com/en-us/azure/devops/pipelines/process/…
|
35

What is important to mention stageDependencies is not available in condition at stage level. It is aviable in jobs, but not in stage directly (at least at the moment).

stages:
- stage: A
  jobs:
  - job: JA
    steps:
    - script: |
        echo "This is job Foo."
        echo "##vso[task.setvariable variable=doThing;isOutput=true]Yes" #The variable doThing is set to true
      name: DetermineResult
    - script: echo $(DetermineResult.doThing)
      name: echovar
  - job: JA_2
    dependsOn: JA
    condition: eq(dependencies.JA.outputs['DetermineResult.doThing'], 'Yes')
    steps:
    - script: |
        echo "This is job Bar."

#stage B runs if DetermineResult task set doThing variable n stage A
- stage: B
  dependsOn: A
  jobs:
  - job: JB
    condition: eq(stageDependencies.A.JA.outputs['DetermineResult.doThing'], 'Yes') #map doThing and check if true
    variables:
      varFromStageA: $[ stageDependencies.A.JA.outputs['DetermineResult.doThing'] ]
    steps:
    - bash: echo "Hello world stage B first job"
    - script: echo $(varFromStageA)

4 Comments

This appears to no longer work because the reference should be $[ stageDependencies.A.JA.outputs['JA.DetermineResult.doThing'] ]
I'm trying to get this to work passing it as a parameter with a template that contains JB, but I cannot get it to work.
@Roelant please create a new question for this. It would be difficult to reply you in a comment.
The ONLY way I was able to get a stageDepencies reference in a conditionto work was using the above approach (using it at the job level, not the stage level), AND taking special care to reference the stage outputting the variable in the dependsOn section (it's easy to miss this last part). Otherwise, this fails silently, which is honestly infuriating. Also make sure you set isOutput=true on your output variable, as this too is easy to miss.
19

Jobs can now access variables from previous stages

Output variables are still produced by steps inside of jobs. Instead of referring to dependencies.jobName.outputs['stepName.variableName'], stages refer to stageDependencies.stageName.jobName.outputs['stepName.variableName'].

https://learn.microsoft.com/en-us/azure/devops/release-notes/2020/sprint-168-update#azure-pipelines-1

Comments

19

This is available as of May 4th 2020

Jobs can access output variables from previous stages:

Output variables may now be used across stages in a YAML-based pipeline. This helps you pass useful information, such as a go/no-go decision or the ID of a generated output, from one stage to the next. The result (status) of a previous stage and its jobs is also available.

Output variables are still produced by steps inside of jobs. Instead of referring to dependencies.jobName.outputs['stepName.variableName'], stages refer to stageDependencies.stageName.jobName.outputs['stepName.variableName'].

Note

By default, each stage in a pipeline depends on the one just before it in the YAML file. Therefore, each stage can use output variables from the prior stage. You can alter the dependency graph, which will also alter which output variables are available. For instance, if stage 3 needs a variable from stage 1, it will need to declare an explicit dependency on stage 1.

2 Comments

the note you copied from the docs helped me. My dependency wasn't working, but I didn't add an explicit dependency on the the prior stage
The line, "For instance, if stage 3 needs a variable from stage 1, it will need to declare an explicit dependency on stage 1" is exactly what I was missing. Read about that here
11

For stage conditions on Azure DevOps Version Dev17.M153.5 with Agent Version 2.153.1 the following works:

stages:
- stage: A
  jobs:
  - job: JA
    steps:
    - script: |
        echo "This is job Foo."
        echo "##vso[task.setvariable variable=doThing;isOutput=true]Yes" #The variable doThing is set to 'Yes'
      name: DetermineResult

#stage B runs if DetermineResult task set doThing variable on stage A
- stage: B
  dependsOn: A
  condition: eq(dependencies.A.outputs['JA.DetermineResult.doThing'], 'Yes')
  jobs:
  - job: JB
    steps:
    - bash: echo "Hello world stage B first job"

Note: The layout of properties is different on stage compared to job:

dependencies.{stage name}.outputs['{job name}.{script name}.{variable name}']

Note: The expression with 'stageDependencies' failed with the following error message:

An error occurred while loading the YAML build pipeline. Unrecognized value: 'stageDependencies'. Located at position XX within expression: and(always(), eq(stageDependencies.A.outputs['JA.DetermineResult.doThing'], 'Yes')). For more help, refer to https://go.microsoft.com/fwlink/?linkid=842996

Bonus:

See the following documentation on how to access the status of the dependent stages: link

Corresponding documentations:

To use the output from a different stage, you must use the syntax depending on whether you're at the stage or job level:

  • At the stage level, the format for referencing variables from a different stage is dependencies.STAGE.outputs['JOB.TASK.VARIABLE']. You can use these variables in conditions.
  • At the job level, the format for referencing variables from a different stage is stageDependencies.STAGE.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.

2 Comments

The above description still works on Azure DevOps Server Version 2020 Update 1.1 with Agent Version 2.191.1 (Windows and Linux agents as well)
Worked fine for me, Azure DevOps (cloud) / self-hosted Linux agents. Caution!!! As written in this answer, make sure to use name: DetermineResult and not displayName: DetermineResult. Just wasted 30 minutes until I figured out...
4

important notice to the solution:

it is only suitable for 1 directly following stage.

assuming you have:

  • stageA - sets variable X
  • stageB - consumes variable X over stageDependencies - works
  • stageC - can't consume variable X unless you specify the dependsOn stageA and stageB.

this is a gotcha i faced recently, the value of variable X consumed by stageC was empty. when you specify dependsOn, you can't just add stageA, it then becomes a parallel stage (what?), so you need to add both stageA and stageB. but such pipeline looks silly.

so i suggest to use artifacts instead. looks like a more robust solution for me.

2 Comments

Helpful . I stumbled on this and tried all possible ways. Your finding worked for me.
I had this issue, it took me a long time to find it Thank you
3

Yes this is possible, you need stageDependencies like below:

stages:
- stage: Build
  displayName: Build stage
  jobs:
  - job: VersionCheck
    pool:
      vmImage: 'ubuntu-latest'
    displayName: Version Check
    continueOnError: false
    steps:

      - script: |
          echo "##vso[task.setvariable variable=curProjVersion;isOutput=true]1.4.5"
        name: setCurProjVersion
        displayName: "Collect Application Version ID"

- stage: Deploy
  displayName: Deploy stage
  dependsOn: Build
  variables:
    curProjVersion1: $[ stageDependencies.Build.VersionCheck.outputs['setCurProjVersion.curProjVersion'] ]
  jobs:
  - job: 
    steps: 
      - script: |
          echo $(curProjVersion1)

Note that I have changed

$[ dependencies.Build.VersionCheck.outputs['setCurProjVersion.curProjVersion'] ]

TO

$[ stageDependencies.Build.VersionCheck.outputs['setCurProjVersion.curProjVersion'] ]

source: https://jimferrari.com/2023/01/05/pass-variables-across-jobs-and-stages-in-azure-devops-pipelines/

2 Comments

how do i do it if insted of - job: VersionCheck i have - template: jobs/checkprojectype.yaml@devops
I assume you are trying to pass job to job in the same stage? Can you send me a full code snippet please?
0

As an update for anyone seeing this question, it seems passing variables between stages has been implemented and should be released in the next couple of weeks.

1 Comment

"Links are fantastic, but they should never be the [only piece of information in your answer." meta.stackexchange.com/questions/8231/…
-2

You can define a global variable and use a Powershell to assign the value of the stage variable to the global variable.

Write-Output ("##vso[task.setvariable variable=globalVar;]$stageVar")

Global variables can either be defined in the yaml itself or in variable groups. Initialise the var with an empty value.

E.g. yaml

  variables:
    globalVar: ''

4 Comments

Thanks! Ill try this out.
Hey @zooes did that end up working out for you? I found this discussion on GitHub where it seems like the only way is to save it to AKV, or use a DB/file somewhere github.com/microsoft/azure-pipelines-tasks/issues/4743
@bla9x - No, it didnt work, because looks like MS-ADO doesnt let you share vars across stages. And you are right, the only way to share it, is either AKV/DB/File.
It creates snapshot for each job. So globalVar in one stage is sth different than globalvar in a different job. So this mechanism you can use to pass the same value across all jobs in all stages, but not to pass value from one to another. For that purpose you should use output variable which are available to share values across stages (at the moment of writing this comment).
-4

You can define the variables just after you define the trigger and before you define the stages

trigger:
- master
  variables:
    VarA: aaaaa
    VarB: bbbbb
stages:
- stage: Build  
  jobs:
  - job: Build
    pool:
      vmImage: 'vs2017-win2016'

1 Comment

Looking at the docs the var declaration goes at the root level, at the top of the file. When I add it to the trigger my vscode extensions throws an error Unexpected property variables

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.