lavoizer
lavoizer

Reputation: 411

Azure Devops yml pipeline if else condition with variables

I am trying to use if else conditions in Azure Devops yml pipeline with variable groups. I am trying to implement it as per latest Azure Devops yaml pipeline build.

Following is the sample code for the if else condition in my scenario. test is a variable inside my-global variable group.

variables:
  - group: my-global
  - name: fileName
    ${{ if eq(variables['test'], 'true') }}:
      value: 'product.js'
    ${{ elseif eq(variables['test'], false) }}:
      value: 'productCost.js'

jobs:
  - job:
    steps:
      - bash:
          echo test variable value $(fileName)

When the above code is executed, in echo statement we don't see any value for filename, i.e. it empty, meaning none of the above if else condition was executed, however when I test the if else condition with the following condition.

  - name: fileName
    ${{ if eq('true', 'true') }}:
       value: 'product.js'

Filename did echo the correct value, i.e. product.js. So my conclusion is that I am not able to refer the variables from the variable group correctly. So any suggestion will be helpful and appreciated. Thanks!

Upvotes: 6

Views: 23681

Answers (5)

Krzysztof Madej
Krzysztof Madej

Reputation: 40533

As of 17.01.2025 you can simplify Tejas solution as ternary operator is available

trigger:
  - none

variables:
  - group: Temp-group-for-testing
  - name: fileName
    value: $[ iif(eq(variables['test'], 'true'), 'product.js', 'productCost.js') ]

stages:
  - stage: test
    jobs: 
     - job: testvar
       continueOnError: false
       steps: 
         - bash: echo $(fileName)
           displayName: "echo variable"

And in general you issue here was that values from variable groups are available at runtime, and syntax ${{ }} is evaluated at compilation time. So your variable was not available at compilation. Syntax $[] is evaluated at runtime, this more variables are available.

Upvotes: 1

Will
Will

Reputation: 387

A cleaner solution in my opinion is to set the variable to a default value (your "else" case) and then have a set variable step to override that value conditionally (your "if" case).

This is "essentially" an if-else and doesn't feel like a hack or workaround like other answers here.

variables:
  # defaults to Testing but conditionally changes to Production if the source branch is release (see below)
  Environment: 'Testing' 

steps: 
- task: VariableSetTask@3
  inputs:
    variableName: 'Environment'
    From: 'value'
    value: 'Production'
  condition: eq(variables['Build.SourceBranch'],'refs/heads/release')
  displayName: 'Set Production Environment'

- script: |
    echo Environment: $(Environment)
    echo Build Source Branch: $(Build.SourceBranch)
  displayName: 'Print Variables'

Upvotes: 1

Marc Wrobel
Marc Wrobel

Reputation: 704

Unfortunately there is no ternary operator in Azure DevOps Pipelines. And it seems unlikely considering the state of https://github.com/microsoft/azure-pipelines-yaml/issues/256 and https://github.com/microsoft/azure-pipelines-yaml/issues/278. So for the time being the only choices are :

  • conditional insertion : it works with parameters, and should work with variables according to the documentation (but it is difficult to use properly),
  • or the hacks you can find in this Stack Overflow question.

Another work-around has been posted by Simon Alling on GitHub (https://github.com/microsoft/azure-pipelines-yaml/issues/256#issuecomment-1077684972) :

format(
  replace(replace(condition, True, '{0}'), False, '{1}'),
  valueIfTrue,
  valueIfFalse
)

It is similar to the solution provided by Tejas Nagchandi, but I find it a little bit better because the syntax looks closer to what it would be if there was a ternary operator.

Upvotes: 5

Tejas Nagchandi
Tejas Nagchandi

Reputation: 512

I was able to achieve the goal using some dirty work-around, but I do agree that using parameters would be much better way unless ternary operators are available for Azure DevOps YAML pipeline.

The issue is that ${{ if condition }}: is compile time expression, thus the variables under variable group are not available.

I was able to use runtime expressions $[<expression>]

Reference: https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops

My pipeline:

trigger:
  - none

variables:
  - group: Temp-group-for-testing
  - name: fileName
    value: $[replace(replace('True',eq(variables['test'], 'True'), 'value1'),'True','value2')]

stages:
  - stage: test
    jobs: 
     - job: testvar
       continueOnError: false
       steps: 
         - bash: echo $(fileName)
           displayName: "echo variable"

Results are available on github

Upvotes: 9

lavoizer
lavoizer

Reputation: 411

After detailed investigation I realized that if else doesnt work with variables in Az Devop yaml pipelines, it only works with parameters. However the solution posted by @Tejas Nagchandi is a workaround and might be able to accomplish the same logic of if else setting variable value with replace commands. Hats off to TN.

Upvotes: 2

Related Questions