Files
gplan-2/tools/run_smoke.py
T
DKChan 6c2dbc37c1 docs: ADR 体系废除 + architecture.md 确立为架构唯一事实源(2026-10-15 用户令:决策记录归 git commit log,不另存决策文档)
- 删除 design/dev/architecture/adr-0001~0007 共 7 份文件(内容留 git 历史可查)
- architecture.md:删「ADR 审计」「ADR 立项清单」两节;清除全文 ADR-000X 注记、QQ 表/S 表 ADR 引用;未决表关闭已落定项(QQ-01/02/03),立项清单在途事项转登记 QQ-11~14;补 A1 生成姿态事实、autoload 四件清单、board_generator 性能姿态;文档状态立「事实源地位」条
- CLAUDE.md:恢复 RNG 单点硬性红线(去 ADR-0007 引用);新增「架构事实唯一源」红线;规范导航架构行标注唯一事实源
- doc-conventions:§5 增「架构事实唯一源」行;§11 活文档清单补架构文档
- registry:architecture.yaml 删 18 处 adr 字段、autoload_set 补 SaveManager/MetaProgression、board_rending 更新为 Node2D 已落地事实;entities.yaml 12 处引用清除
- game/ 代码注释约 60 处清 ADR-000X 引用(事实与日期保留);豁免标记 ADR-0007-exempt → rng-seed-exempt(main.gd/static_scan.sh/architecture.md/06/iter27 五处同步)
- GDD/qa 实现报告/research 卡片/roadmap/tests README 引用全清;死链校验 1206 链接 0 死链、gdd_lint 0 不通过
- 代码中 adr/adr5 等为 adventure_runner 既有局部变量名(非 ADR 引用),未动
2026-10-15 23:52:30 +08:00

79 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
r"""run_smoke.py — 冒烟运行器(脚本错误外部门禁)
用法:
python tools/run_smoke.py # 默认跑切片全量冒烟(本机 Godot 固定路径)
python tools/run_smoke.py --script res://smoke/smoke_all.gd
python tools/run_smoke.py --godot <引擎路径> --path <切片目录> --timeout 180
背景(2026-09-19 台账 83 实证): GDScript 运行时脚本错误(SCRIPT ERROR)不改变进程退出码、
不计入冒烟失败数,且会静默中断所在冒烟函数的剩余断言——首跑「309 项 0 失败」实为断言未跑全。
进程内无脚本错误陷阱 API(GDScript 无 try/catch),故闸设在外部:本包装除退出码与摘要行外,
另扫输出中的 SCRIPT ERROR / Parse Error,命中即判失败。
三闸: ① 进程退出码 = 0;② 摘要行「冒烟完成:N 项检查,0 项失败」在案且失败数为 0;
③ 输出无「SCRIPT ERROR」「Parse Error」标记行。
"""
import argparse
import re
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
DEFAULT_GODOT = r"D:\code\godot\Godot_v4.7.2-stable_win64_console.exe"
DEFAULT_SLICE = ROOT / "game"
DEFAULT_SCRIPT = "res://smoke/smoke_all.gd"
SUMMARY_RE = re.compile(r"冒烟完成:(\d+) 项检查,(\d+) 项失败")
ERROR_MARKERS = ("SCRIPT ERROR", "Parse Error")
def main():
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
ap = argparse.ArgumentParser(description="冒烟运行器(脚本错误外部门禁)")
ap.add_argument("--godot", default=DEFAULT_GODOT)
ap.add_argument("--path", default=str(DEFAULT_SLICE), help="切片项目目录(含 project.godot)")
ap.add_argument("--script", default=DEFAULT_SCRIPT)
ap.add_argument("--timeout", type=int, default=180, help="外部超时秒数(硬性要求)")
args = ap.parse_args()
cmd = [args.godot, "--headless", "--path", args.path, "--script", args.script]
try:
proc = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8",
errors="replace", timeout=args.timeout)
except subprocess.TimeoutExpired:
print(f"[run_smoke] FAIL:外部超时(>{args.timeout}s——硬性要求)")
return 1
out = (proc.stdout or "") + (proc.stderr or "")
sys.stdout.write(out)
if out and not out.endswith("\n"):
print()
gates = []
if proc.returncode != 0:
gates.append(f"退出码 = {proc.returncode}(≠0)")
m = SUMMARY_RE.search(out)
if m is None:
gates.append("摘要行缺失(未检出「冒烟完成:N 项检查,M 项失败」——入口跑完前中断?)")
elif int(m.group(2)) != 0:
gates.append(f"冒烟失败 {m.group(2)} 项 / 共 {m.group(1)} 项")
hits = [ln.strip() for ln in out.splitlines() if any(k in ln for k in ERROR_MARKERS)]
if hits:
gates.append(f"脚本错误标记命中 {len(hits)} 行(首行: {hits[0][:140]}——脚本错误不计冒烟失败数,"
"且中断所在函数的剩余断言,必须人工排查)")
if m is not None:
print(f"[run_smoke] 摘要: {m.group(0)}")
if gates:
print("[run_smoke] FAIL——")
for g in gates:
print(f" - {g}")
return 1
print("[run_smoke] PASS(退出码 / 摘要失败数 / 脚本错误扫描 三闸全过)")
return 0
if __name__ == "__main__":
sys.exit(main())