Skip to content

CI: Dogfood Regression Gate 把 cancelled 当失败 —— 每次连续推送都产生一条假红 #3668

Description

@os-zhuang

现象

dogfood-gate 在 dogfood 矩阵被取消时报失败。因为 CI 开了 cancel-in-progress任何一次「推了新提交、旧运行还在跑」的连续推送都会产生一条假红

#3660 上连续观察到两次,日志完全一致:

Job HeadSHA 日志
89988965549 7972cb3 dogfood matrix aggregate result: cancelled
89990688709 793ee5e dogfood matrix aggregate result: cancelled

两次都是被后续提交取代的运行,代码本身没有任何问题——同一分支最终 18 项检查全绿并合并。

成因

# .github/workflows/ci.yml:14-16
concurrency:
  group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true
# .github/workflows/ci.yml:270-277
- name: Verify dogfood shard results
  run: |
    result="${{ needs.dogfood.result }}"
    echo "dogfood matrix aggregate result: $result"
    case "$result" in
      success|skipped) echo "Dogfood gate satisfied." ;;
      *) echo "::error::Dogfood shards did not pass (aggregate result: $result)"; exit 1 ;;
    esac

skipped 已被正确豁免(filter 判定无 core 变更时),但 cancelled 落进了兜底的 *) 分支。dogfood 分片跑约 7½ 分钟,是 CI 里最长的任务之一,所以它几乎总是「还在跑」的那个,被取消的概率最高。

影响

不阻塞合并(被取代的运行挂在旧 SHA 上,分支保护看的是最新 SHA),但:

  • 假红会触发失败通知,看到的人(或盯 PR 的 agent)必须去翻日志才能确认「这不是真失败」。本次两条告警各花掉一个来回。
  • 噪声会训练出对该 gate 的忽视——一个经常假红的必需检查,真红时也会被当成噪声划过去,而这恰恰是回归门最不该有的属性。

建议修法

cancelled 并入放行分支:

    case "$result" in
      success|skipped|cancelled) echo "Dogfood gate satisfied." ;;

安全性论据(需要确认后再落地):矩阵里若有分片真的失败,GitHub 给出的聚合 resultfailure 而非 cancelled(fail-fast 取消掉的兄弟分片不会把聚合结果降级成 cancelled)。若该前提成立,则 cancelled 只可能来自整个运行被外部取消(并发组取代、手动取消),放行它不会漏掉任何真实回归。这一点建议先用一次 fail-fast 实验验证,别直接照搬我的推断。

不建议的替代方案

把 gate 的 if: always() 改成 if: !cancelled()。这样运行被取消时 gate 自身被跳过,必需检查上下文就不会发布。对被取代的旧 SHA 无所谓,但一旦出现同 SHA 被取消的情况(重跑、排队重复),该 SHA 上就永远缺这个上下文 → PR 卡死。这正是 ci.yml:250-259 注释里记载的 #3622 死锁场景,不应重蹈。

备注

grep 'needs\..*\.result' .github/workflows/*.yml 只有这一处命中,所以该模式目前仅此一个聚合门,改动面很小。

关联:#3622(分片化 + 稳定必需检查名的由来)、#3660(本次观察到的两条假红)。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions