登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  软件教程

GitHub Actions concurrency 怎么取消同分支的旧运行

来源:17golang原创

时间:2026-11-11 05:21:46 370浏览 收藏

同一分支连续推送时,如果每次提交都启动一轮完整 CI,旧运行往往已经失去价值。GitHub Actions 可以用 concurrency 建立并发组,再把 cancel-in-progress 设为 true,让同组的新运行接替旧运行。关键是把工作流名和分支引用放进组名,避免两个不同工作流互相取消。

官方地址:https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency

最稳妥的默认写法是 group: ${{ github.workflow }}-${{ github.ref }} 配合 cancel-in-progress: true。这样同一工作流、同一分支的新运行会取消旧运行,而不同工作流不会因为恰好使用同一分支而互相影响。

先把并发组命名想清楚

并发控制不是“全仓库只留一个运行”。GitHub Actions 会按照 group 判断哪些任务属于同一组;组名相同,运行才会互相等待或取消。只写固定字符串虽然简单,却可能把测试、构建和部署等不同工作流放进同一条取消链。

这个场景适合用两个稳定变量拼接组名:

  • github.workflow 区分工作流;
  • github.ref 区分分支或标签引用。

准备文件时先打开仓库的 .github/workflows/,找到需要“新提交覆盖旧提交”的工作流。不要把并发组放到无关的第三方 action 参数里,它属于 workflow 或 job 的 YAML 配置。

把 concurrency 放在 workflow 级别

在工作流触发条件之后加入 concurrency。下面的配置会让同一个工作流在同一分支上保持一条最新运行;代码块中的注释说明了每个关键字段的作用。

name: test

on:
  push:
    branches: [main, develop]

# workflow 级并发:同一工作流、同一引用归入同一组
concurrency:
  # 加上 workflow 名,避免不同工作流互相取消
  group: ${{ github.workflow }}-${{ github.ref }}
  # 新运行进入同组后,取消仍在运行的旧任务
  cancel-in-progress: true

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: 运行测试
        run: go test ./... # 这里替换成仓库自己的测试命令

选择入口后,编辑器中的关键位置应该是工作流顶层,而不是 jobs.test.steps 下的某个步骤。图 1 是原创界面说明图,展示了 group、分支引用和取消开关的对应关系,不是 GitHub 页面截图。

GitHub Actions 并发配置界面说明图,展示工作流名、分支引用和取消旧运行开关
图1:并发配置操作示意图,展示 workflow 级 concurrency 的关键字段。

保存工作流文件后,GitHub 会重新解析配置。若只想限制一个耗时 job,也可以把 concurrency 放到 jobs. 下;但那只约束这个 job,不会自动取消整个工作流中的其他 job。

在 Actions 页面核对新旧运行

打开仓库的 Actions 页面,进入刚修改的工作流,再连续推送两次同一分支。查看运行列表时,不要只看最新一条绿色或红色结果,而要确认两条运行是否属于同一个并发组。

  1. 在左侧选择对应工作流,确认分支筛选与推送分支一致。
  2. 先观察较早的运行:如果它尚未结束,新运行进入同组后,旧运行应变为已取消或不再继续占用 runner。
  3. 打开较新的运行,确认它仍在执行测试;这条运行才是当前分支要保留的结果。

图 2 用原创界面说明图表达“新运行:运行中、旧运行:已取消”的关系。它只帮助理解页面状态,不是实际运行记录或线上证据。

GitHub Actions 工作流运行列表说明图,展示新运行和旧运行的取消状态
图2:运行结果示意图,展示新运行接替旧运行后的状态差异。

给发布分支保留例外

测试分支通常适合“新提交覆盖旧提交”,但发布分支未必适合无条件取消。可以让并发组仍然按工作流和引用区分,同时把取消规则改成表达式:

# 发布分支保留当前运行,其它分支允许新运行取消旧运行
concurrency:
  # 同一工作流和引用仍然使用独立并发组
  group: ${{ github.workflow }}-${{ github.ref }}
  # release/ 开头的引用不取消进行中的运行
  cancel-in-progress: ${{ !startsWith(github.ref, 'refs/heads/release/') }}

如果工作流同时响应拉取请求和 push,某些事件并不提供相同的引用字段。此时要为可能为空的上下文准备回退值,并把组名设计成不会与其他工作流重叠的形式。GitHub 文档还说明,并发组名称不区分大小写,因此不要只靠大小写区分两个组。

常见误区和快速核对

现象优先检查
不同工作流互相取消group 是否缺少 github.workflow
旧运行仍继续cancel-in-progress 是否为 true 或满足条件的表达式
同一分支没有形成替换两次运行的 github.ref 是否一致、配置是否在目标 workflow 中
发布任务被误取消是否应对 release 引用设置条件例外

把并发控制当成“同一工作流、同一引用只保留最新意图”的配置即可。先用固定的 workflow 加分支组名解决测试浪费,再根据发布流程增加条件取消;这样既能减少重复 CI,也不会把生产动作交给一个过宽的取消规则。

相关问答

只写 cancel-in-progress 不写 group 可以吗?

不建议。取消规则需要依附并发组才能判断哪些运行属于同一组;先定义稳定的 group,再决定是否取消进行中的旧运行。

workflow 级和 job 级 concurrency 有什么区别?

workflow 级影响整轮工作流,job 级只影响指定 job。若目标是新提交替换整轮 CI,优先把配置放在 workflow 顶层。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>