Why Azure Yaml pipeline 'Template Parameter' if-condition does not resolve correctly while comparing the numbers?

90 views Asked by At

I have a parent.yml and sub.yml as shown here:

parent.yml:

variables:
  - name: JavaVersion
    value: 21

jobs:
  - template: templates/sub.yml
    parameters:
      JavaVersion: $(JavaVersion)

sub.yml:

parameters:
  JavaVersion: ''

jobs:
  - job: UseJavaVersion
    steps:
      - ${{ if ge(parameters.JavaVersion, 21) }}:
          - task: PowerShell@2
            displayName: Set default java version to ${{ parameters.JavaVersion }}

      - ${{ else }}:
          - task: PowerShell@2
            displayName: Install java version ${{ parameters.JavaVersion }}

When I run the job then it always goes to else part. Why 'if-condition' does not evaluates to true ? What am I doing wrong or missing here ?

I tried changing the variable value in the parent.yml to '21' and also in the sub.yml if-condition to '21', it did not work.

I also found some related discussions in this github page https://github.com/microsoft/azure-pipelines-agent/issues/1749 but it did not really clarified my issue.

I expect that since variable JavaVersion has value 21 then if-condition in the sub.yml should be executed and we should see a step named as "Set default java version to ${{ parameters.JavaVersion }}".

Note: Since it always goes to else part the step display name shows the correct JavaVersion is resolved by the ${{ parameters.JavaVersion }}.

enter image description here

2

There are 2 answers

1
bryanbcook On BEST ANSWER

You're attempting to perform a conditional insertion expression using a value that is only available at runtime.

Always remember: Variables are evaluated at runtime; Parameters only exist at compile-time.

If you want to do conditional-insertion at compile-time, you need to use a compile-time value for the parameter:

# pipeline.yml
jobs:
  - template: templates/sub.yml
    parameters:
      JavaVersion: 21

If you want to use a variable, you'll have to use conditions on the tasks:

# pipeline.yml
jobs:
- template: templates/sub.yml
  parameters:
    JavaVersion: $(currentJavaVersion)
# templates/sub.yml
parameters:
- name: JavaVersion
  type: string

jobs:
- job: UseJavaVersion

  variables:
    javaVersion: ${{ parameters.JavaVersion }}
 
  steps:
  - task: PowerShell@2
    displayName: Using Java 21 or greater
    condition: and( succeeded(), ge( variables['javaVersion'], 21) )
    inputs:
      targetType: inline
      script: Write-Host "Using ${{ parameters.JavaVersion }}"

  - task: PowerShell@2
    displayName: Install java 
    condition: and( succeeded(), lt( variables['javaVersion'], 21) )
    inputs:
      targetType: inline
      script: Write-Host "Installing!"
0
GalnaGreta On

Just in addition to the previous answer, which is correct about the variables by default are only evaluated during runtime, however, by changing the syntax to ${{ variables.JavaVersion }} we can get the variable(s) to be evaluated during compile-time:

variables:
  - name: JavaVersion
    value: 21

jobs:
  - template: templates/sub.yml
    parameters:
      JavaVersion: ${{ variables.JavaVersion }}

Using this approach you would not need to use conditions in each task as with the input into the sub.yml evaluated during compile-time, your pipeline if-statements should work as intended.