0
votes

We have an on-prem Azure DevOps Server 2019 inaccessible from outside.

As far as I can see right now my options are:

Trigger a build after some other build using the built-in capability:

enter image description here

There are problems with this approach:

  1. All the builds, including this one must be in the same TFS project
  2. We are forced to provide the build branch - impossible if we want to trigger after a PR validation build, which always triggers for a new branch. I guess it could be worked around by creating a garbage branch and providing an exclude filter instead. But it is lame.

Use the build complete service hook

enter image description here

There is no Azure DevOps in this list! So, I guess it is Web Hook. Now, I do not want to maintain my own web service for that, so what is going to host the hook? We cannot use Azure Functions, because our Azure DevOps Server is inaccessible from outside. I could do something convoluted where the service hook is connected to Azure Service Bus and then a periodically scheduled Azure DevOps build polls from it. When its finds the relevant item in the queue, it will do the real "buildy" logic. But it is lame, now?

Use scheduled build to poll other builds

Here I would have a build that would run periodically (every 5 mins?) and examine the build that it is supposed to run after by using the Azure DevOps REST api. Such a build would need a persistent storage to keep track of what it has seen last. (Does Azure DevOps provide persistent storage for its builds?). And it is kind of lame too.

I must be missing something obvious here. It cannot be that complicated.

EDIT 1

The Exclude branch filter requires a branch:

enter image description here

But what branch to provide there? I do not see how to work around it without a special garbage branch that nobody deletes.

EDIT 2

It turns out it is possible to type * into the branch filter:

enter image description here

So I am using it for monitoring non PR validation builds. For the PR validation builds I am excluding master. But it sucks, because it means if I queue the PR build manually for the master branch, it would not trigger my build.

EDIT 3

Just let it run for several hours. It is triggered after all the builds, except the PR builds, even though I have the exclude branch filter there:

enter image description here

EDIT 4

The build trigger does not work when the monitored build fails. While this may make sense, it should not be hard coded into the feature. I, for example, need my build to be triggered in any case, even if the monitored build fails. The name of the feature is Build Completion Trigger, not Build Success Trigger. This limitation of this feature is disappointing.

1
I would write a custom task to trigger builds which takes Build ID as a parameter and embed in your parent build as a last task to execute. - Fairoz
I do not think you would do it. It is a maintenance liability when you have many builds created by different teams. - mark

1 Answers

0
votes

About your first problem All the builds, including this one must be in the same TFS project. In the official documentation about the build completion triggers, add a build completion trigger to run your build upon the successful completion of the triggering build. You can select any other build in the same project. So this feature is designed like this.

About the build completion triggers, when an upstream component(a library, for example) changes, the downstream dependencies have to be rebuild and revalidated. But the PR validation is a pre-build for your protected branch, there is no changes in the upstream and this is why the build completion trigger not worked.

You can change the Include to Exclude without create a garbage branch, then the build completion trigger will work as expected.

As my test, there are three branches in my repo.(master, branch1, branch2) And even I set the confidition as below, the build completion trigger don't work as expected. enter image description here

This is because there are no changes on the three branches, and the conditions are not met, so the build completion trigger not work.

But when you change the type from include to exclude, whatever the branch you choose, the build completion trigger will work as expected.

So I recommand you to change Include to Exclude, and about the branch specification, You can choose a branch at will. As my test, I choose the master branch. As you can see, the pipeline is triggered as expected. enter image description here

enter image description here

Update

The above test results are based on Azure DevOps. And in Azure DevOps, the build completion feature can be executed as described above.

However, in the Azure DevOps Server 2019, no matter how it is set, this feature will not be triggered after PR validation. So I think this is a feature defect of Azure DevOps Server 2019. I recommand you to submit this error on the Developer Community for further invetigation.

About your Editor 4, there is an introduction to this feature in the official documentation, you can refer to https://docs.microsoft.com/en-us/azure/devops/pipelines/build/triggers?view=azure-devops&tabs=classic#build-completion-triggers.

If you still feel that this feature is bothering your use, you can submit a suggestion ticket in Developer Community, too.

And there is an alternative workaround. You can add a Powershell task in your PR validation build pipeline. And set the powershell script as below. This script will queue the specified pipeline.

Param(
    [string]$collectionurl = "http://{instance}/{collection}",
    [string]$project = "{projectname}",
    [string]$definitionid="{definitionid}",
    [string]$user = "{username}",
    [string]$token = "PAT token"
)

#Base64-encodes the Personal Access Token(PAT) appropriately
$base64AuthInfo= [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user, $token)))

#Get response of the build definition
$defurl = "$collectionurl/$project/_apis/build/builds/$definitionid?api-version=5.0"

$definition = Invoke-RestMethod -Uri $defurl -Method Get -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}

$json = @($definition.definition) | ConvertTo-Json -Depth 99
$js = "{'definition':$json}"
$defurl = "$collectionurl/$project/_apis/build/builds?api-version=5.0"

#Queue a build
$updatedef = Invoke-RestMethod -Uri $defurl -Method Post -Body $js -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}