任务控制选项-自定义条件-前一个失败或超时时运行任务

时间:2020-03-23 18:04:24

标签: azure-devops azure-pipelines azure-pipelines-tasks azure-pipelines-yaml

是否有一个选项可以设置自定义条件,该条件将测试上一个任务是否失败或超时?

当前,我使用的是mappings,它在任务失败时起作用。如果任务超时,则不会将其视为错误,而是将其跳过。

那么我需要一个自定义条件,例如Only when a previous task has failed。有可能吗?

上下文

我们在or(failed(), timedout())任务中遇到这个间歇性问题,我们找不到原因,但是在下一次运行作业时就解决了,因此我们正在寻找重试功能。部分解决方案是复制npm install并使用“控制选项”,但不适用于所有“失败”情况。 @Levi Lu-MSFT提供的解决方案似乎可以满足我们的所有需求(确实可以重试),但可惜的是它不能解决问题,第二行重复任务也失败了。

示例错误:

npm install

20741 error   stack: 'Error: EPERM: operation not permitted, unlink \'C:\\agent2\\_work\\4\\s\\node_modules\\.staging\\typescript-4440ace9\\lib\\tsc.js\'',
20741 error   errno: -4048,
20741 error   code: 'EPERM',
20741 error   syscall: 'unlink',
20741 error   path: 'C:\\agent2\\_work\\4\\s\\node_modules\\.staging\\typescript-4440ace9\\lib\\tsc.js',
20741 error   parent: 's' }
20742 error The operation was rejected by your operating system.
20742 error It's possible that the file was already in use (by a text editor or antivirus),
20742 error or that you lack permissions to access it.

有时也会超时

2 个答案:

答案 0 :(得分:3)

可以添加自定义条件。如果希望在上一个任务失败或跳过时执行该任务,则可以使用自定义条件not(succeeded())

enter image description here

但是,上述自定义条件存在问题,它在多任务方案中不起作用。

例如,有三个任务A,B,C。预期的行为是仅当任务B失败时才执行任务C。但是实际的行为是,即使任务B成功执行,当任务A失败时,任务C也会被执行。检查以下屏幕截图。

enter image description here

上述问题的解决方法是添加脚本任务以调用azure devops restful api以获取任务B的状态,并使用此表达式echo "##vso[task.setvariable variable=taskStatus]taskStatus"将其设置为变量。

对于下面的示例,在任务C在以下内联脚本下运行之前,添加一个powershell任务(您需要将此任务的条件设置为Even if a previous task has failed, even if the build was canceled才能始终运行此powershell任务):

$url = "$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/timeline?api-version=5.1"

$result = Invoke-RestMethod -Uri $url -Headers @{authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"} -ContentType "application/json" -Method get

#Get the task B's task result  
$taskResult = $result.records | where {$_.name -eq "B"} | select result  

#set the Task B's taskResult to variable taskStatus
echo "##vso[task.setvariable variable=taskStatus]$($taskResult.result)" 

为了使上述脚本可以访问访问令牌,还需要单击“代理”作业并选中选项Allow scripts to access the OAuth token。请参阅下面的屏幕截图。

enter image description here

最后,您可以对任务C使用自定义条件and(not(canceled()), ne(variables.taskStatus, 'succeeded'))。仅当任务B不成功时才应执行任务C。

enter image description here

答案 1 :(得分:1)

尽管我找不到内置函数来检测构建步骤是否超时,但是您可以尝试在变量的帮助下进行仿真。

考虑以下YAML管道声明:

steps:
- script: |
    echo Hello from the first task!
    sleep 90
    echo "##vso[task.setvariable variable=timedOut]false"
  timeoutInMinutes: 1
  displayName: 'A'
  continueOnError: true

- script: echo Previous task has failed or timed out!
  displayName: 'B'
  condition: or(failed(), ne(variables.timedOut, 'false'))

第一个任务(A)设置为1分钟后超时,但是其中的脚本将长时间运行的任务(sleep 90)模拟了1.5分钟。结果,任务超时,并且timedOut变量被设置为false。因此,任务B的条件评估为true并执行。如果将sleep 90替换为exit 1以模拟任务A失败,也会发生同样的情况。

另一方面,如果任务A成功,则任务B的条件部分都不为真,整个任务B被跳过。

这是一个非常简化的示例,但是它演示了可以进一步调整以满足管道需求的想法。