15

I'm trying to figure out a way to do the following

variables:
  ${{ if eq(variables['var-a'], exists_and_is_set) }}:
    namespaceName: $(var-a)
  ${{ if ne(variables['var-a'], exists_and_is_set) }}:
    namespaceName: $(var-b)

Basically, if variable A exists and has a value != null != '' then use it, otherwise use another variable. The scripting here is pretty simplistic and I can't find a way to do this. The reason for it is I'm making a change that out of several hundred cicd pipelines that use this template, only 10 or so will use var-a, so I'm trying to find a way to implement the logic without having to go update several hundred pipelines to include something they won't use.

scphantm
  • 4,293
  • 8
  • 43
  • 77

2 Answers2

16

You could try to use the ''to indicate non-existence or no value.

For example: eq(variables['var-a'], '')

If you use the If Expression, it may not achieve the feature you want.

Based on my test, when I use the If Expression, the value of the var-a variable will always remain non-existent or empty, even if it has been created.

So I find another method to set the variable, and it could work as expected:

Here is my example:

template: build.yml

steps:

- script: echo "##vso[task.setvariable variable=namespaceName;]$(var-a)"
  condition: ne(variables['var-a'], '')
- script: echo "##vso[task.setvariable variable=namespaceName;]$(var-b)"
  condition: eq(variables['var-a'], '')

Azure pipelines.yml

....
steps:
- template: build.yml
- script: |
    echo $(namespaceName)
  displayName: 'Run a multi-line script'

This sample use the Condition Expression and Logging command.

In this case, it will select the task to run based on the value of the variable. In the task, it will use the logging command to set the variable.

var-a: null/non-existence -> run task 2 -> namespaceName: var-b

var-a: existence -> run task 1 -> namespaceName: var-a

Kevin Lu-MSFT
  • 20,786
  • 3
  • 19
  • 28
7

Kevin Lu is correct, but here is some additional context to why it works the way it does.

The ${{ <expression> }} syntax is only evaluated at template compile time. This means that any user variables will not yet have been initialized. If you attempt to check their value, it will always return an empty value. While the ${{ <expression> }} syntax is handy to conditionally output template lines for processing, user variable values will not have been set limiting what you can do with the if.

The $[ <expression> ] syntax is evaluated at run time. Variables will have been initialized, however you can't directly use the if syntax to conditionally output a different variable value directly. You can use a cleaver hack however, as documented by Simon Alling's answer in this post.

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

This very simple YAML Pipeline illustrates the concept:

stages:
- stage: TestVarsCompile
  variables:
    - name: state_prefix
      # $subdirectory is not defined
      ${{ if eq(variables['subdirectory'], '') }}:
       value: 'subdirectory-not-set'

      # $subdirectory is defined 
      ${{ if ne(variables['subdirectory'], '') }}: 
       value: 'subdirectory-set'

  jobs:
   - job:
     steps:
     - checkout: none
     - script: |
        echo $(subdirectory)
        echo $(state_prefix)

- stage: TestVarsRuntime
  variables:
   state_prefix: $[
        replace(
          replace(
            eq(variables['subdirectory'], ''),
            True,
            'sub-directory-not-set'
          ),
          False,
          'sub-directory-set'
        )
      ]

  jobs:
   - job:
     steps:
     - checkout: none
     - script: |
        echo $(subdirectory)
        echo $(state_prefix)

The TestVarsCompile stage output always returns the following output regardless if the subdirectory variable is set or not:

some value
subdirectory-not-set

The TestVarsRuntime stage output will return the following if the subdirectory variable is set:

some value
subdirectory-set

bryanbcook
  • 16,210
  • 2
  • 40
  • 69
codechurn
  • 3,870
  • 4
  • 45
  • 65