goosseno
goosseno

Reputation: 175

Azure YAML pipelines conditional insertion doesn't work

Consider the following pipeline snippet, this is part of a template.

- task: Bash@3
  inputs:
    targetType: 'inline'
    script: |
      echo "##vso[task.setvariable variable=AppType;]WebJob"
      echo "##[debug] AppType set to WebJob"

# This works, using the task condition
- task: DotNetCoreCLI@2
  condition: eq(variables['AppType'], 'WebJob')
  displayName: 'net publish for WebJob'
  inputs:
    command: 'publish'

# This doesn't work, using the conditional insertion, index syntax
- ${{ if eq(variables['AppType'], 'WebJob') }}:
  - task: DotNetCoreCLI@2
    displayName: 'net publish for WebJob'
    inputs:
      command: 'publish'

# This also doesn't work, using the conditional insertion, property dereference syntax
- ${{ if eq(variables.AppType, 'WebJob') }}:
  - task: DotNetCoreCLI@2
    displayName: 'net publish for WebJob'
    inputs:
      command: 'publish'

Why the task condition works but the conditional insertion doesn't? With the 2nd I don't get any error, the task is just not there, like the if condition is not met.

Upvotes: 5

Views: 3836

Answers (4)

Ryan Thomas
Ryan Thomas

Reputation: 479

I had been hoping to set a variable at the bottom of a template at runtime and use a conditional include at the top prevent portions of the template from being included again later...

But the compile time limitation that Leo Liu pointed out was preventing me from doing so. The closest I could get was by doing this with a parameter:

# some-template.yml
parameters:
- name: firstParameter
  type: string
  default: ''
- name: hasAlreadyBeenRun
  type: boolean
  default: false

steps:
- ${{ if ne(parameters.hasAlreadyBeenRun, true) }}:
  - task1 that only needs run once
  - task2 that only needs run once
  - task3 that only needs run once
- task to repeat
# consuming-definition.yml
steps:
- ${{ if eq(someCondition1, true) }}:
  - template 'some-template.yml'
  - some task 1
- ${{ if eq(someCondition2, true) }}:
  - some task 2
  - some task 3
- ${{ if eq(someCondition3, true) }}:
  - template 'some-template.yml'
    parameters:
      hasAlreadyBeenRun: ${{ eq(someCondition1, true) }}
  - some task 4
- ${{ if eq(someCondition4, true) }}:
  - template 'some-template.yml'
    parameters:
      hasAlreadyBeenRun: ${{ or(eq(someCondition1, true), eq(someCondition3, true)) }}
  - some task 5

Upvotes: 0

iman ansari
iman ansari

Reputation: 103

I have tested your condition on a pipeline and change it like this and it's worked correctly. you should change condition syntax and everything will be correct.

- task: Bash@3
  inputs:
   targetType: 'inline'
   script: |
     echo "##vso[task.setvariable variable=AppType;]WebJob"
     echo "##[debug] AppType set to WebJob"
- task: CmdLine@2
  inputs:
    script: echo Key:'$(AppType)' 
# This doesn't work, using the conditional insertion, index syntax
  ${{ if eq(variables['AppType'], 'WebJob') }}:
- task: CmdLine@2
  inputs:
    script: echo Key:'$(AppType)'
# This also doesn't work, using the conditional insertion, property dereference syntax
  ${{ if eq(variables.AppType, 'WebJob') }}:
- task: CmdLine@2
  inputs:
    script: echo Key:'$(AppType)'

I recommend you try the visual studio code and an extension or any ide to correct your YAML file.

Upvotes: 0

Leo Liu
Leo Liu

Reputation: 76660

Azure YAML pipelines conditional insertion doesn't work

As we know, the syntax ${{}} for compile time:

Expressions

# Note the syntax ${{}} for compile time and $[] for runtime expressions.

So, when we execute the pipeline, the conditional insertion ${{ if eq(variables['AppType'], 'WebJob') }} has already been evaluated, however, the Bash task has not been run, the value of AppType would be always null. That the reason why the conditional insertion does not work.

To resolve this issue, we could define the variable directly:

 variables:
   AppType: WebJob

Or we could define the Runtime parameters:

parameters:
  - name: AppType
    displayName: AppType
    default: WebJob

Upvotes: 5

jessehouwing
jessehouwing

Reputation: 114461

The ${{}} syntax is evaluated at template compile time, not during execution, so the task will be removed from the workflow when the job is being setup as the variable doesn't exist yet, it doesn't wait until it actually needs to run the task to evaluate the condition.

You can use the $[] conditional syntax for runtime evaluation, or rely on the condition:syntax.

From the docs:

# Two examples of expressions used to define variables
# The first one, a, is evaluated when the YAML file is compiled into a plan.
# The second one, b, is evaluated at runtime.
# Note the syntax ${{}} for compile time and $[] for runtime expressions.
variables:
  a: ${{ <expression> }}
  b: $[ <expression> ]

See:

Upvotes: 2

Related Questions