mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-01 06:47:29 +00:00
fix(ci): ID:19 空表假绿堵口 —— 空表须显式声明 # none,删空与有意清空可区分
check-ci-gates.py: TABLE 捕获体 `(.*?)` 允许空串,表被删空时静默走「无排除项」分支。 现在 ci.yml 里加显式空表标记校验(while 跳过 # 注释行),门脚本补正反自测: 合法 `# none` 必过、完全空体/只空行/非显式注释必红。 ID:18: bootgraph_test.go 失败面引用改为按区分词定位,不再依赖包名/行号。
This commit is contained in:
30
.github/scripts/check-ci-gates.py
vendored
30
.github/scripts/check-ci-gates.py
vendored
@ -106,12 +106,19 @@ for _n, r in evid:
|
|||||||
# v4(本条)用**合成行**注入 TABLE 再真跑:
|
# v4(本条)用**合成行**注入 TABLE 再真跑:
|
||||||
# · 不依赖任何真实排除项 ⇒ 排除项增删不会引起误报
|
# · 不依赖任何真实排除项 ⇒ 排除项增删不会引起误报
|
||||||
# · 真跑 ⇒ `&& false` 这类「形似而无效」的改动会被抓出来
|
# · 真跑 ⇒ `&& false` 这类「形似而无效」的改动会被抓出来
|
||||||
|
# v5(ID:19)堵空表假绿:v4 的 `(.*?)` 非贪婪且允许空串 ⇒ 排除表被删到
|
||||||
|
# 空串时捕获体为空,下游只看 "$n" -eq 0 就静默走「无排除项」分支,
|
||||||
|
# 排除项漏删/误删永远不会被任何人发现。现在要求**空表必须显式声明**
|
||||||
|
# (heredoc 里保留一行 `# none`),且下列三条各自有只违反它的坏输入做自测。
|
||||||
#
|
#
|
||||||
# 两条守卫必须**各自**用只违反它的输入来验,否则一条会顶另一条的包
|
# 两条守卫必须**各自**用只违反它的输入来验,否则一条会顶另一条的包
|
||||||
# (第一版我把 reason 与 ticket 同时清空,ticket 守卫兜住了,reason 守卫死没死看不出来)。
|
# (第一版我把 reason 与 ticket 同时清空,ticket 守卫兜住了,reason 守卫死没死看不出来)。
|
||||||
import subprocess as _sp
|
import subprocess as _sp
|
||||||
import tempfile as _tf
|
import tempfile as _tf
|
||||||
|
|
||||||
|
# 空表显式标记:与 ci.yml 里的判据同一串(改一处必须同时改另一处)。
|
||||||
|
_EMPTY_MARK = "# none"
|
||||||
|
|
||||||
_tbl = None
|
_tbl = None
|
||||||
for _n, _r in race:
|
for _n, _r in race:
|
||||||
if "计算 -race 排除表并打印" in (_n or ""):
|
if "计算 -race 排除表并打印" in (_n or ""):
|
||||||
@ -145,10 +152,33 @@ else:
|
|||||||
new_inner = (line + "\n" + inner) if inner.strip() else line
|
new_inner = (line + "\n" + inner) if inner.strip() else line
|
||||||
return _tbl[:_m.start(1)] + new_inner + _tbl[_m.end(1):]
|
return _tbl[:_m.start(1)] + new_inner + _tbl[_m.end(1):]
|
||||||
|
|
||||||
|
def _replace_table(new_inner):
|
||||||
|
"""把 heredoc 的捕获体整段替换成 new_inner(用来造各种空表形态)。"""
|
||||||
|
return _tbl[:_m.start(1)] + new_inner + _tbl[_m.end(1):]
|
||||||
|
|
||||||
# 正向:原样必须通过
|
# 正向:原样必须通过
|
||||||
if _run_body(_tbl).returncode != 0:
|
if _run_body(_tbl).returncode != 0:
|
||||||
fails.append("排除表步骤用当前 ci.yml 实跑不通过(正向基线坏)")
|
fails.append("排除表步骤用当前 ci.yml 实跑不通过(正向基线坏)")
|
||||||
|
|
||||||
|
# ── 正向:合法空表(显式 `# none` 标记)必须通过 ──
|
||||||
|
# ★ 这是"排除表可以合法为空"的必要性证明:最后一条 pkg 行被删掉后,
|
||||||
|
# 表本来就该空,不能一空就红。
|
||||||
|
if _run_body(_replace_table(_EMPTY_MARK)).returncode != 0:
|
||||||
|
fails.append("合法的空表(显式 `# none` 标记)竟被拒 —— 空表本应被允许,"
|
||||||
|
"守卫不能把「排除项删干净」与「漏写标记」混为一谈")
|
||||||
|
|
||||||
|
# ── 反向:空体没有任何标记 ⇒ 必须红(这就是 ID:19 的假绿入口)──
|
||||||
|
for _bad_name, _bad_inner in [
|
||||||
|
("完全空体", ""),
|
||||||
|
("只有空行", "\n"),
|
||||||
|
("只有空行+空白", "\n \n"),
|
||||||
|
("非显式标记的注释", "# 无排除项"),
|
||||||
|
]:
|
||||||
|
if _run_body(_replace_table(_bad_inner)).returncode == 0:
|
||||||
|
fails.append(
|
||||||
|
"空表形态「%s」竟通过 ⇒ 空表显式声明守卫已失效"
|
||||||
|
"(表被删空与有意清空无法区分,排除项漏删会静默变绿)" % _bad_name)
|
||||||
|
|
||||||
_probe = "test|internal/probe/synthetic|TestSyntheticProbe"
|
_probe = "test|internal/probe/synthetic|TestSyntheticProbe"
|
||||||
# 只打 reason:reason 空、ticket 有效
|
# 只打 reason:reason 空、ticket 有效
|
||||||
if _run_body(_inject(_probe + "||PROBE-TICKET")).returncode == 0:
|
if _run_body(_inject(_probe + "||PROBE-TICKET")).returncode == 0:
|
||||||
|
|||||||
13
.github/workflows/ci.yml
vendored
13
.github/workflows/ci.yml
vendored
@ -231,6 +231,10 @@ jobs:
|
|||||||
tests=""; pkgs=""; n=0
|
tests=""; pkgs=""; n=0
|
||||||
echo "════════ -race 排除表 ════════"
|
echo "════════ -race 排除表 ════════"
|
||||||
while IFS='|' read -r grain target test reason ticket; do
|
while IFS='|' read -r grain target test reason ticket; do
|
||||||
|
# ★ 注释行跳过:空表用一行 `# none` 显式声明(见本步骤开头与下方校验)。
|
||||||
|
# 先在里出现 `#` 开头的一行时,否则会被当成粒度 `# none` 报
|
||||||
|
# "粒度必须是 test 或 pkg"—— 标记本身反而把 step 撞红。
|
||||||
|
case "${grain}" in \#*) continue ;; esac
|
||||||
[ -z "${grain// /}" ] && continue
|
[ -z "${grain// /}" ] && continue
|
||||||
# ★ 结构校验:缺原因或缺单号 ⇒ 拒绝(不许无理由/无归属的排除)
|
# ★ 结构校验:缺原因或缺单号 ⇒ 拒绝(不许无理由/无归属的排除)
|
||||||
if [ -z "${reason// /}" ]; then
|
if [ -z "${reason// /}" ]; then
|
||||||
@ -264,6 +268,15 @@ jobs:
|
|||||||
esac
|
esac
|
||||||
done <<< "$TABLE"
|
done <<< "$TABLE"
|
||||||
|
|
||||||
|
# ★ 空表必须**显式声明**:heredoc 里保留且只保留一行 `# none`。
|
||||||
|
# 为何不能允许"什么都没写":那样"表被删空"与"有意清空"无法区分,
|
||||||
|
# 而门脚本(check-ci-gates.py)的正则捕获到空串后,会静默走下面的
|
||||||
|
# "无排除项"分支 —— 排除项漏删/误删都不会有任何人发现(假绿,ID:19)。
|
||||||
|
if [ "$n" -eq 0 ] && ! grep -qEi '^[[:space:]]*#[[:space:]]*none[[:space:]]*$' <<< "$TABLE"; then
|
||||||
|
echo "::error::-race 排除表为空却没有显式空表标记 —— 请在上面的 heredoc 里保留一行 \`# none\`"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$n" -eq 0 ]; then
|
if [ "$n" -eq 0 ]; then
|
||||||
echo " (无排除项)"
|
echo " (无排除项)"
|
||||||
echo "::warning title=-race 无排除项::排除表已空,可考虑删除本步骤与 evidence 步骤"
|
echo "::warning title=-race 无排除项::排除表已空,可考虑删除本步骤与 evidence 步骤"
|
||||||
|
|||||||
@ -15,7 +15,10 @@ package all
|
|||||||
//
|
//
|
||||||
// ★ 迁移没有削弱任何判据的能力:下面判据 5 的真相源(扫 `..` 源码树的
|
// ★ 迁移没有削弱任何判据的能力:下面判据 5 的真相源(扫 `..` 源码树的
|
||||||
// 类型大小)与宿主包无关,换宿主前后都照样咬得住「登记了但漏 import」。
|
// 类型大小)与宿主包无关,换宿主前后都照样咬得住「登记了但漏 import」。
|
||||||
// 变异亲测见本文件尾部「失败面」一节第 1–3 条。
|
// 变异亲测见本文件「## 失败面」一节里标题后注「逐条实测过」的那一处
|
||||||
|
// (不是 TestEveryRegisteredModuleIsCompiledIn 上方注「已实测咬红」的那一处)
|
||||||
|
// 第 1–3 条。★ 按**该节的区分词**找,不按行号/位置找:本文件有**两处**失败面
|
||||||
|
// 小节,且章节位置会随重构漂移。
|
||||||
//
|
//
|
||||||
// ## 这个文件补的是什么(此前完全没有的覆盖)
|
// ## 这个文件补的是什么(此前完全没有的覆盖)
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user