如何强迫工作退出github行动步骤

发布于 2025-02-12 03:43:01 字数 297 浏览 0 评论 0原文

如果满足特定条件,我想退出工作:

jobs:
  foo:
    steps:
      ...
      - name: Early exit
        run: exit_with_success # I want to know what command I should write here
        if: true
      - run: foo
      - run: ...
 ...

我该怎么做?

I want to exit a job if a specific condition is met:

jobs:
  foo:
    steps:
      ...
      - name: Early exit
        run: exit_with_success # I want to know what command I should write here
        if: true
      - run: foo
      - run: ...
 ...

How can I do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

影子的影子 2025-02-19 03:43:01

当前没有办法任意退出工作,但是如果较早的步骤失败,则有一种方法可以使用条件

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: ...
 ...

想法是,如果第一步失败,则其余部分将运行,但是如果第一步不会失败,则其余部分将不会运行。

但是,需要注意的是,如果任何后续步骤都会失败,那么它们之后的步骤仍将运行,这可能是理想的,也可能不是可取的。


另一个选项是使用“ noreferrer”>步骤输出表明失败或成功:

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 语法,然后使用该语法 包含 在进一步的工作中发挥作用,以确保没有任何步骤失败:

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: ...

此外,请记住,“失败”和“成功”并不是一个步骤中唯一的结论。参见 steass出于其他可能的原因,。

There is currently no way to exit a job arbitrarily, but there is a way to allow skipping subsequent steps if an earlier step failed, by using 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: ...
 ...

The idea is that if the first step fails, then the rest will run, but if the first step doesn't fail the rest will not run.

However, it comes with the caveat that if any of the subsequent steps fail, the steps following them will still run, which may or may not be desirable.


Another option is to use step outputs to indicate failure or success:

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: ...
 ...

This method works pretty well and gives you very granular control over which steps are allowed to run and when, however it became very verbose with all the conditions you need.


Yet another option is to have two jobs:

  • one which checks your condition
  • another which depends on it:
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: ...
 ...

This last method works very well by moving the check into a separate job and having another job wait and check the status. However, if you have more jobs, then you have to repeat the same check in each one. This is not too bad as compared to doing a check in each step.


Note: In the last example, you can have the check job depend on the outputs of multiple steps by using the object filter syntax, then use the contains function in further jobs to ensure none of the steps failed:

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: ...

Furthermore, keep in mind that "failure" and "success" are not the only conclusions available from a step. See steps.<step id>.conclusion for other possible reasons.

清晰传感 2025-02-19 03:43:01

exit可以使用GH Run CanceGH Run观看命令:

- name: Early exit
  run: |
    gh run cancel ${{ github.run_id }}
    gh run watch ${{ github.run_id }}
  env:
    GH_TOKEN: ${{ secrets. GITHUB_TOKEN }}

观看是必需的,因为取消是必需的不会立即流产。

您可能需要操作:'Write'为作业添加了权限,类似:

permissions:
  ...
  actions: 'write'

The exit behavior can be achieved with gh run cancel and gh run watch commands:

- name: Early exit
  run: |
    gh run cancel ${{ github.run_id }}
    gh run watch ${{ github.run_id }}
  env:
    GH_TOKEN: ${{ secrets. GITHUB_TOKEN }}

The watch is required since cancellation will not abort immediately.

You may need actions: 'write' permission added for the job, something like:

permissions:
  ...
  actions: 'write'
铁憨憨 2025-02-19 03:43:01

如果其他发布的答案无法解决您的问题,那么您可以考虑创建一个确定应该运行哪些作业并跳过哪些作业的作业。
该解决方案利用作业输出 。<<<<<<<<<<<<<<<< br>
这是一个示例:

jobs:
  planner:
    name: Determine which jobs to run
    runs-on: ubuntu-latest
    # To keep it simple name the step and output the same as job
    outputs:
      foo: ${{ steps.foo.outputs.should-run }}

    steps:
      # Checkout if necessary to determine whether 'foo' needs to run
      # - uses: actions/checkout@v4

      - name: Mark foo job as 'to be run'
        id: foo
        # Replace 'true' with your condition
        run: echo "should-run=true" >> $GITHUB_OUTPUT

  foo:
    runs-on: ubuntu-latest
    needs: planner
    # Skip this job when condition not met
    if: needs.planner.outputs.foo == 'true'

    steps:
      - uses: actions/checkout@v4
      # ...

该方法的一个例子是,当您拥有昂贵的工作时,如果输出相同,则可以跳过。例如,针对最新标签进行夜间测试,但最新标签尚未更改。

If the other posted answers did not solve your problem then, you could consider creating a job that determines which jobs should be run and which should be skipped.
This solution makes use of job outputs.
Here is an example:

jobs:
  planner:
    name: Determine which jobs to run
    runs-on: ubuntu-latest
    # To keep it simple name the step and output the same as job
    outputs:
      foo: ${{ steps.foo.outputs.should-run }}

    steps:
      # Checkout if necessary to determine whether 'foo' needs to run
      # - uses: actions/checkout@v4

      - name: Mark foo job as 'to be run'
        id: foo
        # Replace 'true' with your condition
        run: echo "should-run=true" >> $GITHUB_OUTPUT

  foo:
    runs-on: ubuntu-latest
    needs: planner
    # Skip this job when condition not met
    if: needs.planner.outputs.foo == 'true'

    steps:
      - uses: actions/checkout@v4
      # ...

An example use case for this approach would be when you have an expensive job which can be skipped if the output is the same. For example running nightly tests against latest tag, but latest tag has not changed.

苄①跕圉湢 2025-02-19 03:43:01

我只是通过运行退出1来做到这一点,

job:
  runs-on: ubuntu-latest
    steps:
      - name: 'Stage 1'
        run: |
          if [[ "${{ github.event.head_commit.message }}" =~ \[run-stage-2\] ]];
          then
            echo "Valid commit message detected. stage 2 will run."
          else 
            echo "Valid commit message not detected. stage 2 will not run."
            exit 1
          fi
      - name: 'Stage 2'
        run: <whatever>

因此,在这里,阶段1一个检查提交消息是否包含[Run stage-2]。如果这样做,阶段1将完成,第2阶段将开始;但是如果没有,退出1被调用,工作流将失败。

I just did this by running exit 1

job:
  runs-on: ubuntu-latest
    steps:
      - name: 'Stage 1'
        run: |
          if [[ "${{ github.event.head_commit.message }}" =~ \[run-stage-2\] ]];
          then
            echo "Valid commit message detected. stage 2 will run."
          else 
            echo "Valid commit message not detected. stage 2 will not run."
            exit 1
          fi
      - name: 'Stage 2'
        run: <whatever>

So here, stage 1 one checks to see if the commit message contains [run-stage-2]. If it does, stage 1 will complete and stage 2 will begin; but it if doesn't, exit 1 is called and the workflow will fail.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文