Home > Enterprise >  Azure Pipeline pass parameter from one job to another
Azure Pipeline pass parameter from one job to another

Time:06-09

My ci_pipeline.yml contains the following:

- stage: DeployDEV
  pool:
    vmImage: 'windows-latest'
  variables:
    - group: [REDACTED]
    - name: test_var
      value: firstval
  jobs:
    - job: BuildDeploy
      displayName: "REDACTED"
      steps:
        - script: echo "test_var = $(test_var)"
          displayName: first variable pass

        - bash: echo "##vso[task.setvariable variable=test_var]secondValue"
          displayName: set new variable value

        - script: echo "test_var = $(test_var)"
          displayName: second variable pass

          name: Env
          displayName: "Extract Source Branch Name"
    - template: pipeline_templates/ci_pipeline_templates/build_deploy_dev.yml
      parameters:
        testvar: $(test_var)

and in the build_deploy_dev.yml template:

parameters:
  - name: testvar

jobs:
    - job: Test
      displayName: "Testjob"
      steps:
        - script: echo "test_var=${{ parameters.testvar }}"
          name: TestVar
          displayName: 'test'

I need to be able to modify the variable in the main yml file BEFORE passing it into the template. However, test_var still remains as firstval. What am I doing wrong? It seems like the change is successful in the main yml file. The second variable pass script displays test_var=secondValue. How to make the change be permanent so the template can have it ?

CodePudding user response:

Unfortunately you cannot use variables set during runtime, ie. $test_var, as parameters for templates. Think of templates less like functions and more like snippets. The pipeline essentially swaps the guts of the template for the reference to the template and all parameters are evaluated at that time and swapped.

So when you set $test_var to 'firstval', the template is evaluated at that time and the parameter is set to 'firstval' as well. Then when you set $test_var later in the yaml, it is too late. See the documentation below:

https://docs.microsoft.com/en-us/azure/devops/pipelines/process/templates?view=azure-devops#context

It may feel dirty to reuse code but unfortunately this would be the recommended solution.

- stage: DeployDEV
      pool:
        vmImage: 'windows-latest'
      variables:
        - group: [REDACTED]
        - name: test_var
          value: firstval
      jobs:
        - job: BuildDeploy
          displayName: "REDACTED"
          steps:
            - script: echo "test_var = $(test_var)"
              displayName: first variable pass
    
            - bash: echo "##vso[task.setvariable variable=test_var]secondValue"
              displayName: set new variable value
    
            - script: echo "test_var = $(test_var)"
              displayName: second variable pass
                  
        - job: Test
          displayName: "Testjob"
          steps:
            - script: echo "test_var=$(test_var)"
              name: TestVar
              displayName: 'test'

CodePudding user response:

As stated above: Parameters are evaluated in compile time. So, using parameters won't solve your problem, however you can create a new variable as an output and make your template job dependent from the job which generates a new variable afterwards you can use it in your template as follows:

ci_pipeline.yml

- stage: DeployDEV
  pool:
    vmImage: 'windows-latest'
  variables:
    - group: [REDACTED]
    - name: test_var
      value: firstval
  jobs:
    - job: BuildDeploy
      displayName: "REDACTED"
      steps:
        - script: echo "test_var = $(test_var)"
          displayName: first variable pass

        - bash: echo "##vso[task.setvariable variable=new_var;isOutput=true]SomeValue"
          displayName: set new variable value
          name: SetMyVariable

          name: Env
          displayName: "Extract Source Branch Name"

    - template: pipeline_templates/ci_pipeline_templates/build_deploy_dev.yml

Then in your build_deploy_dev.yml you can use the variable you've created previously:

jobs:
    - job: Test
      variables:
        test_var: $[ dependencies.BuildDeploy.outputs['SetMyVariable.new_var'] ]
      displayName: "Testjob"
      dependsOn: BuildDeploy
      steps:
        - script: echo "test_var=$(test_var)"
          name: TestVar
          displayName: 'test'

Note that you can still leverage your $(test_var) for instance to check whether it has the value 'firstValue' and then in case positive you create the 'newVar' and use it on the other job, you could even use the value of $(test_var) in your 'newVar' and use the value which you previously set:

- bash: echo "##vso[task.setvariable variable=new_var]$(test_var)"
  displayName: set new variable value

In this way you can dynamically 'change' the behavior of your pipeline and keep your template file.

  • Related