如何在Github Actions中推送新提交(更新当前提交)时取消以前的运行?

85

当我将我的提交推送到PR时,我的测试会针对该提交进行触发。在此之后,如果我向此PR推送其他提交,则Github Actions中的测试将运行在这两个提交上。

我需要取消以前的运行并仅在最近推送的提交上运行。

我该如何配置我的yaml文件来实现这一点?


请接受备选答案,即使原回答者要求如此。 - Csaba Toth
4个回答

128

如果要在触发新工作流时取消当前正在运行的工作流,可以使用以下方法:在同一PR、分支或标签中

name: Workflow X

on: # ...

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs: # ...

说明:

  • ${{ github.workflow }}:使用工作流名称来生成并发组(例如Workflow 1),以允许您在同一事件(例如PR)上触发多个不同的工作流(例如workflow1.yamlworkflow2.yaml)。否则,workflow1.yaml将取消workflow2.yaml或反之亦然。
  • ${{ github.event.pull_request.number }}:当触发事件是PR时,它将使用PR号码来生成并发组(例如workflow1-33)。
  • || github.ref }}:当触发的不是PR而是push时,它将使用分支或标签名称来生成并发组(例如workflow1-branch1)。
  • cancel-in-progress: true:如果省略cancel-in-progress或将其设置为false,则当触发新工作流时,当前正在运行的工作流不会被取消,并且新工作流将排队等待,直到前一个完成。

参考:https://docs.github.com/en/actions/using-jobs/using-concurrency


1
这是一个很好的解释,特别是在考虑到不同的工作流程时添加${{ github.workflow }}非常重要。由于对于拉取请求,github.refrefs/pull/<pr_number>/merge,因此它也足够独特。似乎稍微简单一点的组合也同样有效:group: ${{ github.workflow }}-${{ github.ref }}。因此,我很好奇为什么需要在你的答案中处理event.pull_request.number的特定逻辑。 - BjornO
3
我也会考虑根据GitHub并发文档中提到的,将${{ github.ref }}更改为${{ github.ref || github.run_id }}。这允许任意事件(例如workflow_dispatch)在其自己的组中运行工作流程,而不必拥有引用。因此,总结一下我的两个评论:group: ${{ github.workflow }}-${{ github.ref || github.run_id }} - BjornO

92

您可以使用Concurrency

并发性可确保任何时候只有一个使用相同并发组的作业或工作流会运行。

concurrency: 
  group: ${{ github.head_ref }}
  cancel-in-progress: true

运行非常好。注意:并发性(concurrency)截至2021年5月10日仍处于测试阶段,可能会有所更改。 - vhiairrassary
3
这是什么级别的?每个示例都只显示它本身...没有完整的文件或示例。谢谢。 - naspinski
9
@naspinski的工作示例https://github.com/TeamAmaze/AmazeFileManager/blob/release/3.7/.github/workflows/android-feature.yml - EmmanuelMess
@EmmanuelMess 在你的回答中,你使用了 github.head_ref,而在你的仓库引用中只使用了 github.ref,就像 https://github.community/t/stop-running-actions-when-new-commit-pushed-to-branch/16455/5 中一样。哪一个更好? - Csaba Toth
3
@CsabaToth github.ref 请参见此处head_ref "仅在触发工作流运行的事件为pull_request或pull_request_target时可用。"但是ref只是“触发工作流运行的分支或标签ref。” - EmmanuelMess

9
你还需要确保在同一存储库中有多个工作流时考虑取消相同工作流程的正在进行的运行。

来自并发使用 GitHub文档的片段:

concurrency: 
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

完整的工作示例(源代码):

name: CI with in-progress cancellations

on:
  pull_request:
    branches: [ main ]
  workflow_dispatch:

# This is what will cancel the workflow
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Print concurrency group
        run: echo '${{ github.workflow }}-${{ github.ref }}'
      - name: Sleep 15s
        run: sleep 15s

4

更新

这个已经不再适用,自从GitHub Actions以后,这种体验有所改善。首先查看替代答案

旧答案

就像我们曾经说过“这有一个应用程序!”,现在是“这有一个Action(操作)!”:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Cancel Previous Runs
        uses: styfle/cancel-workflow-action@0.8.0
        with:
          access_token: ${{ github.token }}
      #- name: Run Tests
      #  uses: actions/setup-node@v1
      #  run: node test.js
      # ... etc

https://github.com/styfle/cancel-workflow-action


4
cancel-workflow-action已被废弃,建议改用concurrency - EmmanuelMess
3
@max,你能否取消接受这个答案并将其转移到备选项上。我的答案已经过时了,因为GitHub Actions已经发展壮大了。 - jessehouwing
确定,完成,谢谢 - Max

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接