Search code examples
azure-devopsazure-pipelinesazure-pipelines-yaml

Why are my conditions not working as expected in Azure DevOps YAML Pipelines when using conditions based on a dynamic variable?


I'm creating a YAML release script for Azure DevOps. I'm still testing how to differentiate between a manual trigger/other pipeline trigger and a trigger coming from a webhook and how to conditionally execute some other logic (f.e. different approvals, ...).

Currently I have the following YAML:

trigger: none
resources:
  pipelines:
  - pipeline: buildPipeline
    source: 'POC - Build'
    trigger:
      branches:
        include:
        - develop
  webhooks:
    - webhook: Trigger
      connection: Connection
      filters:
        - path: ReleaseName
          value: Plugins

variables:
  - name: isAutomatedTrigger
    value: $[
              and(
                eq(variables['Build.reason'], 'ResourceTrigger'),
                eq(variables['resources.triggeringAlias'], 'KristaDeploymentTrigger')
              )
            ]

stages:
  - stage: Test
    jobs:
    - job:
      steps:
      - checkout: none
      - ${{if eq(variables.isAutomatedTrigger, True)}}:
        - script: echo 'This is an automated trigger'
      - ${{else}}:
        - script: echo 'This is not an automated trigger'

When I execute the script starting it manually in DevOps, DevOps shows me the isAutomatedTrigger parameter evaluates to False. When i start the script using the webhook, DevOps shows me the parameter evaluates to true.

However in both situations the text 'This is not an automated trigger' is printed.

I tried different spellings of True, true, 'True', ...

I tried not using the eq (just if(variables.isAutomatedTrigger), ... but nothing helps. I also tried the different variable notation: variables['isAutomatedTrigger'].

Sometimes the result switches: both the manual and webhook trigger of the pipeline result in 'This is an automated trigger' but never do they behave like intended, even if the parameter always evalaates correctly


Solution

  • According to the Resources schema, when a resource triggers a pipeline, the following variables get set:

    resources.triggeringAlias
    resources.triggeringCategory
    

    The variable Build.Reason must be ResourceTrigger for these values to get set. The values are empty if a resource didn't trigger the pipeline run. These variables are available to your pipeline only at runtime.

    Therefore, we can only evaluate such resources variables in runtime expressions rather than in compilie time template expressions such as the conditional insertions (${{if}}), which are processed at compile time before runtime.

    In addition to the clear and explicit answer by @RUI, the variable $(resources.triggeringAlias) will be expanded as the symbolic name of the triggering resource, that is buildPipeline or Trigger given your sample; and we don't need to evalute if $(Build.Reason) is ResourceTrigger, when the $(resources.triggeringAlias) is not empty.

    Here is a sample YAML pipeline for your reference.

    trigger: none
    resources:
      pipelines:
      - pipeline: buildPipeline
        source: 'POC - Build'
        trigger:
          branches:
            include:
            - develop
      webhooks:
        - webhook: Trigger
          connection: Connection
          filters:
            - path: ReleaseName
              value: Plugins
    
    variables:
      - name: isAutomatedTrigger
        value: $[
                  and(
                    eq(variables['Build.Reason'], 'ResourceTrigger'),
                    eq(variables['resources.triggeringAlias'], 'buildPipeline')
                  )
                ]
    
    stages:
      - stage: Test
        jobs:
        - job:
          steps:
          - checkout: none
          - script: |
              echo "================ This is an automated trigger by resource ================"
              echo "Build.Reason is $(Build.Reason)"
              echo "triggeringAlias is $(resources.triggeringAlias)"
              echo "resources.triggeringCategory is $(resources.triggeringCategory)"
    
              echo "================ Is Automated Trigger? - $(isAutomatedTrigger) ================"
            condition: or(
                          eq(variables['resources.triggeringAlias'], 'buildPipeline'),
                          eq(variables['resources.triggeringAlias'], 'Trigger')
                        )
          - script: echo 'This is not an automated trigger'
            condition: eq(variables['resources.triggeringAlias'], '')
    
    

    Image