在 Azure Devops 管道中,如何检测和取消来自同一 Git 分支的其他构建作业?

In an Azure Devops pipeline, how can I detect and cancel other build jobs from the same Git branch?

我如何编写一个 Azure Pipeline 脚本来检测是否有任何其他 CI 构建作业正在 运行 使用相同的 Git 分支,并取消那些其他作业?

Azure DevOps VM 是自托管 Windows VM,因此任务必须是 PowerShell 或 Windows 脚本,而不是 bash。 源在 Bitbucket Cloud 中 -- 这很重要,因为 ADO 处理 Bitbucket Cloud 存储库的方式与其他存储库不同。

如果有固定任务,我也可以用。

以下问题是相关的,但它们并不直接针对此用例。

您可以先使用API“Builds - List”列出所有已触发但未完成的构建。

GET https://dev.azure.com/{organization}/{project}/_apis/build/builds?reasonFilter={reasonFilter}&statusFilter={statusFilter}&branchName={branchName}&repositoryId={repositoryId}&api-version=6.0

对于你的情况,

  • reasonFilter的值应该是batchedCIindividualCI.
  • statusFilter的值应该是inProgress,notStartedpostponed.
  • branchName的值为您指定的分支。
  • repositoryId 的值是您的 Git 存储库的 ID。

然后使用API“Builds - Update Build”循环取消所有构建(当前构建除外)。

您可以将 powershell 脚本步骤添加到构建定义中,以检查同一分支上的活动构建。举个例子

$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 
        }
    }
}

@Shamrai-Alexsandr的回答取消了当前构建,但我想做的是取消所有其他仍在进行中的构建(即CI在当前分支上构建)。

@bright-ran-msft 的回答给了我足够的线索将@bright 的解决方案与@shamrai 的解决方案结合起来,将 exit 1 替换为取消其他构建的代码:

        if ($buildId -gt $bid) 
        {
            $build.status = "Cancelling"
            $cancelRequest = $build | ConvertTo-Json -Depth 10
            $uriCancel = "$orgUrl$teamProject/_apis/build/builds/$($build.id)?api-version=6.0"
            $resultOfCancel = Invoke-RestMethod -Uri $uriCancel -Method Patch -ContentType "application/json" -body $cancelRequest -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}
            Write-Host "Result of Cancel request: " $resultOfCancel.status
        }