Skip to content
返回质量保障

并发控制与管道取消

限并发管道运行并取消被取代的运行、使 CI 资源花在最新提交非将被推过的旧提交。

为什么

无并发控制、开发者连推 5 提交触发 5 管道运行、全并行对已过时提交 1-4 跑——CI 烧 5 倍算力为无人读的结果、且第 5 运行(重要的)排 4 旧运行后更慢。并发控制在新提交推时取消旧运行、使仅最新提交管道跑——这减半 CI 账单、加速最新提交反馈、释放运行器给其他 PR。部署管道同理: 部署进行中新部署触发时、旧的应取消(非并行跑、可坏发布)。机制是按分支(或 PR)键的并发组、cancel-in-progress: true。

何时使用

CI 运行器为共享有限资源时——本质总如此。团队有超几并发 PR 或 CI 分钟为计费资源时此控制变关键。

如何做

1. 给每工作流加并发组
   - 按分支(或 PR 号)键使不同分支运行不互取消
   - 设 cancel-in-progress: true 使新运行取消同分支前一运行

2. PR 和 push 用不同组
   - PR 运行: 并发组 "pr-${{ github.event.pull_request.number }}"
   - main 运行: 并发组 "main"(勿取消——每 main 运行为部署候选)

3. 取消旧矩阵 job
   - 矩阵构建(如 5 OS × 3 Node 版 = 15 job)中跑取消释放 15 运行器
   - 新提交推时并发组取消整个矩阵

4. 勿取消部署管道
   - 部署管道用 cancel-in-progress: false(进行中部署应完成、非中部署取消)
   - 或部署用单独并发组最大 1

5. 监取消率
   - 高取消率(> 50%)示开发者推太频——考虑本地跑 lint 的 pre-commit hook
   - 低取消率(< 5%)示并发控制未抓旧运行——查组键

示例

# .github/workflows/ci.yml — 取消旧 PR 运行
name: ci
on:
  pull_request:
    branches: [main]
concurrency:
  group: pr-${{ github.event.pull_request.number }}
  cancel-in-progress: true
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm test

# .github/workflows/deploy.yml — 勿取消部署
name: deploy
on:
  push:
    branches: [main]
concurrency:
  group: deploy-production
  cancel-in-progress: false   # 让当前部署完成

常见问题

  • ⚠PR 运行并发组键 github.ref——所有 PR 共享同 ref(refs/pull/N/merge)、故一 PR 运行取消另一 PR 运行、开发者见 CI 消失无解释。
  • ⚠部署工作流设 cancel-in-progress: true——生产部署被新推 main 中途取消、留服务半部署状态新旧代码混。
  • ⚠完全不用并发控制——开发者调试时推 10 提交、10 管道运行并行、CI 账单升、第 10 运行(重要的)慢因运行器忙于 9 旧运行。
  • ⚠取消最后几秒运行(传产物、发评论)——取消失产物和评论、开发者须重跑管道得测试报告。

最佳实践

  • ✓PR 并发组键 PR 号(github.event.pull_request.number)非 github.ref——这确保每 PR 运行仅取消该 PR 旧运行。
  • ✓CI 工作流(lint、test、build)设 cancel-in-progress: true、部署工作流设 false——CI 运行便宜可重复、部署贵须原子完成。
  • ✓取消前加短宽限期(平台支持时)使最后几秒运行可完成传产物——这保留最新运行测试报告。
  • ✓同监取消率和运行器利用率——高取消率低利用率示组键错(运行应取消时未取消)。