能否通过编程取消 Azure DevOps 管道作业?

19

在 Azure DevOps 管道中,可以停止单个步骤:

echo "##vso[task.complete result=Succeeded;]DONE"

请参阅:https://github.com/microsoft/azure-pipelines-tasks/blob/master/docs/authoring/commands.md#task-logging-commands

另外,是否可以检查某个条件,并根据此条件停止整个管道运行或作业运行?

附注:我知道您可以为作业设置条件,但在我的情况下,整个管道是单个作业,因为其他原因,将其拆分为多个作业没有意义。


同意Krzysztof Madej的观点。这里有一些额外的信息。1.如果您使用Rest Api取消构建,则管道状态将被标记为“已取消”。2.由于您不想添加代码,因此可以向每个任务添加条件。在这种情况下,管道将运行并标记为“成功”,但所有任务都将被跳过。您可以参考此票证 - Kevin Lu-MSFT
@KevinLu-MSFT。我以前就知道这种解决方案。那确实在某种程度上解决了问题,但我看到还没有优雅的解决方式。 - Matthias
2个回答

35

你可以通过REST API取消构建:

PATCH https://dev.azure.com/atbagga/atbagga/_apis/build/Builds/120
Request content: {'status': 'Cancelling'}

这里有一个例子:

steps:
- task: PowerShell@2
  name: ConditionalStep
  inputs:
    targetType: 'inline'
    script: |
      Write-Host "I'm here"
      Write-Host ('$(SomeVariable)' -eq 'Stop')
      if ('$(SomeVariable)' -eq 'Stop') {
        $uri = "https://dev.azure.com/thecodemanual/DevOps Manual/_apis/build/builds/$(Build.BuildId)?api-version=5.1"

        $json = @{status="Cancelling"} | ConvertTo-Json -Compress

        $build = Invoke-RestMethod -Uri $uri -Method Patch -Headers @{Authorization = "Bearer $(System.AccessToken)"} -ContentType "application/json" -Body $json

        Write-Host $build
      }
      Write-Host "And now here!"
    pwsh: true
- pwsh: Start-Sleep -Seconds 60    
- task: PowerShell@2
  inputs:
    targetType: 'inline'
    script: |
      $uri = "https://dev.azure.com/thecodemanual/DevOps Manual/_apis/build/builds/$(Build.BuildId)/timeline?api-version=5.1"

      Write-Host $uri

      # Invoke the REST call
      $build = Invoke-RestMethod -Uri $uri -Method Get -Headers @{Authorization = "Bearer $(System.AccessToken)"} -ContentType "application/json"

      $taskResult = $build.records | Where-Object {$_.name -eq "ConditionalStep" } | Select-Object result

      Write-Host $taskResult.result

    pwsh: true

您将获得以下输出:

enter image description here

如果您遇到以下错误:

 | {"$id":"1","innerException":null,"message":"Access denied.
 | DevOps Manual Build Service (thecodemanual) needs Stop builds
 | permissions for vstfs:///Build/Build/1611 in team project
 | DevOps Manual to perform the
 | action.","typeName":"Microsoft.TeamFoundation.Build.WebApi.AccessDeniedException, Microsoft.TeamFoundation.Build2.WebApi","typeKey":"AccessDeniedException","errorCode":0,"eventId":3000}
请确保您的构建账户有停止构建的权限:
您可以在以下部分找到此选项:

enter image description here

enter image description here

请注意

您不能将构建设置为已完成。如果您这样做,整个流水线仍将被执行。因此,如果这不是您想要的,请在先前在流水线中设置输出变量的每个步骤中添加条件,并以这种方式忽略这些步骤。

steps:
- task: PowerShell@2
  name: ConditionalStep
  inputs:
    targetType: 'inline'
    script: |
      Write-Host "I'm here"
      Write-Host ('$(SomeVariable)' -eq 'Stop')
      if ('$(SomeVariable)' -eq 'Stop') {
        Write-Host '##vso[task.setvariable variable=shouldStop;isOutput=true]Yes'
      }
      Write-Host "And now here!"
    pwsh: true
- pwsh: Start-Sleep -Seconds 60
  condition: ne(variables['ConditionalStep.shouldStop'], 'Yes')
- task: PowerShell@2
  condition: ne(variables['ConditionalStep.shouldStop'], 'Yes')
  inputs:
    targetType: 'inline'
    script: |
      $uri = "https://dev.azure.com/thecodemanual/DevOps Manual/_apis/build/builds/$(Build.BuildId)/timeline?api-version=5.1"

      Write-Host $uri

      # Invoke the REST call
      $build = Invoke-RestMethod -Uri $uri -Method Get -Headers @{Authorization = "Bearer $(System.AccessToken)"} -ContentType "application/json"

      $taskResult = $build.records | Where-Object {$_.name -eq "ConditionalStep" } | Select-Object result

      Write-Host $taskResult.result

    pwsh: true

1
谢谢您的回复! 嗯,我认为这不是一个令人满意的解决方案:如果条件未满足,则不应将管道标记为失败,并且我不想在每个后续步骤中添加额外的代码。 - Matthias
欢迎。你能否检查一下这是否符合您的要求? - Krzysztof Madej
@Matthias,如果我的回复对您有帮助,您能否考虑给我点个赞呢? - Krzysztof Madej

1

使用Python脚本和管道内的REST API取消管道有不同的方法。

       - task: PythonScript@0
         inputs:
            scriptSource: 'inline'
            script: |
              import requests
              import json
              import base64

              pat = 'your personal token access'
              authorization = str(base64.b64encode(bytes(':'+pat, 'ascii')), 'ascii')

              # Returns a JSON - serializable representation of the pipeline.
              def get_builds():
                  url_pipeline = "https://dev.azure.com/{Organisation}/{Project}/_apis/pipelines/{definitionId}/runs?api-version=6.0-preview.1"
                  headers = {
                      'Authorization': 'Basic '+authorization,
                      'Content-Type': 'application/json',
                  }
                  response = requests.request("GET", url_pipeline, headers=headers)
                  json_data = response.json()
                  with open("data.json", "w") as outfile:
                      json.dump(json_data, outfile)
              get_builds()

              # Get buildId from data. json file
              def get_buildId():
                  with open('data.json') as json_file:
                      data = json.load(json_file)
                      buildId = data['value'][0]['id']
                      print(buildId)
                      return buildId
              get_buildId()

              # Cancel a build pipeline by buildId and pipelineId.
              def cancel_build():
                url = "https://dev.azure.com/{Organisation}/{Project}/_apis/build/builds/"+str(get_buildId())+"?api-version=6.0"
                payload = json.dumps({
                    "status": "Cancelling"
                })
                headers = {
                    'Authorization': 'Basic '+authorization,
                    'Content-Type': 'application/json',
                }
                requests.request("PATCH", url, headers=headers, data=payload)
              cancel_build()

在任务pythonScript执行后,您需要添加另一个任务来安装库requests

       - task: AzureCLI@2
         displayName: 'install required libraries'
         inputs:
           azureSubscription: '$(AZURE_RM_SVC_CONNECTION)'
           scriptType: ps
           scriptLocation: inlineScript
           inlineScript: |
             pip install requests

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