目前无法任意退出作业,但有一种方法可以在前一步失败时跳过后续步骤,使用conditionals:
jobs:
foo:
steps:
...
- name: Early exit
run: exit_with_success # I want to know what command I should write here
- if: failure()
run: foo
- if: failure()
run: ...
...
这个想法是,如果第一步失败,那么其余的将运行,但如果第一步没有失败,其余的将不会运行。
但是,需要注意的是,如果任何后续步骤失败,它们之后的步骤仍将运行,这可能是可取的,也可能不是可取的。
另一种选择是使用step outputs 表示失败或成功:
jobs:
foo:
steps:
...
- id: s1
name: Early exit
run: # exit_with_success
- id: s2
if: steps.s1.conclusion == 'failure'
run: foo
- id: s3
if: steps.s2.conclusion == 'success'
run: ...
...
这种方法效果很好,让您可以非常精细地控制允许运行哪些步骤以及何时运行,但是在您需要的所有条件下它变得非常冗长。
另一种选择是拥有两份工作:
jobs:
check:
outputs:
status: ${{ steps.early.conclusion }}
steps:
- id: early
name: Early exit
run: # exit_with_success
work:
needs: check
if: needs.check.outputs.status == 'success'
steps:
- run: foo
- run: ...
...
通过将检查移至单独的作业并让另一个作业等待并检查状态,最后一种方法非常有效。但是,如果您有更多工作,则必须在每个工作中重复相同的检查。与在每个步骤中进行检查相比,这还不错。
注意:在最后一个示例中,您可以使用 object filter 语法让 check 作业依赖于多个步骤的输出,然后使用contains 在进一步的工作中发挥作用,以确保没有任何步骤失败:
jobs:
check:
outputs:
status: ${{ join(steps.*.conclusion) }}
steps:
- id: early
name: Early exit
run: # exit_with_success
- id: more_steps
name: Mooorreee
run: # exit_maybe_with_success
work:
needs: check
if: !contains(needs.check.outputs.status, 'failure')
steps:
- run: foo
- run: ...
此外,请记住,“失败”和“成功”并不是从某个步骤中得出的唯一结论。其他可能的原因请参见steps.<step id>.conclusion。