Azure DevOps多阶段流水线等待批准而停滞不前

5
我正在使用托管Azure DevOps并在Azure Git Repos中存储代码。我们曾经使用“Classic”基于UI的流水线编辑器,但现在将构建/发布阶段的工作移至YAML模板。
以前,我配置了CI/CD,当通过拉取请求将代码提交到主分支时,它会触发构建,然后进行开发环境部署。其他发布阶段将在代码移动到该阶段之前等待批准。新版本将取消尚未部署到各自环境的任何以前的版本。
使用YAML部署阶段时,我发现当主分支触发构建时,它会部署到开发环境,但是流水线会停留在等待状态,因为其他阶段尚未获得批准。因此,运行不会被标记为“完成”,最终,其他阶段将超时并标记为失败。此外,之前的流水线运行未被取消,因此多个运行堆积在等待状态中。
理想情况下,如果有一个新构建,它应该取消所有先前的流水线运行。我希望看到在部署到开发环境后,运行被标记为“完成”,并且可以在事后手动部署到其他阶段。
还有其他人想要做同样的事情吗?我是不是想错了,应该用不同的方式来做?
1个回答

1

目前在yaml管道中不支持手动部署到阶段。请查看开放问题

您可以尝试为每个阶段添加dependsOncondition。对于下面的示例yaml管道,只有在阶段Start成功完成后,阶段Build才会开始运行,然后阶段Build将等待批准,只有在阶段Build得到批准并成功完成后,阶段Release才会被触发。

您可以定义pr trigger并设置autocancel=true(默认为true),以取消先前运行,如果新更改已推送到同一pr。

triggerbatch 属性可以实现类似的效果。如果当前的 pr 仍在构建中,它将不会启动新的运行。

trigger:
  batch: boolean # batch changes if true (the default); start a new build for every push if false
  branches:
    include:

_

pr:
  autoCancel: true
  branches:
    include:
    - master

stages:
- stage: Start
  jobs:
    - job: A
      pool:
        vmImage: windows-latest
      steps:
      - powershell: |
          echo "i am job a"

- stage: Build
  dependsOn: Start
  condition: succeeded()
  jobs:
  - deployment: Dev
    displayName: deploy Web App
    pool:
      vmImage: 'Ubuntu-16.04'
  # creates an environment if it doesn't exist
    environment: 'Dev'
    strategy:
    # default deployment strategy, more coming...
      runOnce:
        deploy:
          steps:
          - script: echo "i am dev environment"


- stage: Release
  dependsOn: Build
  condition: succeeded()
  jobs:
  - deployment: Environ
    displayName: deploy Web App
    pool:
      vmImage: 'Ubuntu-16.04'
  # creates an environment if it doesn't exist
    environment: 'Environment'
    strategy:
    # default deployment strategy, more coming...
      runOnce:
        deploy:
          steps:
          - script: echo "i am Environment environment"

更新: 通过powershell脚本取消正在进行的构建

您可以在管道顶部添加一个powershell任务来调用构建API。以下脚本获取所有正在进行的构建并取消它们,但保留当前构建。

- task: PowerShell@2

      inputs:
        targetType: inline
        script: |

          $header = @{ Authorization = "Bearer $(system.accesstoken)" }
          $buildsUrl = "$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_apis/build/builds?api-version=5.1"
          echo $buildsUrl
          $builds = Invoke-RestMethod -Uri $buildsUrl -Method Get -Header $header

          $buildsToStop = $builds.value.Where({ ($_.status -eq 'inProgress') -and ($_.definition.name -eq "$(Build.DefinitionName)") -and ($_.id -ne $(Build.BuildId))})

          ForEach($build in $buildsToStop)
          {
            echo $build.id
            $build.status = "cancelling"
            $body = $build | ConvertTo-Json -Depth 10
            $urlToCancel = "$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_apis/build/builds/$($build.id)?api-version=5.1"
            echo $urlToCancel
            Invoke-RestMethod -Uri $urlToCancel -Method Patch -ContentType application/json -Body $body -Header $header
          }

为了让您的流水线有权限取消当前正在运行的构建。您需要进入您的流水线,单击3个点,并选择“管理安全性”。

enter image description here

然后将用户 Project Collection Build Service(projectName)停止构建 权限设置为允许。

enter image description here


1
目前我的各个阶段之间存在依赖关系。开发阶段依赖于构建阶段,而测试阶段则依赖于开发阶段。测试阶段已经设置了批准流程,但开发阶段并没有。因此,每次合并 PR 时,它会部署到开发环境中,但必须等待测试阶段的批准。由于 PR 经常发生,这导致许多流水线运行等待批准。它们从不自动取消,并最终超时。此外,我发现代码覆盖率选项卡从未显示,因为运行从未标记为完成。 - Frank Hoffman
你可以尝试在触发器中使用批量属性,或者使用PR触发器。我已经更新了上面的答案。 - Levi Lu-MSFT
我不确定这是否完全符合我的要求。对于PR触发器(不适用于Azure Repos选项),它仅取消同一PR之前运行的任务。批处理选项(默认为true)似乎只是减少运行次数,但不会取消所有先前的运行任务。 - Frank Hoffman
这接近我的需求了,但似乎没有找到与 where 子句匹配的构建。部分原因是我对语法缺乏经验。我进行了一些调试,发现 $buildsToStop 似乎为空。我还需要在 '$(Build.DefinitionName)' 周围添加引号。你能否在示例管道上运行成功?我不确定缺少什么。我尝试将 where 子句更改为仅包括定义名称而不包括其他条件,但似乎仍然为空。 - Frank Hoffman
非常感谢您在此事上的帮助。这是非常有用的信息,已经实现了我想要的目标!您赢得了点赞 :) - Frank Hoffman
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接