Share variables across stages in azure pipelines with templates

56 Views Asked by At

i have an azure pipeline that is what it looks like in pipeline.yml represented below. i'm trying to pass the variable set in stage to a job in another stage like a parameters. the problem is that it doesn't work:

job_template1.yml:

jobs:  
- job: A1
  steps:
  - script: echo ##vso[task.setvariable variable=shouldrun;isOutput=true]true
    name: printvar

job_template2.yml:

parameters:
  myparam: ''

jobs:
- job: B1
  steps:
  - script: echo ${{ parameters.myparam }}

pipeline.yml

stages:
- stage: A
  jobs:
  - template: job_template1.yml
- stage: B
  jobs:
  - template: job_template2.yml
    parameters:
      myparam: $[ stageDependencies.A.A1.outputs['printvar.shouldrun'] ]

the final echo is: $[ stageDependencies.A.A1.outputs['printvar.shouldrun'] ]

any idea on how to fix it?

i even tried changing the pipeline in:

stages:
- stage: A
  jobs:
  - job: A1
    steps:
    - script: echo ##vso[task.setvariable variable=shouldrun;isOutput=true]true
      name: printvar
- stage: B
  jobs:
  - template: job_template2.yml
    parameters:
      myparam: $[ stageDependencies.A.A1.outputs['printvar.shouldrun'] ]

without any luck

4

There are 4 best solutions below

0
wes On

I have something similar in our templated pipeline. One of the things you forgot to add is the dependsOn tag and you are not using quotes (") around the script.

In order to get it to work, you will need to save the variable that you set in Stage A in a variable for stage B, as shown below.

Here is a sample code in 1 file. But splitting these up in multiple templates shouldn't cause any issues.

stages:
  - stage: A
    jobs:
      - job: A1
        steps:
          - script: echo "##vso[task.setvariable variable=shouldrun;isOutput=true]true"
            name: printvar
  - stage: B
    dependsOn: A
    variables:
      - name: test
        value: $[ stageDependencies.A.A1.outputs['printvar.shouldrun'] ]
    jobs:
      - job: B1
        steps:
          - script: echo $(test)

Hope this helps.

0
Ziyang Liu-MSFT On

To turn a pipeline into a run, the first step is to expand templates and evaluate template expressions. During that step, runtime variables don't exist. Therefore, you can't pass output variable to a template parameter. See Process the pipeline for the detailed info.

To share variables between stages, you can use logging command to define output variables and map the output variable to a stage, job, or task-scoped variable in a future stage. As shown by wes, he mapped shouldrun to a stage-scoped variable.

According to the official doc Set an output variable for use in future stages, output variables are only available in the next downstream stage. If multiple stages consume the same output variable, use the dependsOn condition. If you set an output variable in stageA and only consume it in the next stage "stageB", it is OK without using dependsOn condition. For example,

job_template2.yml

jobs:
- job: B1
  variables:
    myStageAVar: $[stageDependencies.A.A1.outputs['printvar.shouldrun']]
  steps:
    - script: echo $(myStageAVar)

main.yml

#Without dependsOn condition
stages:
- stage: A
  jobs:
  - template: job_template1.yml
- stage: B
  jobs:
  - template: job_template2.yml

There is no change in job_template1.yml.

0
wenbo On

Issues:

  1. issue 1: echo "##vso[task.setvariable variable=shouldrun;isOutput=true]true" double quotes missing
  2. issue 2: parameters should be provided explicitly, and its value needed already exist at the beginning, can't be the value during the run-time. (as your code it be produced at the mid-process)

job_template1.yml

jobs:  
- job: A1
  steps:
  - script: echo "##vso[task.setvariable variable=shouldrun;isOutput=true]true"
    name: printvar

job_template2.yml

jobs:
- job: B1
  variables: 
    myVarfromStageA: $[ stageDependencies.A.A1.outputs['printvar.shouldrun'] ]

  steps:
  - script: echo $(myVarfromStageA)

main.yml

stages:
- stage: A
  jobs:
  - template: job_template1.yml
- stage: B
  dependsOn: A
  jobs:
  - template: job_template2.yml

What's more, setVariable should use variable of string type. boolean type true here also be treated as string 'true'

0
VishwajeetMCA On

We can also use the concept for variable groups like below variables:

  • group: my-variable-group

We can also use both individual variables and variable groups together: variables:

  • group: my-variable-group
  • name: my-bare-variable value: 'value of my-bare-variable'