How do I write an Azure Pipeline script that detects whether any other CI build jobs are running using the same Git branch, and cancels those other jobs?
I want to cancel only CI build jobs. Any PR build jobs and manually triggered jobs from the same Git branch should be ignored, and allowed to continue running.
Any build jobs from other Git branches should also be ignored.
The Azure DevOps VM is a self-hosted Windows VM, so the task must be a PowerShell or Windows script, not bash. The source is in Bitbucket Cloud -- this is important, because ADO handles Bitbucket Cloud repositories differently from other repositories.
If a canned task is available, I can use it as well.
The following questions are related, but they do not directly address this use case.
- Is an Azure DevOps build pipeline, is there a way to cancel one pipeline job from another job?
- Azure devops build pipeline depends on other build pipeline
CodePudding user response:
You can first use the API "Builds - List" to list all the builds which have been trigged but not completed.
GET https://dev.azure.com/{organization}/{project}/_apis/build/builds?reasonFilter={reasonFilter}&statusFilter={statusFilter}&branchName={branchName}&repositoryId={repositoryId}&api-version=6.0
For your case,
- The value of reasonFilter should be
batchedCI
andindividualCI
. - The value of statusFilter should be
inProgress
,notStarted
andpostponed
. - The value of branchName is the branch you specify.
- The value of repositoryId is the ID of your Git repository.
Then use the API "Builds - Update Build" to cancel all the builds (except the current build) in a loop.
CodePudding user response:
You can add powershell script step into your build definition to check active builds on the same branch. As an example
$user = ""
$token = "$(System.AccessToken)"
$buildDef = "$(System.DefinitionId)"
$branchName = "$(Build.SourceBranch)"
$teamProject = "$(System.TeamProject)"
$orgUrl = "$(System.CollectionUri)"
$buildId = $(Build.BuildId) -as [int]
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$uriGetActiveBuilds = "$orgUrl/$teamProject/_apis/build/builds?definitions=$buildDef&statusFilter=inProgress&branchName=$branchName&api-version=5.1"
$resultStatus = Invoke-RestMethod -Uri $uriGetActiveBuilds -Method Get -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}
if ($resultStatus.count -gt 0)
{
foreach ($build in $resultStatus.value)
{
$bid = $build.id -as [int]
if ($buildId -gt $bid) //if exists a lower value of the build id on the same branch, the current build should be stoped
{
exit 1
}
}
}