Azure devops 如何将azure devops管道结果设置为成功,即使其中一个作业失败

Azure devops 如何将azure devops管道结果设置为成功,即使其中一个作业失败,azure-devops,azure-pipelines,Azure Devops,Azure Pipelines,我正在开发一个Azure CD YAML管道,以将CI管道的结果部署到虚拟机上。 现在,为了这篇文章的目的,稍微简化一些事情,CD管道非常简单,由一个阶段和3个作业组成: 第一个作业运行脚本来停止某种复杂的应用程序。这有时会失败 仅当第一个作业失败时,第二个作业才会运行。这使管理员有机会进行手动干预(利用内置功能)并修复第一个作业中遇到的问题。如果管理员愿意继续运行部署管道,他将恢复管道的运行 第三步是部署新版本的应用程序 以下是YAML管道的总体结构: jobs: - deployme

我正在开发一个Azure CD YAML管道,以将CI管道的结果部署到虚拟机上。 现在,为了这篇文章的目的,稍微简化一些事情,CD管道非常简单,由一个阶段和3个作业组成:

  • 第一个作业运行脚本来停止某种复杂的应用程序。这有时会失败
  • 仅当第一个作业失败时,第二个作业才会运行。这使管理员有机会进行手动干预(利用内置功能)并修复第一个作业中遇到的问题。如果管理员愿意继续运行部署管道,他将恢复管道的运行
  • 第三步是部署新版本的应用程序
以下是YAML管道的总体结构:

jobs:
  - deployment: StopApplication
    environment:
      name: 'EnvA'  # This environment is a set of virtual machines running self-hosted Azure Agents.
      resourceType: VirtualMachine
    strategy:
          rolling:
            maxParallel: 1
            deploy:
              steps:
              - task: ...
  - job: ManualIntervation
        displayName: Manual intervention to fix issue while stopping application
        pool: server
        dependsOn: StopApplication
        condition: failed()  # This job will run only if job StopApplication has failed.
        timeoutInMinutes: 60 
        steps:
        - task: ManualValidation@0
          timeoutInMinutes: 50
          inputs:
            notifyUsers:
              someone@somewhere.com
            instructions: 'Do something'
            onTimeout: 'reject'
  - deployment: DeployApp
        dependsOn:
        - StopApplication
        - ManualIntervation
        condition: xor(succeeded('StopApplication'), succeeded('ManualIntervation'))
        workspace:
          clean: all
        environment:
          name: 'EnvA'  # This environment is a set of virtual machines running self-hosted Azure Agents.
          resourceType: VirtualMachine
        strategy:
          rolling:
            maxParallel: 1
            deploy:
              steps:
              - task: ...
我遇到的问题是,如果第一个部署作业失败,但管理员检查了问题,修复了问题,恢复管道运行,并且最后一个部署作业成功,Azure DevOps会将我的管道显示为失败(DevOps门户中的红十字),我可以理解为其中一个作业失败。 然而,从功能上讲,部署成功了,因此我想设置/强制管道运行的结果为成功,以便Azure DevOps显示绿色检查

有人知道实现这一目标的方法吗?
我假设这是可能的,否则我不理解为什么我们有机会在管道中进行手动干预。

构建结果是只读的,在构建完成后无法更新。不过,您可以查看下面的解决方法,以消除Devops门户中的失败标志(红十字)

1、对作业中的任务使用
continueOnError
。例如:

jobs:
 - deployment: StopApplication
   ...
    steps:
    - task: taskName
       ...
      continueOnError: true
 - powershell: |
      
      $body = @{
                templateParameters=@{
                    ManualIntervation= "false"
                }
              }

      if("$(Agent.JobStatus)" -eq "Failed"){
          $body.templateParameters.ManualIntervation='true'
      }
      $url = "$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_apis/pipelines/{second-pipelineId}/runs?api-version=6.1-preview.1"
      $result5 = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Bearer $(system.accesstoken)"} -Method post -Body (convertto-json $body) -ContentType "application/json" 

    condition: always() #always run this task
当continueOnError属性设置为true时。任务失败时,管道的结果将设置为
SucceededWithIssues
。你将有一个感叹号而不是红十字

对于作业
ManualIntervation
,您还需要切换到
条件

然后更改job
ManualIntervation
的条件,以检查标志变量是否设置为true。见下文:

- job: ManualIntervation
  dependsOn: StopApplication
  condition: eq(dependencies.StopApplication.result, 'SucceededWithIssues')
2,另一种解决方法是将
stopplication
作业与不同管道中的其他作业分开

您需要创建两个管道。第一个管道只有
stopplication
作业。第二条管道包含其余的作业。以及使用从第一管道触发第二管道

在第一条管道中。以及失败任务后的powershell任务,用于检查作业状态并使用rest api触发第二个管道。请参见以下示例:

jobs:
 - deployment: StopApplication
   ...
    steps:
    - task: taskName
       ...
      continueOnError: true
 - powershell: |
      
      $body = @{
                templateParameters=@{
                    ManualIntervation= "false"
                }
              }

      if("$(Agent.JobStatus)" -eq "Failed"){
          $body.templateParameters.ManualIntervation='true'
      }
      $url = "$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_apis/pipelines/{second-pipelineId}/runs?api-version=6.1-preview.1"
      $result5 = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Bearer $(system.accesstoken)"} -Method post -Body (convertto-json $body) -ContentType "application/json" 

    condition: always() #always run this task
然后在第二条管道中定义一个
ManualIntervation
,并设置作业
ManualIntervation
的条件,见下文:

parameters:
- name: ManualIntervation
  type: string
  default: false
  
...

- job: ManualIntervation
  dependsOn: StopApplication
  condition: eq('${{parameters.ManualIntervation}}', 'true') 
当执行第一个管道时。powershell任务将被触发,第二条管道将通过模板参数请求正文覆盖第二条管道中的参数
ManualIntervation
。如果
ManualIntervation
为真。然后将执行手动干预作业


因此,即使第一个管道失败,第二个管道也会成功。

生成结果是只读的,在生成完成后无法更新。不过,您可以查看下面的解决方法,以消除Devops门户中的失败标志(红十字)

1、对作业中的任务使用
continueOnError
。例如:

jobs:
 - deployment: StopApplication
   ...
    steps:
    - task: taskName
       ...
      continueOnError: true
 - powershell: |
      
      $body = @{
                templateParameters=@{
                    ManualIntervation= "false"
                }
              }

      if("$(Agent.JobStatus)" -eq "Failed"){
          $body.templateParameters.ManualIntervation='true'
      }
      $url = "$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_apis/pipelines/{second-pipelineId}/runs?api-version=6.1-preview.1"
      $result5 = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Bearer $(system.accesstoken)"} -Method post -Body (convertto-json $body) -ContentType "application/json" 

    condition: always() #always run this task
当continueOnError属性设置为true时。任务失败时,管道的结果将设置为
SucceededWithIssues
。你将有一个感叹号而不是红十字

对于作业
ManualIntervation
,您还需要切换到
条件

然后更改job
ManualIntervation
的条件,以检查标志变量是否设置为true。见下文:

- job: ManualIntervation
  dependsOn: StopApplication
  condition: eq(dependencies.StopApplication.result, 'SucceededWithIssues')
2,另一种解决方法是将
stopplication
作业与不同管道中的其他作业分开

您需要创建两个管道。第一个管道只有
stopplication
作业。第二条管道包含其余的作业。以及使用从第一管道触发第二管道

在第一条管道中。以及失败任务后的powershell任务,用于检查作业状态并使用rest api触发第二个管道。请参见以下示例:

jobs:
 - deployment: StopApplication
   ...
    steps:
    - task: taskName
       ...
      continueOnError: true
 - powershell: |
      
      $body = @{
                templateParameters=@{
                    ManualIntervation= "false"
                }
              }

      if("$(Agent.JobStatus)" -eq "Failed"){
          $body.templateParameters.ManualIntervation='true'
      }
      $url = "$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_apis/pipelines/{second-pipelineId}/runs?api-version=6.1-preview.1"
      $result5 = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Bearer $(system.accesstoken)"} -Method post -Body (convertto-json $body) -ContentType "application/json" 

    condition: always() #always run this task
然后在第二条管道中定义一个
ManualIntervation
,并设置作业
ManualIntervation
的条件,见下文:

parameters:
- name: ManualIntervation
  type: string
  default: false
  
...

- job: ManualIntervation
  dependsOn: StopApplication
  condition: eq('${{parameters.ManualIntervation}}', 'true') 
当执行第一个管道时。powershell任务将被触发,第二条管道将通过模板参数请求正文覆盖第二条管道中的参数
ManualIntervation
。如果
ManualIntervation
为真。然后将执行手动干预作业


这样,即使第一条管道失败,第二条管道也会成功。

您好,感谢您的宝贵意见。有点奇怪的是,虽然我们可以在管道中进行手动干预,但我们无法设置管道运行状态。你认为这是一个有价值的新功能吗?我想我们需要重新考虑我们的管道执行方法,因为如果没有明确的结果(失败或成功),只会给操作人员留下解释和困惑的空间,因为他们想知道什么软件实际部署在哪里。另一方面(并且为了潜在读者的利益),在第一个解决方案中,一个改进可以是在手动干预作业的条件下直接使用StopApplication作业状态。这使得创建变量的经济性更高。条件