Search code examples
azure-devopsyamlcontinuous-integrationazure-pipelinesazure-pipelines-yaml

Can we use runtime variables in conditional statement while calling a template in Azure Pipelines?


Hello I am not sure whether this could be achieved or not but heres my question ! I have two YAML files.

  1. Parent Yaml : SetVariable.yml
  2. Template Yaml : setvariabletemplate.yml

We are setting a Set Variable in parent variable and based on its value i.e. True/False. I want the following template to run. Ideally : So if the value is false, it should go inside the template but if its true, it should fall in the else statement.

Result (whats happening now) : It is executing else statement irrespective of the Set Variable.

Below are the two YAMLs im using.

  1. Parent Yaml
trigger: none

pool: Self Hosted Docker (Linux)

jobs:
- job: A
  steps:
    - powershell: |
        $a="lakshay"

        if ($a -eq "lakshay")
        {
          $skipEnvironmentDeployment = $true
        }
        else {
          $skipEnvironmentDeployment = $false
        } 
        
        Write-Host "##vso[task.setvariable variable=SkipEnvironmentDeployment;isOutput=true]$skipEnvironmentDeployment"

      name: ProduceVar
    
    - powershell: |
        Write-Host $(ProduceVar.SkipEnvironmentDeployment)

- ${{ if eq(variables['ProduceVar.SkipEnvironmentDeployment'], 'false') }}:
  - template: setvariabletemplate.yml
  
- ${{ else }}:
  - job: C
    steps:
    - powershell: |
        Write-Output "Hello from Job C" 
  1. Template Yaml
jobs:
- job: B
  steps:
    - powershell: Write-Host "Hello from Job B"

I looked at the documentation but couldnt find what I was looking for.


Solution

  • To turn a pipeline into a run, the first step is to expand templates and evaluate template expressions. But the output variable is only available at runtime, so setvariabletemplate.yml is not expanded. See the detailed info about pipeline run sequence from Process the pipeline.

    According to your yaml, you seem to want to run job B when the value of SkipEnvironmentDeployment is false, otherwise run job C. If so, you can use runtime expressions $[] in the condition. Refer to the example below.

    The Parent Yaml

    jobs:
    - job: A
      steps:
        - powershell: |
            $a="lakshay"
    
            if ($a -eq "lakshay")
            {
              $skipEnvironmentDeployment = $true
            }
            else {
              $skipEnvironmentDeployment = $false
            } 
            
            Write-Host "##vso[task.setvariable variable=SkipEnvironmentDeployment;isOutput=true]$skipEnvironmentDeployment"
          name: ProduceVar
        
        - powershell: |
            Write-Host $(ProduceVar.SkipEnvironmentDeployment)
    
    - job: B
      dependsOn: A
      condition: eq(dependencies.A.outputs['ProduceVar.SkipEnvironmentDeployment'], 'false')
      steps:
      - template: mysetvariabletemplate.yml
    
    - job: C
      dependsOn: A
      condition: eq(dependencies.A.outputs['ProduceVar.SkipEnvironmentDeployment'], 'true')
      steps:
      - powershell: |
          Write-Output "Hello from Job C" 
    

    The Template Yaml:

    steps:
      - powershell: Write-Host "Hello from Job B"
    

    Update

    If your jobA is also a template, you can put the dependsOn and condition inside the template.

    The Parent Yaml:

    jobs:
    - template: jobA.yml
    - template: jobB.yml
    - template: jobC.yml
    

    The jobA.yml:

    jobs:
    - job: A
      steps:
        - powershell: |
            $a="lakshay1"
    
            if ($a -eq "lakshay")
            {
              $skipEnvironmentDeployment = $true
            }
            else {
              $skipEnvironmentDeployment = $false
            } 
            
            Write-Host "##vso[task.setvariable variable=SkipEnvironmentDeployment;isOutput=true]$skipEnvironmentDeployment"
          name: ProduceVar
        
        - powershell: |
            Write-Host $(ProduceVar.SkipEnvironmentDeployment)
    

    The jobB.yml:

    jobs:
    - job: B
      dependsOn: A
      condition: eq(dependencies.A.outputs['ProduceVar.SkipEnvironmentDeployment'], 'false')
      steps:
        - powershell: Write-Host "Hello from Job B"
    

    The jobC.yml:

    jobs:
    - job: C
      dependsOn: A
      condition: eq(dependencies.A.outputs['ProduceVar.SkipEnvironmentDeployment'], 'true')
      steps:
      - powershell: |
          Write-Output "Hello from Job C"