ci: 把 check-ci-gates.py 接进 go job,CI 自己检查自己的配置不许静默退化

背景:.github/scripts/check-ci-gates.py 上一轮已写好并入仓(ed8f28e),
但它**没被任何 workflow 调用** —— `grep check-ci-gates .github/workflows/ci.yml`
零命中。等于判据只活在评审口径里,CI 实际上不跑它。本次把它接上。

## 一、ci.yml:新增 2 步(go job,插在 go vet 之后、go test 之前)

- `actions/setup-python@v7`(3.12)
- `CI 配置门禁自检(动态枚举 / 排除表 / 启动图判据不许静默退化)`

位置为什么在 go test ./... **之前**而不是之后:

  · 该步骤是纯静态检查 —— 只读 ci.yml,秒级,无网络、无 cgo、
    不建 SQLite、不占端口;而 go test ./... 要跑 20 分钟。
  · 「门禁本身坏掉」应该第一时间红。放后面会让一次坏配置白白消耗
    20 分钟机器时间才发现,也让失败信号埋在 93 个包的输出后面。

runner 的 pyyaml **不假设自带**:先 `python3 -c 'import yaml'` 探测,
缺了才 `pip install pyyaml`(幂等,几秒)。本机实测 pyyaml 6.0.3 已有,
但本机的 Python 环境不等于 runner —— 所以做探测而不是赌。

## 二、顺手纳管 internal/kernelboot/modules/registry.go 的注释改动

该文件 +6/−3 的改动是**纯注释**,内容为 11:08 那轮已拍板要记进文件头的说明:
真相源为什么刻意不扫 `kernelmod.Register(...)` 调用点 ——
删掉某模块的 init() 后调用点消失,源码侧与登记表侧会同时少一个,
比对照样相等 ⇒ 假绿。手写模块名清单同理。故真相源取
「目录+类型名复合键 + 四方法齐全」的类型,而不是要检测对象的入口。

★ 这点在 commit message 里点明,是为了不让它变成夹带:它不是本次新写的代码,
  是上一轮已定但未提交的说明文字,与本次「门禁入 CI」同一主题(判据不许假绿)。

## 三、验证(先证能红,再证能绿,都不靠嘴说)

从 ci.yml 里**抽出该 step 的 run 块原样执行**(不是手敲等价命令):
  · 变色前(动态枚举改回写死 ./internal/agent/core/ ./cmd/waiter/)
    → EXIT=1,报 `race job 应恰有一步用 go list ./... 动态枚举包(实际 0 步)`
  · 还原后 → EXIT=0,报「CI 门禁自检通过:动态枚举 / 排除表校验 / 启动图判据步骤 / 交叉枚举 / 全部 run 步骤语法」

另在临时副本里抽查 5 个变异,4 个如期变红(写死枚举 / 去掉 -count=1 /
-race 不吃枚举 / cross 写死 cmd)。第 5 个「删掉排除表的原因校验」**没红** ——
已定位为脚本自身缺口,见下条,不在本次授权范围故未改。

## 四、已知遗留(未修,留给后续)

check-ci-gates.py 第 100 行用的是 `any("没有写原因" in r for ...)` ——
它只检查**提示文案还在**,不检查那段 `if [ -z "${reason// /}" ]` 校验逻辑本身。
于是把条件改成 `if false;` 而保留文案,断言仍然绿(实测 EXIT=0)。
判据被注释/文案顶包,与它自己在 docstring 里批判的「注释骗过 grep」是同一类错误。
属于该脚本的缺陷,本次任务授权只到「接进 CI」,故只记录不修。
This commit is contained in:
JianFeeeee
2026-10-24 11:55:28 +08:00
parent ed8f28ea6c
commit 49141fe6f0
2 changed files with 39 additions and 3 deletions

View File

@ -62,6 +62,39 @@ jobs:
- name: go vet ./...
run: go vet ./...
# ── CI 配置门禁自检(.github/scripts/check-ci-gates.py)──
#
# ## 为什么 CI 要检查自己的配置文件
#
# ci.yml 是「静默退化」的高发区:把 race 门的动态枚举改回写死包列表,
# 流水线照样绿(只是罩得少了),没人会发现。该脚本用 yaml.safe_load
# 解析(丢掉注释 ⇒ 「注释里写一句同名机制」顶不了包),断言这些仍在:
# · race 门动态枚举 + 真剔除 cmd/gui + go test -race 真吃了枚举结果
# · -skip 排除表每项都写了原因(缺原因那一步自己会失败)
# · go job 的「整机启动图判据」步骤还在、且带 -count=1
# · cross job 的 cmd 清单是实测枚举、构建真吃枚举结果
# · 每个 run 步骤的 bash 语法
#
# ★ 位置刻意放在 go test 之前:它是纯静态检查(只读 ci.yml,秒级,
# 无网络、无 cgo、不建库不起端口),而 go test ./... 要跑 20 分钟。
# 门禁本身坏掉应该第一时间红,不该等全量测试跑完才发现。
#
# ★ 不假设 runner 自带 pyyaml:先探测、缺了才装(幂等,几秒)。
# 「我以为 runner 有」正是假红/假绿的来源,代价比显式装一行高得多。
- uses: actions/setup-python@v7
with:
python-version: '3.12'
- name: CI 配置门禁自检(动态枚举 / 排除表 / 启动图判据不许静默退化)
run: |
set -euo pipefail
if ! python3 -c 'import yaml' 2>/dev/null; then
echo " pyyaml 缺失,安装"
python3 -m pip install --quiet pyyaml
fi
python3 -c 'import yaml; print(" pyyaml", yaml.__version__)'
python3 .github/scripts/check-ci-gates.py
# ./... 不点名 cmd/gui(该目录是纯 Electron,无 .go 文件):
# 显式 `go test ./cmd/gui` 会报 "no Go files",那是误报,不是缺陷。
- name: go test ./...