任务控制选项 - 自定义条件 - 运行 之前失败或超时的任务
Task Control Option - Custom Condition - run task when previous failed or timed out
是否有选项可以设置自定义条件来测试上一个任务是否失败或超时?
目前,我正在使用 Only when a previous task has failed
,它在任务失败时起作用。如果任务超时,则不会将其视为错误并被跳过。
然后我需要一个自定义条件,比如 or(failed(), timedout())
。可能吗?
上下文
我们在 npm install
任务中遇到了这个间歇性问题,我们找不到原因,但下一个作业 运行 解决了这个问题,所以我们正在寻找重试功能。部分解决方案是复制 npm install
并使用控制选项,但它不适用于所有 "failure" 情况。 @Levi Lu-MSFT 给出的解决方案似乎可以满足我们的所有需求(它会重试)但遗憾的是它没有解决问题,第二行重复任务也失败了。
错误示例:
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.
或
21518 verbose stack SyntaxError: Unexpected end of JSON input while parsing near '...ter/doc/TypeScript%20'
21518 verbose stack at JSON.parse (<anonymous>)
21518 verbose stack at parseJson (C:\agent2\_work\_tool\node.17.0\x64\node_modules\npm\node_modules\json-parse-better-errors\index.js:7:17)
21518 verbose stack at consumeBody.call.then.buffer (C:\agent2\_work\_tool\node.17.0\x64\node_modules\npm\node_modules\node-fetch-npm\src\body.js:96:50)
21518 verbose stack at <anonymous>
21518 verbose stack at process._tickCallback (internal/process/next_tick.js:189:7)
21519 verbose cwd C:\agent2\_work\s
21520 verbose Windows_NT 10.0.14393
21521 verbose argv "C:\agent2\_work\_tool\node\8.17.0\x64\node.exe" "C:\agent2\_work\_tool\node\8.17.0\x64\node_modules\npm\bin\npm-cli.js" "install"
21522 verbose node v8.17.0
21523 verbose npm v6.13.4
21524 error Unexpected end of JSON input while parsing near '...ter/doc/TypeScript%20'
21525 verbose exit [ 1, true ]
有时也会超时
虽然我没有找到内置函数来检测构建步骤是否超时,但您可以尝试借助变量来模拟它。
考虑以下 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分钟后超时,但是里面的脚本模拟了long-运行任务(sleep 90
)1.5分钟。结果,任务超时并且 timedOut
变量 NOT 设置为 false
。因此,任务 B
的条件评估为 true
并执行。如果将 sleep 90
替换为 exit 1
以模拟任务 A 失败,也会发生同样的情况。
另一方面,如果任务 A 成功,则任务 B 的两个条件部分的计算结果都不为真,整个任务 B 将被跳过。
这是一个非常简化的示例,但它展示了您可以进一步调整以满足管道需求的想法。
可以添加自定义条件。如果你希望任务在上一个任务失败或跳过时执行,你可以使用自定义条件not(succeeded())
但是上面的自定义条件有一个问题,它在多任务场景中不起作用。
比如有A,B,C三个任务。预期的行为是仅当任务 B 失败时才执行任务 C。但实际行为是即使任务 B 成功,任务 C 也会在任务 A 失败时执行。检查下面的屏幕截图。
上述问题的解决方法是添加一个脚本任务来调用 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
。参考下面的截图。
终于可以对Task C使用自定义条件and(not(canceled()), ne(variables.taskStatus, 'succeeded'))
,Task C只有在Task B没有成功的情况下才会执行。
是否有选项可以设置自定义条件来测试上一个任务是否失败或超时?
目前,我正在使用 Only when a previous task has failed
,它在任务失败时起作用。如果任务超时,则不会将其视为错误并被跳过。
然后我需要一个自定义条件,比如 or(failed(), timedout())
。可能吗?
上下文
我们在 npm install
任务中遇到了这个间歇性问题,我们找不到原因,但下一个作业 运行 解决了这个问题,所以我们正在寻找重试功能。部分解决方案是复制 npm install
并使用控制选项,但它不适用于所有 "failure" 情况。 @Levi Lu-MSFT 给出的解决方案似乎可以满足我们的所有需求(它会重试)但遗憾的是它没有解决问题,第二行重复任务也失败了。
错误示例:
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.
或
21518 verbose stack SyntaxError: Unexpected end of JSON input while parsing near '...ter/doc/TypeScript%20'
21518 verbose stack at JSON.parse (<anonymous>)
21518 verbose stack at parseJson (C:\agent2\_work\_tool\node.17.0\x64\node_modules\npm\node_modules\json-parse-better-errors\index.js:7:17)
21518 verbose stack at consumeBody.call.then.buffer (C:\agent2\_work\_tool\node.17.0\x64\node_modules\npm\node_modules\node-fetch-npm\src\body.js:96:50)
21518 verbose stack at <anonymous>
21518 verbose stack at process._tickCallback (internal/process/next_tick.js:189:7)
21519 verbose cwd C:\agent2\_work\s
21520 verbose Windows_NT 10.0.14393
21521 verbose argv "C:\agent2\_work\_tool\node\8.17.0\x64\node.exe" "C:\agent2\_work\_tool\node\8.17.0\x64\node_modules\npm\bin\npm-cli.js" "install"
21522 verbose node v8.17.0
21523 verbose npm v6.13.4
21524 error Unexpected end of JSON input while parsing near '...ter/doc/TypeScript%20'
21525 verbose exit [ 1, true ]
有时也会超时
虽然我没有找到内置函数来检测构建步骤是否超时,但您可以尝试借助变量来模拟它。
考虑以下 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分钟后超时,但是里面的脚本模拟了long-运行任务(sleep 90
)1.5分钟。结果,任务超时并且 timedOut
变量 NOT 设置为 false
。因此,任务 B
的条件评估为 true
并执行。如果将 sleep 90
替换为 exit 1
以模拟任务 A 失败,也会发生同样的情况。
另一方面,如果任务 A 成功,则任务 B 的两个条件部分的计算结果都不为真,整个任务 B 将被跳过。
这是一个非常简化的示例,但它展示了您可以进一步调整以满足管道需求的想法。
可以添加自定义条件。如果你希望任务在上一个任务失败或跳过时执行,你可以使用自定义条件not(succeeded())
但是上面的自定义条件有一个问题,它在多任务场景中不起作用。
比如有A,B,C三个任务。预期的行为是仅当任务 B 失败时才执行任务 C。但实际行为是即使任务 B 成功,任务 C 也会在任务 A 失败时执行。检查下面的屏幕截图。
上述问题的解决方法是添加一个脚本任务来调用 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
。参考下面的截图。
终于可以对Task C使用自定义条件and(not(canceled()), ne(variables.taskStatus, 'succeeded'))
,Task C只有在Task B没有成功的情况下才会执行。