【问题标题】:VSTS - Is there a way to only run a task if a specific task has failed?VSTS - 有没有办法只在特定任务失败时才运行任务?
【发布时间】:2018-09-13 10:55:02
【问题描述】:

我需要在我的构建定义中运行一个发布任务,但前提是它之前的某个任务失败了。如果其他任务通过,我希望它被忽略而不运行。

有没有办法做到这一点?

我希望我可以根据任务成功设置输出变量,然后在自定义条件下使用该变量在任务失败时运行任务。

如果任务失败,我看不到如何设置输出变量。这可能吗?

【问题讨论】:

    标签: azure-devops


    【解决方案1】:
    • 在任务设置中展开“控制选项”
    • 在“运行此任务”中选择 - Only when a previous task has failed

    如果您只想在最后一个/特定任务失败时运行该任务:

    假设您的特定任务(您检查的关于其状态的任务)称为A。目标是仅在 A 失败的情况下调用另一个构建任务(比如说B)。

    • 定义一个custom build variable,称它为task.A.status并设置为success
    • 创建另一个构建任务,例如C 并安排在 A 之后;将其设置为仅在 A 失败时运行 - 有一个标准条件
    • 任务 C 应该只做一件事 - 将 task.A.status 构建变量设置为“失败”(就像这样,如果我们使用 PowerShell:Write-Host "##vso[task.setvariable variable=task.A.status]failure"
    • 最后,任务B被安排在Cis conditioned之后的某个时间运行,以防task.A.status等于failure,就像这样:eq(variables['task.A.status'], 'failure')

    【讨论】:

    • 如果之前的任何任务失败,它就会运行它。这个新任务只有在特定任务之前失败时才能运行。
    • 完美 - 应该这样做。我想我必须使用任务 C 的选项,因为我正在运行的任务不是 powershell 任务。虽然在可能失败的任务之后直接执行任务,但很容易排序。
    • 嘿,如果A 失败,运行任务C 的条件是什么?你说的具体情况是什么?我看到了检查Only when a previous task has failed 的选项。所以它可以是C 以上的任何任务,而不仅仅是A
    • @MehulParmar 你需要选择“自定义条件”
    • @ShaykiAbramczyk 似乎没有任何标准功能可用于检查 previous 任务是否失败,即使使用“自定义条件”也是如此。不确定这个答案是否有效。
    【解决方案2】:

    您可以使用构建 REST API 通过 PowerShell 检查以前的任务,例如检查 taskA(显示名称)并在 taskA 失败时运行 taskB:

    1. 检查阶段中的Allow scripts to access the OAuth token 选项
    2. 添加 PowerShell 任务(运行此任务:Only when a previous task has failed;参数:-targetTaskName "taskA" -collectionURL $(Build.Repository.Uri) -projectName $(System.TeamProject) -buildId $(Build.BuildId) -token $(System.AccessToken)

    代码:

    param(
        [string]$token,
            [string]$targetTaskName,
            [string]$collectionURL,
            [string]$projectName,
            [string]$buildId
        )
        $buildTimelineREST="$collectionURL$projectName/_apis/build/builds/$buildId/Timeline?api-version=4.1"
        $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "test",$token)))
        $result= Invoke-RestMethod -Method GET -Uri $buildTimelineREST -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}
        $targetTask=$result.records | where { $_.Name -eq $targetTaskName }
        Write-Host $targetTask.result
        if($targetTask.result -eq "failed"){
            Write-Host "##vso[task.setvariable variable=isTaskAFailed;]true"
        }
    
    1. taskB(运行此任务:Custom conditions;自定义条件:eq(variables['isTaskAFailed'],'true'

    【讨论】:

    • 您好,这个方法还有效吗?发送请求时出现错误。
    【解决方案3】:

    除了starian chen-MSFT 的代码,它适用于构建管道,下面是我为发布管道收集的代码(以防它对任何人有用)。这将输出一个管道变量“deploymentStatus”,它等于任务的状态(由 Azure DevOps 定义:https://docs.microsoft.com/en-us/rest/api/azure/devops/release/releases/get%20release?view=azure-devops-rest-5.1#taskstatus):

    $targetTaskName = "Some Task Name"
    $token = $env:System_AccessToken
    $releaseURL = $env:System_TeamFoundationServerUri
    $projectName = $env:System_TeamProject
    $releaseId= $env:Release_ReleaseId
    $environmentId = $env:Release_EnvironmentId
    $releaseAttemptNumber = $env:Release_AttemptNumber
    
    $releaseREST="$releaseURL$projectName/_apis/release/releases/$releaseId/environments/$environmentId/?api-version=5.1-preview.6"
    Write-Host "GET request to Azure Pipelines with URL: $releaseREST"
    $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "test",$token)))
    $result= Invoke-RestMethod -Method GET -Uri $releaseREST -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}
    
    $targetReleaseAttempt = $result.deploySteps | where { $_.attempt -eq $releaseAttemptNumber}
    $targetTask = $targetReleaseAttempt.releaseDeployPhases.deploymentJobs.tasks | where { $_.name -eq $targetTaskName }
    $targetTask
    
    $targetTaskStatus = $targetTask.status
    Write-Host "Setting variable deploymentStatus to $targetTaskStatus"
    Write-Host "##vso[task.setvariable variable=deploymentStatus;]$targetTaskStatus"
    

    【讨论】:

      【解决方案4】:

      根据@Merivale 的回答,这是对我有用的代码;

      $targetTaskName = "SomeTaskName"
      
      $pat = ":$(System.AccessToken)"
      $b  = [System.Text.Encoding]::ASCII.GetBytes($pat)
      $token = [System.Convert]::ToBase64String($b)
      
      $releaseURL="$(System.TeamFoundationServerUri)"
      $releaseId= $(Release.ReleaseId)
      $environmentId = $(Release.EnvironmentId)
      $releaseAttemptNumber = $(Release.AttemptNumber)
      
      $releaseREST_p1="$releaseURL"
      $releaseREST=$releaseREST_p1+"$(System.TeamProject)/_apis/release/releases/$releaseId/environments/$environmentId/?api-version=5.1-preview.6"
      Write-Host "GET request to Azure Pipelines with URL: $releaseREST"
      
      $result= Invoke-RestMethod -Method GET -Uri $releaseREST -ContentType "application/json" -Headers @{'Authorization' = "Basic $token"}
      
      $targetReleaseAttempt = $result.deploySteps | where { $_.attempt -eq $releaseAttemptNumber}
      $targetTask = $targetReleaseAttempt.releaseDeployPhases.deploymentJobs.tasks | where { $_.name -eq $targetTaskName }
      $targetTask
      
      $targetTaskStatus = $targetTask.status
      Write-Host "Setting variable releaseStatus to $targetTaskStatus"
      Write-Host "##vso[task.setvariable variable=releaseStatus;]$targetTaskStatus"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-09
        • 2017-09-02
        • 1970-01-01
        • 1970-01-01
        • 2022-01-25
        • 1970-01-01
        相关资源
        最近更新 更多