skip to Main Content

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 ?

2

Answers


  1. 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://learn.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'
    
    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search