在 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 分支,并取消那些其他作业?
我只想取消 CI 构建作业。应忽略来自同一 Git 分支的任何 PR 构建作业和手动触发的作业,并允许继续 运行。
来自其他 Git 分支的任何构建作业也应被忽略。
Azure DevOps VM 是自托管 Windows VM,因此任务必须是 PowerShell 或 Windows 脚本,而不是 bash。 源在 Bitbucket Cloud 中 -- 这很重要,因为 ADO 处理 Bitbucket Cloud 存储库的方式与其他存储库不同。
如果有固定任务,我也可以用。
以下问题是相关的,但它们并不直接针对此用例。
- Is an Azure DevOps build pipeline, is there a way to cancel one pipeline job from another job?
您可以先使用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的值应该是
batchedCI
和individualCI
.
- statusFilter的值应该是
inProgress
,notStarted
和postponed
.
- 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
}
我如何编写一个 Azure Pipeline 脚本来检测是否有任何其他 CI 构建作业正在 运行 使用相同的 Git 分支,并取消那些其他作业?
我只想取消 CI 构建作业。应忽略来自同一 Git 分支的任何 PR 构建作业和手动触发的作业,并允许继续 运行。
来自其他 Git 分支的任何构建作业也应被忽略。
Azure DevOps VM 是自托管 Windows VM,因此任务必须是 PowerShell 或 Windows 脚本,而不是 bash。 源在 Bitbucket Cloud 中 -- 这很重要,因为 ADO 处理 Bitbucket Cloud 存储库的方式与其他存储库不同。
如果有固定任务,我也可以用。
以下问题是相关的,但它们并不直接针对此用例。
- Is an Azure DevOps build pipeline, is there a way to cancel one pipeline job from another job?
您可以先使用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的值应该是
batchedCI
和individualCI
. - statusFilter的值应该是
inProgress
,notStarted
和postponed
. - 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
}