fix(ci)+test(packaging): 关掉「门禁关死而自检全绿」三条路:outputs 绑定、判据步真跑、自检步指向
r2 复审:r1 那 11 条 + M3 已闭合(复审自己重放 12/12 红),但它新造的 40 条变异仍有 11 条漏网,
其中三条是「1 行改绿」:把 `probe.outputs.available` 改指向 `reason`/字面量(门永久关、每次绿);
判据步的退出码在标记表之外被吞(`|| echo 先忽略` / `; :` / `| cat` / `if !` / `true # 原行`,
复审真 bash 实测 exit 0);自检步被指向另一个脚本(自检根本不跑)。
三条 P1:
- 新判据 9:`probe.outputs.{available,log,png}` 必须逐个等于 `${{ steps.detect.outputs.<同名> }}`;
- 新判据 5:把 `id: judge` 的 `run` 原文真跑两次 —— 正例必须 exit 0、CPU 档日志必须 exit≠0,
且 `bash -e` 与**裸 bash** 各跑一遍(`; :` 只在后者现形,实测 `bash -e`=1 / 裸 bash=0)。
这一条一次封掉整类「吞码」,不依赖标记表;
- 判据 2:`id: wiring` 的 `run` 必须含 `gpu_shot_ci_selftest.py`,且 `vectors`/`wiring` 必须是**单条命令**
(不许换行/管道/`;`/`&`/反引号/`#`/`$(`)⇒ `|| echo 先忽略` 无从下手。
两条 P2:
- 新判据 10:`on:` 必须同时有 `push`(含 `main`)/`pull_request`/`workflow_call`;
- 「载体依赖」这条边界补进四处(自检 docstring / gpu-evidence.md §8 / README / workflow 头注释):
整个 workflow 被删掉就没有东西会跑自检,`guards.yml` 399/400 行塞不进去。
止步线(写进 docstring 与 §8):封闭清单 10 类 / 33 条变异向量;明确不覆盖「改判据脚本」「删掉整个
workflow」「求值器与 GitHub 语义差」「判据 4 的合法调用替换」;本文档不宣称「不可能被改成总是绿」;
**自 2026-11-11 起停止加固,扩项须由人类新开 mission**。
新增 `packaging/tests/gpu_shot_ci_expr.py`(`if:` 小求值器,判据脚本仍守 ≤400 行:377/215/64)。
This commit is contained in:
1 parent
2e9702790d
commit
8722c5a0ab
7 files changed
+358
-139
No files matched your search
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python3
|
||||
"""GitHub `if:` 表达式的小求值器(M253 / r2 复审返工,判据 3 用)。
|
||||
|
||||
为什么需要它:字符串存在性判据被两轮复审证伪过 —— `if: needs.probe.outputs.available == 'true' || always()`
|
||||
用 `in` 判照样绿,`if: true` 也绿。所以这里**真求值**:给 `needs.probe.outputs.available` 分别取
|
||||
`'true'` / `'false'` / `''`,门必须分别判真 / 假 / 假 —— 门到底还挂不挂,由语义决定,不由子串决定。
|
||||
|
||||
**只认一小撮语法,其余一律抛 `ConditionError`(调用方按红处理,宁可假红)**:
|
||||
`==` / `!=` / `&&` / `||` / 括号 / 单引号字符串 / 数字 / `needs.<job>.outputs.<名>` / `true|false|null` /
|
||||
`always()|success()|failure()|cancelled()`(后四个按「假定上游成功」取常量)。**不支持 `!`**:GitHub 与
|
||||
Python 的 `!` 优先级不同,认不出比误判安全。不是 GitHub 语义的替身,是它的一个保守子集。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
AVAILABLE_IDENT = "needs.probe.outputs.available"
|
||||
CALL_FUNCS = {"always": True, "success": True, "failure": False, "cancelled": False}
|
||||
_TOKEN_RE = re.compile(r"(?P<string>'[^']*')|(?P<number>\d+)|(?P<ident>[A-Za-z_][\w.\-]*)|(?P<op>==|!=|&&|\|\||[()!])")
|
||||
|
||||
|
||||
class ConditionError(Exception):
|
||||
"""`if:` 表达式认不出 —— 认不出即判红,绝不默认放过。"""
|
||||
|
||||
|
||||
def evaluate_condition(raw, available: str) -> bool:
|
||||
"""把 GitHub 的 `if:` 表达式求值。只认一小撮语法,其余抛 `ConditionError`(= 判红)。"""
|
||||
text = str(raw).strip()
|
||||
if text.startswith("${{") and text.endswith("}}"):
|
||||
text = text[3:-2].strip()
|
||||
for name, value in CALL_FUNCS.items():
|
||||
text = re.sub(rf"\b{name}\s*\(\s*\)", "true" if value else "false", text)
|
||||
if re.search(r"\b(" + "|".join(CALL_FUNCS) + r")\s*\(", text):
|
||||
raise ConditionError("函数只支持不带参数的形式")
|
||||
parts: list[str] = []
|
||||
pos = 0
|
||||
while pos < len(text):
|
||||
if text[pos].isspace():
|
||||
pos += 1
|
||||
continue
|
||||
match = _TOKEN_RE.match(text, pos)
|
||||
if not match:
|
||||
raise ConditionError(f"认不出的字符 {text[pos]!r}")
|
||||
pos = match.end()
|
||||
token = match.group()
|
||||
if match.lastgroup in ("string", "number"):
|
||||
parts.append(token)
|
||||
elif match.lastgroup == "ident":
|
||||
if token == AVAILABLE_IDENT:
|
||||
parts.append("__available")
|
||||
elif token in ("true", "false", "null"):
|
||||
parts.append({"true": "True", "false": "False", "null": "None"}[token])
|
||||
else:
|
||||
raise ConditionError(f"认不出的标识符 `{token}`")
|
||||
else:
|
||||
if token == "!":
|
||||
raise ConditionError("不支持 `!`(GitHub 与 Python 的优先级不同,宁可认不出)")
|
||||
parts.append({"&&": "and", "||": "or"}.get(token, token))
|
||||
source = " ".join(parts)
|
||||
try:
|
||||
return bool(eval(source, {"__builtins__": {}}, {"__available": available})) # noqa: S307 - 词表是白名单,见上
|
||||
except Exception as error: # noqa: BLE001 - 任何求值失败都按「认不出」处理
|
||||
raise ConditionError(f"求值失败({error}):`{source}`") from None
|
||||
Reference in new issue
Block a user