gitpowershellazure-devopsazure-pipelines

Prevent Pull Request builds from triggering Continuous deployment trigger Azure DevOps Server


TL;DR

We want to prevent Pull Request branch policy builds in Azure Devops from triggering releases via the Continuous deployment trigger mechanism.

Problem

We are currently users of Azure DevOps Server 2019 Version Dev17.M153.3

We are utilizing both Build and Release pipelines. When a user submits a Pull Request, we have a Branch Policy that queues a build to ensure that code compiles and any tests pass. The completion of this build triggers the Continuous deployment trigger we have configured on the Build artifact of the corresponding release - this is NOT ideal behavior for us.

Our ideal behavior is to have the Branch Policy build queued by a Pull Request NOT trigger the Continuous deployment trigger and therefore NOT queue a release. We only want to trigger a release via the Continuous deployment trigger if we MANUALLY queue a build. We never want this to happen with a branch policy build on a Pull Request.

We've tried using the Build branch filters in the Continuous deployment trigger, but have had no luck. I've tried setting this using Exclude and setting Build branch to pull/*, refs/pull/* and merge but have not had any luck with these filters, the release is still being queued.

I want to know if there is potentially a better way to handle this scenario, or if additional filters can be added to the Continuous deployment trigger to mitigate unwanted releases from being queued.


Solution

  • We've established that there is no "best solution" for this problem at the moment, below are some alternatives.

    Easy work arounds

    enter image description here


    Release variables and custom conditions (single artifact)

    If you only have a single artifact in your release, you can skip tasks on the job level by using the Build.SourceBranchName release variable:

    enter image description here

    When the variable expression resolves, if the Build.SourceBranchName variable is equal to merge it skips all following tasks:

    enter image description here


    Release variables and custom conditions (multiple artifacts)

    Finally, if you're using multiple artifacts in your release, you can still accomplish the above behavior, albeit, you need to do some extra work with a PowerShell script.

    You use a PowerShell script to look at the RELEASE_TRIGGERINGARTIFACT_ALIAS environment variable and then looks at the corresponding RELEASE_ARTIFACTS_<RELEASE_TRIGGERINGARTIFACT_ALIAS>_SOURCEBRANCHNAME variable.

    Your environment variables (visible in the Initialize Job step of a release look like the following.

    ...
    [RELEASE_ARTIFACTS_PROJECT1_SOURCEBRANCHNAME] --> [master]
    ...
    [RELEASE_ARTIFACTS_PROJECT2_SOURCEBRANCHNAME] --> [merge]
    ...
    [RELEASE_ARTIFACTS_PROJECT3_SOURCEBRANCHNAME] --> [master]
    ...
    [RELEASE_TRIGGERINGARTIFACT_ALIAS] --> [PROJECT2]
    ...
    

    This is also visible in a standard release view.

    enter image description here

    enter image description here

    Ultimately we want to see if the triggering artifact's source branch name variable is set to merge, if so I short-circuit the release and skip all following tasks via Control Options Custom conditions. This is not an ideal situation as Pull Request builds still trigger unnecessary releases, however, it prevents any actual release action from occurring.

    PowerShell task

    Below is the PowerShell I'm currently using in the very first task

    # Use the triggering artifact alias and constructing the name of the variable that will ultimately get us the source branch that triggered the release
    $SrcBranchName = "RELEASE_ARTIFACTS_$(('$(RELEASE.TRIGGERINGARTIFACT.ALIAS)' -replace '(^\s+|\s+$)','' -replace '\s+','_').ToUpper())_SOURCEBRANCHNAME"
    
    # Get the environment variable that holds the name of the source branch
    $SrcBranchName = Get-Item  env:$SrcBranchName | Select-Object -ExpandProperty Value
    Write-Host "SrcBranchName: $SrcBranchName"
    
    if ($SrcBranchName -eq "merge") {
        Write-Host "Release caused by a PR - no further steps will run."
    }
    
    # Set an environment variable with the source branch name for use in a Custom Conditions Control
    Write-Host "##vso[task.setvariable variable=TriggeringArtifactSourceBranchName;]$SrcBranchName"
    

    Custom Condition

    Then for my custom conditions in each task, I use the following which skips the task if the TriggeringArtifactSourceBranchName is set to merge.

    and(succeeded(), ne(variables['TriggeringArtifactSourceBranchName'], 'merge'))