是否可以在 Azure Pipelines 中 运行 a "final stage" 而不知道总共有多少个阶段?

Is it possible to run a "final stage" in Azure Pipelines without knowing how many stages there are in total?

有没有办法让阶段 运行 作为最后阶段(不包括 post-job/ 报告构建状态)?

问题是:我有一个包含未知数量元素的每个循环,每个元素都有自己的阶段。

所以我们不能只在最后阶段说“dependendOn”,因为之前的每个阶​​段都有一个在 运行 时间给出的唯一名称。

各个阶段的顺序如下:

  1. 准备

2 - n) 使用特定 docker 容器构建/编译/测试

last) 删除所有容器

目前这工作正常,有一个小问题,最后一个阶段将 运行 在 n 阶段的最后一个结束后(完成 succeededOrFailed 条件) 问题是,当最后一个 n 阶段比其他所有阶段都快时。

删除容器阶段是分开的,因为我们 运行 遇到问题,当所有 n 阶段尝试同时删除它们的容器时,docker 无法处理。

yaml 文件上的管道 运行s

Is it possible to run a “final stage” in Azure Pipelines without knowing how many stages there are in total?

答案是肯定的。

解法的主要思路是:

在最后阶段(移除所有容器),在Remove all containers之前添加一个Inline powershell任务。此任务将调用 REST API Definitions - Get 来监视当前发布管道中的所有阶段是否具有 inprocessqueue 状态。如果是,则等待 30 秒,然后再次循环,直到当前发布管道中的所有其他阶段都没有 inprocessqueue 状态。然后接下来将执行删除所有容器任务。

脚本:

例如,我使用以下脚本在 Dev 阶段添加 Inline powershell 任务:

$connectionToken="$(Your PAT here)"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
Start-sleep -Seconds 20 # In case this stage run as first stage.
$success = $false
$count = 0

do{
    try{

        $stageurl2 = "https://vsrm.dev.azure.com/{org name}/{project name}/_apis/release/deployments?definitionId={release definition ID}&deploymentStatus=inProgress&api-version=6.0"
        $stageinfo2 = (Invoke-RestMethod -Uri $stageurl2 -Method Get -UseDefaultCredential -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}) 

        $stageInProgressNum= $stageinfo2.count

        $stageurl3 = "https://vsrm.dev.azure.com/{org name}/{project name}/_apis/release/deployments?definitionId={release definition ID}&deploymentStatus=notDeployed&api-version=6.0"
        $stageinfo3 = Invoke-RestMethod -Method Get -ContentType application/json -Uri $stageurl3 -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}

        $stageInQueuedNum = $stageinfo3.count

        Write-Host "stage In Progress Num is = $stageInProgressNum"

        Write-Host "stage In Queued Num is = $stageInQueuedNum"

        if($stageInProgressNum -ne 1) {     #The value set to 1 is because the ststus of curret stage is in inProgress when this powershell scripts is executed.      
            Write-output "There is/are $stageInProgressNum Deployment In Progress, Waiting for it to finish!"
            Write-output "Next attempt in 30 seconds"
            Start-sleep -Seconds 30         
      } else {           
            Write-Host "No Current Deployment in Progress"
            if($stageInQueuedNum -ne 0) {
            write-output "There is/are $stageInQueuedNum Queued deployments"
            Write-output "Next attempt in 30 seconds"
            Start-sleep -Seconds 30
            }
            else{
            write-output "No Queued deployments, starting release"
            $success = $true     
            }     
      }
    }
    catch{
        Write-output "catch - Next attempt in 30 seconds"
        write-output "1"
        Start-sleep -Seconds 30
      # Put the start-sleep in the catch statemtnt so we
      # don't sleep if the condition is true and waste time
    }
   
    $count++
   
}until($count -eq 2000 -or $success)
if(-not($success)){exit}

测试结果:

Dev 将继续检查,直到所有其他阶段完成:

注意:需要在最新stage添加Inline powershell任务,我在stage中间添加是为了清楚显示inline powershell任务会监控整个在其他阶段完成之前发布。

更新:

I tried to convert this to Build Pipelines instead of Release Pipelines. However I couldn't find any API reference to the status of Build-Stages. The doc for stages is empty docs.microsoft.com/en-us/rest/api/azure/devops/build/… And postman doesn't want to filter on the definitions in build area

如果您想将其用于构建管道,目前没有记录的 REST API 来获取阶段状态。但是我们可以在浏览器中按 F12 然后按 select Network 来捕获请求以获得阶段结果。您可以从响应正文中捕获结果。但不同阶段的结果由不同的数字表示,即 0->未开始、1->进行中、2->完成等:

https://dev.azure.com/<YourOrgName>/LeoTest/_build/results?buildId=6522&__rt=fps&__ver=2

现在,我们可以用同样的思路来确定state的值来解决你的需求。代码我这里就不重复分享了,大家有什么问题可以私信我