目标
给 drift-check 增加两类"活体验证":(a) required check 活体存在性——ruleset 文本正确但实际匹配为空时检出;(b) PR liveness 侦测——auto-merge 已开但卡死的 PR 自动开 issue。
背景(源自 #81 §3.2 / §6)
- required check 是字符串精确匹配。
gate 是唯一 required check,一旦 job 改名或 workflow 重构,ruleset 静默匹配不到任何东西 → 变成"零 required check" → PR 裸奔合并。而 drift-check 现在只对账 ruleset JSON 文本,JSON 完全正确的同时实际匹配为空。文本对账 ≠ 生效验证。
- 门禁再严,如果每周有五个 PR 卡住等人手动捞,人还是瓶颈。drift-check 现在只看治理漂移,不看"流水线卡死"。需要:auto-merge 已开但 >N 小时未合并 / check pending 超时 / 应有而无 check run → 自动开 issue。
涉及文件
governance/drift-check.sh(新增两个检查段)
governance/expected-state.json(声明 liveness 阈值,如 pr_liveness_hours: 4)
.github/workflows/governance-drift.yml(如需新权限:读 PR/check runs——actions:read、pull-requests:read、checks:read)
执行步骤
- 活体验证段:对每个受管仓,拉最近 N 个(建议 20)已合并/打开的 PR 的 check runs(
gh api repos/.../commits/{sha}/check-runs),断言存在名为 gate 的 check run 且 conclusion 非空。若最近没有 PR 活动,退化为对默认分支 HEAD commit 断言 check run 存在。
- PR liveness 段:遍历受管仓所有 open PR,检出三类卡死:
auto_merge 已设置但 PR open 时间 > 阈值;
- 任一 required check
pending/queued 超过阈值;
- PR HEAD 上完全没有任何 check run(应有而无)。
命中即开 issue(打 drift label,复用 GM-1 通道),恢复后自动关闭。
- 阈值进
expected-state.json,可被对账。
- 权限评估:governance-drift workflow 用的 token 需能读各仓 check runs/PR,按最小权限补齐。
验收标准
- 把某测试仓 gate job 改名后,drift-check 下一次运行即报"required check 活体缺失"并开 issue;改回后 issue 自动关闭。
- 构造卡死 PR(阈值临时调低)后,drift-check 开出指明该 PR 的 liveness issue。
- 正常状态下不误报(连续 3 天运行无假 issue)。
测试方法(预先指定)
T1 required-check 活体缺失注入(核心,负向)
- 在测试仓
Use-up-Plan 的 PR 里把 workflow 中 job 名从 gate 改为 gate2(ruleset 仍要求 gate)。
- 手动触发 governance-drift workflow。
- 断言:workflow 检出
Use-up-Plan 的 required check 活体缺失并开 issue,issue 内容指明"ruleset 要求 gate 但实际 check runs 中无此名称"。
- 还原 job 名,再触发,断言 issue 自动关闭。
T2 PR liveness 注入(负向)
- 把 liveness 阈值临时改为 1 分钟(通过 expected-state.json 临时值或 workflow dispatch input 注入)。
- 在测试仓开一个 PR 并 enable auto-merge,但让其 check 永不完成(例如 push 一个含
if: false 使 gate 不产生的分支——产生"应有而无 check run"型卡死)。
- 触发 drift-check,断言:开出 liveness issue,内容含 PR 链接与卡死类型。
- 关闭测试 PR、还原阈值,断言 issue 关闭。
T3 误报控制(正向 soak)
- 合入后连续观察 3 天(drift-check 每小时跑):断言无一条 liveness/活体误报 issue。出现误报先修判定逻辑,不允许调大阈值掩盖。
依赖
- P1-1(drift-check 已覆盖 repo settings,本卡在其框架内扩展)
目标
给 drift-check 增加两类"活体验证":(a) required check 活体存在性——ruleset 文本正确但实际匹配为空时检出;(b) PR liveness 侦测——auto-merge 已开但卡死的 PR 自动开 issue。
背景(源自 #81 §3.2 / §6)
gate是唯一 required check,一旦 job 改名或 workflow 重构,ruleset 静默匹配不到任何东西 → 变成"零 required check" → PR 裸奔合并。而 drift-check 现在只对账 ruleset JSON 文本,JSON 完全正确的同时实际匹配为空。文本对账 ≠ 生效验证。涉及文件
governance/drift-check.sh(新增两个检查段)governance/expected-state.json(声明 liveness 阈值,如pr_liveness_hours: 4).github/workflows/governance-drift.yml(如需新权限:读 PR/check runs——actions:read、pull-requests:read、checks:read)执行步骤
gh api repos/.../commits/{sha}/check-runs),断言存在名为gate的 check run 且 conclusion 非空。若最近没有 PR 活动,退化为对默认分支 HEAD commit 断言 check run 存在。auto_merge已设置但 PR open 时间 > 阈值;pending/queued超过阈值;命中即开 issue(打
driftlabel,复用 GM-1 通道),恢复后自动关闭。expected-state.json,可被对账。验收标准
测试方法(预先指定)
T1 required-check 活体缺失注入(核心,负向)
Use-up-Plan的 PR 里把 workflow 中 job 名从gate改为gate2(ruleset 仍要求gate)。Use-up-Plan的 required check 活体缺失并开 issue,issue 内容指明"ruleset 要求 gate 但实际 check runs 中无此名称"。T2 PR liveness 注入(负向)
if: false使 gate 不产生的分支——产生"应有而无 check run"型卡死)。T3 误报控制(正向 soak)
依赖