我有以下工作结构:
主要目标是运行发布工件,如果任何任务成功,如果所有任务都失败,发布工件不应该被执行,作业应该失败。
我尝试考虑的事情:
我尝试过的解决方案:
我尝试在发布工件上使用自定义条件,之前询问所有任务的结果,但 azure 管道不保存任务的结果状态。
我还尝试在除最后一个任务(任务 N)之外的每个任务上使用 continueOnError 但如果此任务失败,即使其中一个成功,整个过程也会失败。
我tried this solution但是这个解决方案中的脚本不知道我正在设置变量的任务是否实际通过,它只会认为任何任务失败,它不会确定哪个任务是失败的那个。
有什么关于我如何通过这次考试的建议吗?
答案 0 :(得分:1)
我不确定我是否完全按照您的要求进行操作,但我认为这可能会满足您的需求。
假设我是正确的:
# Sample pipeline
# Inline bash scripts to simulate failing tasks.
# Comment out the 'exit 1' line to allow a task to succeed
# The Publish Artifact task below is just a fake for the purposes of testing
steps:
- task: Bash@3
name: task1
displayName: Task 1
continueOnError: true
inputs:
targetType: 'inline'
script: |
echo 'Task 1'
exit 1
echo "##vso[task.setvariable variable=task1_succeeded]true"
failOnStderr: true
- task: Bash@3
name: task2
displayName: Task 2
condition: ne(variables.task1_succeeded, true)
continueOnError: true
inputs:
targetType: 'inline'
script: |
echo 'Task 2'
exit 1
echo "##vso[task.setvariable variable=task2_succeeded]true"
failOnStderr: true
- task: Bash@3
name: task3
displayName: Task 3
condition: |
and(
ne(variables.task1_succeeded, true),
ne(variables.task2_succeeded, true)
)
continueOnError: true
inputs:
targetType: 'inline'
script: |
echo 'Task 3'
exit 1
echo "##vso[task.setvariable variable=task3_succeeded]true"
failOnStderr: true
- task: Bash@3
name: taskN
displayName: Task N
condition: |
and(
ne(variables.task1_succeeded, true),
ne(variables.task2_succeeded, true),
ne(variables.task3_succeeded, true)
)
continueOnError: false
inputs:
targetType: 'inline'
script: |
echo 'Task N'
exit 1
echo "##vso[task.setvariable variable=taskN_succeeded]true"
failOnStderr: true
- task: Bash@3
name: publishArtifact
condition: |
or(
eq(variables.task1_succeeded, true),
eq(variables.task2_succeeded, true),
eq(variables.task3_succeeded, true),
eq(variables.taskN_succeeded, true)
)
displayName: 'Publish Artifact'
inputs:
targetType: 'inline'
script: |
echo 'Pseudo Publish Artifact'
failOnStderr: true
答案 1 :(得分:1)
检查这个 YAML,我们可以添加一个 power shell 任务并调用 REST API 来检查任务结果。
# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml
trigger: none
pool:
vmImage: ubuntu-latest
steps:
- task: PowerShell@2
displayName: task1
inputs:
targetType: 'inline'
script: 'Write-Host "Hello World"'
- task: PowerShell@2
displayName: task2
inputs:
targetType: 'inline'
script: 'Write-Host "Hello World" $(xasda)'
- task: PowerShell@2
displayName: taskn
inputs:
targetType: 'inline'
script: 'Write-Host "Hello World"'
condition: always()
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
$PAT="{pat}"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($PAT)"))
#List all build timeline via build ID
$ListAllBuildTimeLineURL="https://dev.azure.com/{Org name}/{Project name}/_apis/build/builds/$(Build.BuildId)/timeline?api-version=6.1-preview.2"
$ListAllBuildTimeLineResult = Invoke-RestMethod -Uri $ListAllBuildTimeLineURL -Headers @{Authorization = "Basic {0}" -f $base64AuthInfo} -Method get
$ListAllBuildTimeLineResult.records.Count
#Check task result and set variable
foreach($Task in $ListAllBuildTimeLineResult.records){
if($Task.name -eq "taskn"){
#write-host $Task.state
#write-host $Task.id
if($Task.result -eq "succeeded"){
Write-Host "##vso[task.setvariable variable=taskn.status]Success"
}
}
if($Task.name -eq "task1"){
if($Task.result -eq "succeeded"){
Write-Host "##vso[task.setvariable variable=task.status]Success"
}
}
if($Task.name -eq "task2"){
if($Task.result -eq "succeeded"){
Write-Host "##vso[task.setvariable variable=task.status]Success"
}
}
}
condition: always()
#
- task: Bash@3
displayName: publishArtifact
inputs:
targetType: 'inline'
script: 'printenv'
condition: and(eq(variables['taskn.status'], 'success'),eq(variables['task.status'], 'success'))
结果:
注意:任务 Bash
应该是任务 Publish artifact
答案 2 :(得分:0)
有 2 个可能的答案,每个答案都有一些问题。但他们确实解决了这个问题。
这将要求每个任务都被视为一个单独的作业,因此条件和依赖项取决于作业,并且应该在它们之间传递。
# Sample pipeline
# Avoiding setup and rest of variables
- job: task_1
steps:
- task: Bash@3
name: task1
displayName: Task 1
continueOnError: true
inputs:
targetType: 'inline'
script: |
echo 'Task 1'
- task: Bash@1
displayName: 'Publish Artifact'
inputs:
targetType: 'inline'
script: |
echo "Publish artifact"
- job: task_2
dependsOn:
- task_1
condition: eq(dependencies.task_1.result,'SucceededWithIssues')
steps:
- task: Bash@3
name: task2
displayName: Task 2
continueOnError: true
inputs:
targetType: 'inline'
script: |
echo 'Task 2'
- task: Bash@1
displayName: 'Publish Artifact'
inputs:
targetType: 'inline'
script: |
echo "Publish artifact"
#Keep on doing tasks...
- job: task_N
dependsOn:
- task_N-1
condition: eq(dependencies.task_N-1.result,'SucceededWithIssues')
steps:
- task: Bash@3
name: task_N
displayName: Task N
inputs:
targetType: 'inline'
script: |
echo 'Task N'
- task: Bash@1
displayName: 'Publish Artifact'
inputs:
targetType: 'inline'
script: |
echo "Publish artifact"
注意:
优点:
缺点:
我没有设法在我需要的代码上测试这个例子,但看起来很合乎逻辑,我不明白为什么它会失败。这是基于@Vito Liu-MSFT 的回答
# Sample pipeline
- job: task_1
steps:
- task: Bash@3
name: task1
displayName: Task 1
inputs:
targetType: 'inline'
script: |
echo 'Task 1'
failOnStderr: true
- task: Bash@3
name: task2
displayName: Task 2
condition: failed()
inputs:
targetType: 'inline'
script: |
echo 'Task 1'
failOnStderr: true
# Keep doing tasks
- task: Bash@3
name: taskN
displayName: Task N
inputs:
targetType: 'inline'
script: |
echo 'Task 1'
failOnStderr: true
condition: failed()
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
$PAT="{pat}"
$base64AuthInfo= System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($PAT)"))
#List all build timeline via build ID
$ListAllBuildTimeLineURL="https://dev.azure.com/{Org name}/{Project name}/_apis/build/builds/$(Build.BuildId)/timeline?api-version=6.1-preview.2"
$ListAllBuildTimeLineResult = Invoke-RestMethod -Uri $ListAllBuildTimeLineURL -Headers @{Authorization = "Basic {0}" -f $base64AuthInfo} -Method get
$ListAllBuildTimeLineResult.records.Count
#Check task result and set variable
foreach($Task in $ListAllBuildTimeLineResult.records){
if($Task.name -eq "task1"){
if($Task.result -eq "succeeded"){
Write-Host "##vso[task.setvariable variable=task1.status]Success"
}
}
if($Task.name -eq "task2"){
if($Task.result -eq "succeeded"){
Write-Host "##vso[task.setvariable variable=task2.status]Success"
}
}
# Keep printing each task if succeed
if($Task.name -eq "taskN"){
if($Task.result -eq "succeeded"){
Write-Host "##vso[task.setvariable variable=taskN.status]Success"
}
}
}
condition: SucceededOrFailed()
- task: Bash@1
displayName: 'Publish Artifact'
inputs:
targetType: 'inline'
script: |
echo "Publish artifact"
condition: |
or(
SucceededOrFailed(),
or(
eq(variables['task1.status'], 'success'),
or(
eq(variables['task2.status'], 'success'),
or(
# Keep writing ors
eq(variables['taskN-1.status'], 'success')
eq(variables['taskN.status'], 'success')
)
)
)
)
注意事项:
优点:
缺点:
我没有对此进行测试,我不确定,但是由于任务失败,我相信作业的状态将失败,未来的依赖项将不得不处理这种情况,这将不确定作业是否真的失败了。管道可能会作为错误返回。使用 ContinueOnError 更改失败时可以获得更好的结果,并且作业将返回 SucceededWithIssues。