Search code examples
azure-pipelinesazure-pipelines-yaml

How to pass a variable into a YAML template parameter and use it in a condition


Let's say I have the following YAML template in Azure DevOps pipeline:

parameters:
- name: filePath
  type: string

steps:
- script: |
    @echo "${{ parameters.filePath }}"

And the calling side:

variables:
- name: filePath
  value: 'my1.xml'
  readonly: true

steps:
- template: template.yml
  parameters:
    filePath: '$(filePath)'

Now I want to add a condition to the script step based on filePath parameter:

condition: and(succeeded(), ${{ eq(parameters.filePath, 'my.xml') }})

which does not work. What am I missing?


Solution

  • Revising my answer based on the updated question. You are passing a variable to a template, which is fine. Here’s how you can use it, but lots to unpack to understand why.

    A condition is a runtime expression. The following statements are equivalent:

    condition: succeeded()
    # equivalent to:
    condition: $[ succeeded() ]
    

    Variables are also only evaluated at runtime. When referencing variables, you can use “Macro syntax” $(<variable_name>). As the name “macro” implies, it’s actually a shorthand syntax for a runtime expression. The following statements are equivalent:

    value: $(<variable-name>)
    # equivalent to:
    value: $[ variables[“variable_name”] ]
    # or 
    value: $[ variables.variable_name ]
    

    As a macro is a shorthand for a runtime expression, they can’t be embedded inside another runtime expression.

    If you are passing a variable into a template parameter with the intention of using it as part of another runtime expression, the easiest method is to copy the parameter to a variable. This allows you to pass a literal, variable or another runtime expression into the template.

    Assuming a stage or job template:

    parameters:
     - name: filePath 
       type: string
    
    jobs:
     - job: jobName
       variables:
         # dereference the parameter into a variable
         filePathValue: ${{ parameters.filePath }}
       steps:
     - script: …
       condition: |
         and(
           succeeded(),
           eq(variables[“filePathValue”], “file.yml”)
         )
    

    Note: I’m explicitly suggesting this technique for stage or job templates because they support declaring variables as part of their scope. Step templates don’t have a scope that would allow you to define a variable and use it in your condition.