Azure Devops yml pipeline if else condition with variables
Asked Answered
F

4

5

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!

Frederick answered 20/10, 2021 at 20:25 Comment(6)
#69378958Vezza
this link is not correct, i am trying to do something else, you cant just post me a link and close my question. thats not fair.Frederick
Ok, re-opened, but I still think you're asking the same thing. You want to use a condition to override a value of a YAML declared variable using another variable. That doesn't work, at the time the YAML template is expanded, our own variables aren't available yet. So you need to fix this at runtime. Or I'm totally misunderstanding your question.Vezza
Basically, at the time of template expansion, the variable variables['test'] is undeclared, because the variable group won't be fully loaded until the variable block has expanded.Vezza
I'll echo @jessehouwing's comment on the variable reference - if the variable is defined statically in the variables section of the current file, you should be able to reference it - group variable references should not be available at this point in your file.Sur
@Sur - i think if else doesnt work with variables, however if you have any example of such code that works for if else with variables that would be interesting to see. please share.Frederick
F
2

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.

Frederick answered 3/12, 2021 at 11:29 Comment(0)
S
9

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

Summerly answered 1/12, 2021 at 12:51 Comment(7)
can you retest your working scenario cuz it will set the value of test to value1, independent of if else condition.Frederick
Retested with indentation just like yours. code ${{ if eq(variables['test'], 'False') }}: value: 'value1' ${{ else }}: value: 'value2' output: value2Summerly
strange, my observation is something else, i was able to sort it out. If else only works with parameters, not variables, can you share a working example for if else with variables, i am intrigued.Frederick
@lavoizer: I got the issue now, don't have a good solution but was able to achieve the goal with some work-around. I have updated the solution and more details are available on github.com/tejas-nagchandi/azure-devops-conditional-variableSummerly
Hey - I was trying to understand this, how does this work? can you explain? $[replace(replace('True',eq(variables['test'], 'True'), 'value1'),'True','value2')]Frederick
@lavoizer: The explanation is available here github.com/tejas-nagchandi/…Summerly
update path for github repo github.com/tejas-nagchandi/stackoverflowissues/tree/main/…Summerly
C
5

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.

Clamp answered 19/4, 2022 at 10:52 Comment(0)
F
2

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.

Frederick answered 3/12, 2021 at 11:29 Comment(0)
E
0

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'
Essayistic answered 5/9 at 18:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.