Multiline expressions in Azure DevOps pipelines

For better readability, it is nice to break the lines in bigger conditions in Azure DevOps Pipeline definition, but it is not clearly documented, how it should be done exactly.

Below you will find three examples.

Conditional template inclusion

jobs:
  - job: myJob
    displayName: 'My fancy job'
    steps:
      - checkout: self

      # Do something only on main/master
      - ? ${{ if or(
                  eq(variables['Build.SourceBranchName'], 'master'),
                  eq(variables['Build.SourceBranchName'], 'main')
          ) }}
        : - template: magic-task.yaml

      # Do something only on PR
      - ${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
        - template: pr-magic-task.yaml

      ...

If we need to do this on the condition property level, then you need such construction:

stages:
- stage: myFancyStage
  displayName: 'My fancy stage'
  condition: |
    and(
      succeeded(),
      or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
    )
  pool:
    name: ubuntu-latest

${{ }} formula

Also, the construction with ${{ }} will work in the below case:

stages:
- stage: ${{ 
    coalesce(
      parameters.stageName, 
      ... (some other conditions)
    ) }}
... (other parts of the template)

Conclusion

It is not a hard thing, but I wanted to summarize it as those informations are thrown here and there. It is better to have them in one place. Keep in mind that you need to be careful with intendations and placing parts of the template in proper places.

Read more