maze
maze

Reputation: 884

Execute or not template in Azure Pipeline with runtime condition

I have got an Azure Pipeline already running. Now I want to execute a sequence of steps only if a certain condition becomes true during runtime.

Example

steps:
  - template: steps_checkout.yml
  # some more steps here

  - bash: |
    if [ some condition ]; then 
      echo "##vso[task.setVariable variable=rebuild_lib]false"
      echo "Did set rebuild_lib to false"
     fi

  - if eq( variables.rebuild_lib, true) ):
    - template: steps_lib_build.yml

The line if eq( variables.rebuild_lib, true) ) does not work, because it is not a correct condition syntax. I could use

${{ if eq( parameters.something, true ) }}

but that needs to be known at runtime. Accodring to https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops an expression can also be $[ if eq(variables.rebuild_lib), true] to be evaluated at runtime, but using this, I get

Unexpected value '$[ if eq( variables.rebuild_lib, true) ) ]'

Seems like the yml cannot be modified at runtime this way.

So how do I decide to use a template at runtime?

I could imagine giving the variable as parameter to the next template adapter.yml. This template adapter.yml gets then the variable as parameter and could use the ${{}} expression and again use the next template steps_lib_build.yml ... but creating templates only for that seems somehow ... workaroundish.

Also using something like

- template: steps_lib_build.yml
  condition: ...

does not work.

Is there a good way to do this?

Upvotes: 11

Views: 6884

Answers (2)

Felix
Felix

Reputation: 1152

In your current yaml, you are trying to use the Parameters to select a template. But according to the doc: Parameters to select a template at runtime, this is only used at runtime. So here, we can use the job conditions and output variables to help us separate the second yaml template.

Here is a demo yaml example to help you:

trigger: none

pool:
  vmImage: ubuntu-latest

jobs:
  - job: A
    steps:
    - task: Bash@3
      name: ProduceVar  # because we're going to depend on it, we need to name the step
      inputs:
        targetType: 'inline'
        script: 'echo "##vso[task.setVariable variable=rebuild_lib;isOutput=true]false"'
  - job: B
    condition: and(succeeded(), eq(dependencies.A.outputs['ProduceVar.rebuild_lib'], 'true'))
    dependsOn: A
    steps:
      # - script: echo Hello B
      - template: start.yaml

Please Note: We should use the task Bash to help us set the output variable, because we're going to depend on the task name.

Upvotes: 4

Andy
Andy

Reputation: 43

I struggled myself with this issue. From my findings, it seems that condition is not possible because it is evaluated at compile-time, whereas the variable is set at runtime.

This is the reason your dynamic variable is not available.

To find more, check Adam's article: https://adamtheautomator.com/azure-devops-variables.

The only way to make it work is to have a condition at the task/template level.

  parameters: $(rebuildLib)  # or ${{ variables.rebuildLib }}

And inside the template (steps_lib_build.yml):

- task: ...
  condition: ne('${{ parameters.rebuildLib }}', '')

Upvotes: 1

Related Questions