DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

cancel-in-progress 为 false,排队的 Actions 任务还是被取消

cancel-in-progress:false保护正在运行的任务,默认只保留一个pending。按平台支持情况设置queue:max,保留共享资源互斥,并核对容量与等待顺序。

几个 PR 共用一台测试设备,工作流设置了相同 concurrency.group,并写明 cancel-in-progress: false。正在运行的任务没被打断,等候中的任务却在新任务到来后变成 canceled。这个选项保护正在运行的任务,默认队列仍然只保留一个 pending 名额。

本文针对 GitHub Cloud 当前的并发队列规则。自托管 Runner 承接执行,也不会把服务端默认 pending 队列自动变成无限队列;GitHub Enterprise Server 则需先核对所用版本是否支持下面的属性。

分开看 running 和 pending

同一并发组默认最多有一个正在运行的任务,以及一个 pending 任务。A 已运行、B 等待时,C 进入这个组,B 会被取消,由 C 占据等候名额。A 可以继续,这与 cancel-in-progress: false 并不矛盾。

先查看被取消任务有没有真正取得 Runner、执行过步骤,以及其他工作流是否也使用相同组名。组名在同一仓库内生效,不区分大小写;Prod 和 prod 不构成两个独立组。

手工取消、执行超时、上游失败与 pending 被替换也会产生不同的取消或跳过结果,不能只看任务最终颜色。先核对它进入并发等待的时间和随后进入相同组的任务。

需要保留多个等候任务时,使用受支持的队列设置

如果所有任务都需要按同一资源串行执行,GitHub Cloud 当前支持 queue: max。例如,在工作流级别保护一台独占测试设备:

concurrency:
  group: ios-test-device-01
  cancel-in-progress: false
  queue: max

这是并发配置片段,组名替换为实际资源标识。工作流级和 job 级的作用范围不同:若设备从准备到测试结束一直被占用,应按真实占用生命周期设计组,不能只在一个准备 job 上上锁,就认为后面的独立 job 也一直受保护。

queue: max 最多允许 100 个 pending job 或工作流运行,队列已满时新加入的任务仍会被取消。它不能与 cancel-in-progress: true 同时使用,否则工作流验证会失败。修改前保存原配置,先在不会操作正式资源的路径验证平台确实接受该属性。

如果需求本来就是只保留最新一份检查,默认 queue: single 可能符合目的,无需为了让所有历史任务运行而扩大队列。需要保留的部署、测试或处理任务,则要明确谁负责补偿被取消或超过容量的工作。

组名不能随便改成每次唯一

把 github.run_id 加进组名,可以使每次运行获得不同组,但也同时失去那台设备的互斥。如果资源真的只有一份,多个任务就可能同时读写它,原来“排队被取消”的问题会变成资源冲突。

只有资源相互独立时,才按工作流、分支或其他资源维度拆组。同一个共享资源被多个工作流使用时,共用一个组也可能是有意的约束;不能一律加 github.workflow 把它们隔开。

任务被取消后还要看 needs 的影响。必要的准备或构建结果没有产生时,强加 always() 让下游执行,不能补回那些结果,也可能让部署在缺少输入时启动。

等候顺序不等于提交顺序

当前队列按各任务进入并发等待的时间进行 FIFO 处理,不按提交时间或整个工作流的派发时间。上游依赖、审批和任务启动延迟都可能改变进入队列的顺序。

若业务必须逐个处理所有提交且严格遵守业务顺序,就还需要明确的任务记录、去重与补偿设计,不能把有限并发队列当成持久业务队列。

验证时观察同组的多个受控任务:运行中的任务是否保持,等待项是否保留到容量边界,以及共享资源有没有出现并行操作。看见一份排队任务最终成功,只说明那一份进入并执行了,不能证明以后不会达到队列上限。