工程(ci远端化·阶段二): 闸脚本跨平台化——新增tools/gate_platform.sh单点封装(平台探测/路径形式/纯bash带超时执行/孤儿清杀/进程计数,双平台双栖); run_all_gates cygpath×2换封装+PY解析加存在性守卫(修非Windows误选幽灵venv路径); probe_gate/render_gate/golden_baseline_refresh的cygpath/taskkill/PowerShell/tasklist/裸timeout全部收编封装,Windows侧原逻辑保留走平台分支; run_smoke/run_system_test DEFAULT_GODOT改GODOT_BIN环境变量优先; gdstyle_gate DEFAULT_BIN平台化(macOS=/usr/local/bin/gdstyle,自举件装v0.4.0 darwin包); 依据=第七轮容器实测断点清单+runner迁移Mac host模式裁决
This commit is contained in:
1 parent
0e7fdfb84c
commit
b3928f8167
8 files changed
+134
-28
No files matched your search
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
# 闸件跨平台件——平台探测/路径形式/带超时执行/Godot 孤儿清杀,Git Bash 与 macOS/Linux 双栖。
|
||||
# 单点定义:run_all_gates.sh / probe_gate.sh / render_gate.sh / golden_baseline_refresh.sh 共用(source 引入)。
|
||||
# 纪律:闸脚本禁裸调 coreutils timeout 与 Windows 专用件(taskkill/PowerShell/ps -W/tasklist/cygpath)——
|
||||
# 一律走本件封装;macOS 为 BSD 工具链(无 coreutils timeout,sed/stat 语义不同),裸调必断
|
||||
# (2026-11-03 远端 CI 迁移裁决:runner=Mac 本机 host 模式,禁再增 Windows 专用直调)。
|
||||
# 平台判定以 uname 为准(Git Bash=MINGW*,macOS=Darwin,Linux=Linux)。
|
||||
|
||||
gate_is_win() {
|
||||
case "$(uname -s 2>/dev/null)" in
|
||||
MINGW*|MSYS*|CYGWIN*|Windows_NT) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Godot --path 接受的项目路径形式:Windows 需 cygpath -m 混合斜杠,其他平台原样。
|
||||
gate_game_path() {
|
||||
if gate_is_win; then cygpath -m "$1"; else printf '%s' "$1"; fi
|
||||
}
|
||||
|
||||
# 杀整棵进程树(<pid>)——递归杀子进程后杀本进程。macOS/Linux 走 pgrep -P;
|
||||
# Windows 侧 MSYS kill 对其可见进程有效,带 wrapper 树的场景仍由调用方原 taskkill /T 逻辑负责。
|
||||
gate_kill_tree() {
|
||||
local p c
|
||||
kill -9 "$1" 2>/dev/null
|
||||
for c in $(pgrep -P "$1" 2>/dev/null); do gate_kill_tree "$c"; done
|
||||
}
|
||||
|
||||
# 带超时执行(coreutils timeout 的纯 bash 替代,双平台同语义):
|
||||
# gate_run_timeout <秒> <日志路径> <命令...>
|
||||
# 命令输出重定向到日志;退出码=命令退出码,超时=124(与 coreutils 语义一致,判据与既有闸一致)。
|
||||
# 实现=后台启动+守卫落标志文件(probe_gate run_suite 同款手法:taskkill 强杀后 wait 报 0 的
|
||||
# 假绿以标志文件纠偏);超时先杀整树再回 124。
|
||||
gate_run_timeout() {
|
||||
local t="$1" log="$2"; shift 2
|
||||
local kf
|
||||
kf="$(mktemp "${TMPDIR:-/tmp}/gatetime_XXXXXX")"
|
||||
"$@" >"$log" 2>&1 &
|
||||
local pid=$!
|
||||
( sleep "$t" 2>/dev/null
|
||||
touch "$kf"
|
||||
gate_kill_tree "$pid"
|
||||
true ) &
|
||||
local guard=$!
|
||||
wait "$pid"; local st=$?
|
||||
kill "$guard" 2>/dev/null; wait "$guard" 2>/dev/null
|
||||
if [ -f "$kf" ]; then
|
||||
gate_kill_tree "$pid"
|
||||
st=124
|
||||
fi
|
||||
rm -f "$kf"
|
||||
return "$st"
|
||||
}
|
||||
|
||||
# 列命令行含 <game路径> 的 Godot 进程 PID(孤儿清杀与批末残留清点共用)。
|
||||
# Windows:PowerShell WMI 按进程名+命令行匹配(console wrapper+真引擎都算);
|
||||
# macOS/Linux:ps 全表按「可执行含 godot+命令行含本 game 路径」过滤(ps 两平台同形)。
|
||||
gate_orphans() {
|
||||
local gp="$1"
|
||||
if gate_is_win; then
|
||||
local tmpf
|
||||
tmpf="$(mktemp "${TMPDIR:-/tmp}/gateorph_XXXXXX.ps1")"
|
||||
local gp_win
|
||||
gp_win="$(cygpath -m "$gp")"
|
||||
printf "Get-CimInstance Win32_Process -Filter \"Name like 'Godot%%'\" | Where-Object { \$_.CommandLine -like '*%s*' } | ForEach-Object { \$_.ProcessId }\n" "$gp_win" > "$tmpf"
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File "$(cygpath -w "$tmpf")" 2>/dev/null | tr -d '\r'
|
||||
rm -f "$tmpf"
|
||||
else
|
||||
ps -axo pid=,command= 2>/dev/null | awk -v g="$gp" 'tolower($0) ~ /godot/ && index($0, g) {print $1}'
|
||||
fi
|
||||
}
|
||||
|
||||
gate_kill_orphans() { # gate_kill_orphans <game路径>
|
||||
local p
|
||||
for p in $(gate_orphans "$1"); do
|
||||
if gate_is_win; then taskkill //F //PID "$p" >/dev/null 2>&1
|
||||
else kill -9 "$p" 2>/dev/null; fi
|
||||
done
|
||||
}
|
||||
|
||||
# 全局 Godot 进程计数(其他会话的仅报数不算账——批末残留清点的对照面)。
|
||||
gate_godot_count_all() {
|
||||
if gate_is_win; then tasklist 2>/dev/null | grep -ci '^Godot' || true
|
||||
else ps -axo comm= 2>/dev/null | grep -ci 'godot' || true
|
||||
fi
|
||||
}
|
||||
@@ -48,7 +48,10 @@ CONFIG = ROOT / "tools" / "gdstyle.toml"
|
||||
BASELINE = ROOT / "tools" / "gdstyle_baseline.txt"
|
||||
SCAN_DIRS = ["game/core", "game/data", "game/presentation"]
|
||||
PINNED_VERSION = "0.4.0"
|
||||
DEFAULT_BIN = "D:/code/gdstyle/gdstyle.exe"
|
||||
# 二进制定位:GDSTYLE_BIN 环境变量优先;Windows 本机固定路径保底,macOS/Linux 走 /usr/local/bin
|
||||
# (mac_setup.sh 自举件装钉定版 v0.4.0 darwin 包至此,远端 CI 与本机同判据)。
|
||||
DEFAULT_BIN = ("D:/code/gdstyle/gdstyle.exe" if sys.platform == "win32"
|
||||
else "/usr/local/bin/gdstyle")
|
||||
MAX_REPORT = 50
|
||||
MAX_VANISHED_REPORT = 20
|
||||
SHRINK_GUARD = 0.9 # 新键数 < 旧键数 * 本系数=骤降,refresh 拒写须 --force
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
set -u
|
||||
G="${GODOT_BIN:-/d/code/godot/Godot_v4.7.2-stable_win64_console.exe}"
|
||||
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
. "$REPO/tools/gate_platform.sh" # 跨平台件(平台探测/路径形式/带超时执行)
|
||||
GAME=""
|
||||
MODE="board"
|
||||
for a in "$@"; do
|
||||
@@ -24,7 +25,7 @@ for a in "$@"; do
|
||||
esac
|
||||
done
|
||||
GAME="${GAME:-$REPO/game}"
|
||||
GAME_WIN="$(cygpath -m "$GAME")"
|
||||
GAME_WIN="$(gate_game_path "$GAME")" # Godot --path 接受形式(Windows 混合斜杠,其他平台原样)
|
||||
TMP="$(mktemp -d /tmp/goldenrefresh_XXXXXX)"
|
||||
trap 'rm -rf "$TMP"' EXIT
|
||||
|
||||
@@ -36,7 +37,7 @@ if [ "$MODE" = "menu" ]; then
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
timeout 240 "$G" --path "$GAME_WIN" res://probe/shot_probe.tscn -- "$TMP/shots" >"$TMP/run.log" 2>&1
|
||||
gate_run_timeout 240 "$TMP/run.log" "$G" --path "$GAME_WIN" res://probe/shot_probe.tscn -- "$TMP/shots"
|
||||
st=$?
|
||||
grep -E "\[shot_probe\]" "$TMP/run.log" | tail -3
|
||||
if [ "$st" -ne 0 ] || [ ! -s "$TMP/shots/shot_menu.png" ]; then
|
||||
@@ -61,7 +62,7 @@ for a in assets/fonts/ui_font_fusion_pixel_zh_hans.ttf \
|
||||
fi
|
||||
done
|
||||
|
||||
timeout 180 "$G" --path "$GAME_WIN" res://probe/board_shot_probe.tscn -- "$TMP/shots" >"$TMP/run.log" 2>&1
|
||||
gate_run_timeout 180 "$TMP/run.log" "$G" --path "$GAME_WIN" res://probe/board_shot_probe.tscn -- "$TMP/shots"
|
||||
st=$?
|
||||
grep -E "\[board_shot\]" "$TMP/run.log" | tail -6
|
||||
if [ "$st" -ne 0 ] || [ ! -s "$TMP/shots/board_meta.json" ]; then
|
||||
|
||||
+17
-8
@@ -17,10 +17,12 @@
|
||||
# 四件带断言探针;默认段断言面零删减零改动(--full 只增不改)。
|
||||
# 渲染面归 render_gate.sh 正主(窗口化:shot_probe 七屏+fx_shot/board_shot 取证+棋盘 golden 逐像素)。
|
||||
# 用法: tools/probe_gate.sh [game目录] [--click] [--full] 缺省 game 目录=脚本所在仓库的 game/(worktree 内自动指向该 worktree)
|
||||
# 依赖: Git Bash(coreutils timeout/taskkill) + PowerShell;Godot 路径可用环境变量 GODOT_BIN 覆盖。
|
||||
# 依赖: Git Bash(coreutils timeout/taskkill) + PowerShell(Windows 侧);macOS/Linux 走 tools/gate_platform.sh
|
||||
# 共享跨平台件(Godot 路径两平台都可用 GODOT_BIN 环境变量覆盖)。
|
||||
set -u
|
||||
G="${GODOT_BIN:-/d/code/godot/Godot_v4.7.2-stable_win64_console.exe}"
|
||||
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
. "$REPO/tools/gate_platform.sh" # 跨平台件(平台探测/路径形式/带超时执行/孤儿清杀)
|
||||
GAME=""; WITH_CLICK=0; WITH_FULL=0
|
||||
for a in "$@"; do
|
||||
case "$a" in
|
||||
@@ -30,7 +32,7 @@ for a in "$@"; do
|
||||
esac
|
||||
done
|
||||
GAME="${GAME:-$REPO/game}"
|
||||
GAME_WIN="$(cygpath -m "$GAME")" # Godot --path 需 Windows 形式
|
||||
GAME_WIN="$(gate_game_path "$GAME")" # Godot --path 接受形式(Windows 混合斜杠,其他平台原样)
|
||||
TMP="$(mktemp -d /tmp/probegate_XXXXXX)"
|
||||
trap 'rm -rf "$TMP"' EXIT
|
||||
_rc=0
|
||||
@@ -68,12 +70,11 @@ verdict() { # verdict <探针名> <日志路径> <退出码> [签名标记]
|
||||
return 0
|
||||
}
|
||||
|
||||
orphans() { # 列出命令行含本 game 路径的 Godot 进程 PID(console wrapper+真引擎都算)
|
||||
printf "Get-CimInstance Win32_Process -Filter \"Name like 'Godot%%'\" | Where-Object { \$_.CommandLine -like '*%s*' } | ForEach-Object { \$_.ProcessId }\n" "$GAME_WIN" > "$TMP/k.ps1"
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File "$(cygpath -w "$TMP/k.ps1")" 2>/dev/null | tr -d '\r'
|
||||
orphans() { # 列出命令行含本 game 路径的 Godot 进程 PID(实现单点在 gate_platform.sh,双平台)
|
||||
gate_orphans "$GAME_WIN"
|
||||
}
|
||||
kill_orphans() {
|
||||
local p; for p in $(orphans); do taskkill //F //PID "$p" >/dev/null 2>&1; done
|
||||
gate_kill_orphans "$GAME_WIN"
|
||||
}
|
||||
|
||||
# 每段跑批统一走本函数:后台启动记 MSYS PID→WINPID,守卫进程到点先 taskkill /T 整树回收
|
||||
@@ -81,6 +82,14 @@ kill_orphans() {
|
||||
# 2026-10-25 在册挂死根源),后 kill -9 收 MSYS 侧。正常退出不动进程树;段后 kill_orphans 照跑兜底。
|
||||
run_suite() { # run_suite <timeout秒> <日志> <场景 res:// 路径>
|
||||
local t="$1" log="$2" scene="$3"
|
||||
if ! gate_is_win; then
|
||||
# macOS/Linux:无 console wrapper(Godot 单进程),走共享带超时执行+孤儿清杀兜底。
|
||||
local st
|
||||
gate_run_timeout "$t" "$log" "$G" --headless --path "$GAME_WIN" "$scene"
|
||||
st=$?
|
||||
gate_kill_orphans "$GAME_WIN"
|
||||
return "$st"
|
||||
fi
|
||||
local kf="$TMP/killed.$RANDOM"
|
||||
rm -f "$kf"
|
||||
"$G" --headless --path "$GAME_WIN" "$scene" >"$log" 2>&1 &
|
||||
@@ -108,7 +117,7 @@ run_suite() { # run_suite <timeout秒> <日志> <场景 res:// 路径>
|
||||
# 冷检出刷导入(.godot 不入 git,fresh worktree 首跑一次性付)
|
||||
if [ ! -f "$GAME/.godot/uid_cache.bin" ]; then
|
||||
echo "[probe_gate] 冷检出:editor --quit 刷导入(一次性,可到 1-2 分钟)"
|
||||
timeout 300 "$G" --headless --path "$GAME_WIN" --editor --quit >/dev/null 2>&1
|
||||
gate_run_timeout 300 "$TMP/refresh.log" "$G" --headless --path "$GAME_WIN" --editor --quit >/dev/null 2>&1
|
||||
kill_orphans
|
||||
fi
|
||||
|
||||
@@ -183,7 +192,7 @@ fi
|
||||
|
||||
echo "======== 残留检查(批末闸) ========"
|
||||
left="$(orphans | wc -l | tr -d ' ')"
|
||||
total="$(tasklist 2>/dev/null | grep -ci '^Godot' || true)"
|
||||
total="$(gate_godot_count_all)"
|
||||
echo "本闸残留 Godot=$left(必须0) 全局 Godot 进程=$total(其他会话的仅报数不算账)"
|
||||
if [ "$left" -ne 0 ]; then echo "[probe_gate] FAIL — 本闸残留未清零"; kill_orphans; _rc=1; fi
|
||||
if [ "$_rc" -eq 0 ]; then echo "[probe_gate] 全绿"; else echo "[probe_gate] 存在 FAIL,见上"; fi
|
||||
|
||||
+11
-11
@@ -27,22 +27,22 @@
|
||||
# 窗口化运行会短暂弹 Godot 窗口(本机可开窗口径);禁改 --headless 跑本闸
|
||||
# (headless 无渲染面,探针内 fail-fast 护栏会红——那是护栏生效不是闸红)。
|
||||
# 用法: tools/render_gate.sh [game目录] 缺省 game 目录=脚本所在仓库的 game/(worktree 内自动指向该 worktree)
|
||||
# 依赖: Git Bash(coreutils timeout/taskkill) + PowerShell + python(PIL);Godot 路径可用环境变量 GODOT_BIN 覆盖。
|
||||
# 依赖: tools/gate_platform.sh(双平台封装)+ python(PIL);Windows 侧另用 taskkill/PowerShell,macOS/Linux 走共享件;Godot 路径可用环境变量 GODOT_BIN 覆盖。
|
||||
set -u
|
||||
G="${GODOT_BIN:-/d/code/godot/Godot_v4.7.2-stable_win64_console.exe}"
|
||||
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
. "$REPO/tools/gate_platform.sh" # 跨平台件(平台探测/路径形式/带超时执行/孤儿清杀)
|
||||
GAME="${1:-$REPO/game}"
|
||||
GAME_WIN="$(cygpath -m "$GAME")" # Godot --path 需 Windows 形式
|
||||
GAME_WIN="$(gate_game_path "$GAME")" # Godot --path 接受形式(Windows 混合斜杠,其他平台原样)
|
||||
TMP="$(mktemp -d /tmp/rendergate_XXXXXX)"
|
||||
trap 'rm -rf "$TMP"' EXIT
|
||||
_rc=0
|
||||
|
||||
orphans() { # 列出命令行含本 game 路径的 Godot 进程 PID(console wrapper+真引擎都算)
|
||||
printf "Get-CimInstance Win32_Process -Filter \"Name like 'Godot%%'\" | Where-Object { \$_.CommandLine -like '*%s*' } | ForEach-Object { \$_.ProcessId }\n" "$GAME_WIN" > "$TMP/k.ps1"
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File "$(cygpath -w "$TMP/k.ps1")" 2>/dev/null | tr -d '\r'
|
||||
orphans() { # 列出命令行含本 game 路径的 Godot 进程 PID(实现单点在 gate_platform.sh,双平台)
|
||||
gate_orphans "$GAME_WIN"
|
||||
}
|
||||
kill_orphans() {
|
||||
local p; for p in $(orphans); do taskkill //F //PID "$p" >/dev/null 2>&1; done
|
||||
gate_kill_orphans "$GAME_WIN"
|
||||
}
|
||||
|
||||
scan_log() { # scan_log <段名> <日志>——脚本错误扫描;日志不可读(error_scan exit 2)同判红
|
||||
@@ -57,7 +57,7 @@ scan_log() { # scan_log <段名> <日志>——脚本错误扫描;日志不
|
||||
# 冷检出刷导入(.godot 不入 git,fresh worktree 首跑一次性付)
|
||||
if [ ! -f "$GAME/.godot/uid_cache.bin" ]; then
|
||||
echo "[render_gate] 冷检出:editor --quit 刷导入(一次性,可到 1-2 分钟)"
|
||||
timeout 300 "$G" --headless --path "$GAME_WIN" --editor --quit >/dev/null 2>&1
|
||||
gate_run_timeout 300 "$TMP/refresh.log" "$G" --headless --path "$GAME_WIN" --editor --quit >/dev/null 2>&1
|
||||
kill_orphans
|
||||
fi
|
||||
|
||||
@@ -66,7 +66,7 @@ if [ "$pre" -gt 0 ]; then echo "[render_gate] 预清本闸残留 Godot×$pre"; k
|
||||
|
||||
echo "======== shot_probe 七屏截图 → shot_checker A-D ========"
|
||||
SHOT="$TMP/shots"
|
||||
timeout 180 "$G" --path "$GAME_WIN" res://probe/shot_probe.tscn -- "$SHOT" >"$TMP/shot.log" 2>&1
|
||||
gate_run_timeout 180 "$TMP/shot.log" "$G" --path "$GAME_WIN" res://probe/shot_probe.tscn -- "$SHOT"
|
||||
st=$?; kill_orphans
|
||||
grep -E "\[shot_probe\]" "$TMP/shot.log" | tail -12
|
||||
if [ "$st" -eq 124 ] || [ "$st" -eq 137 ]; then
|
||||
@@ -83,7 +83,7 @@ scan_log "shot_probe" "$TMP/shot.log"
|
||||
|
||||
echo "======== fx_shot_probe 三时刻取证(Q7) ========"
|
||||
FX="$TMP/fxshots"
|
||||
timeout 180 "$G" --path "$GAME_WIN" res://probe/fx_shot_probe.tscn -- "$FX" >"$TMP/fx.log" 2>&1
|
||||
gate_run_timeout 180 "$TMP/fx.log" "$G" --path "$GAME_WIN" res://probe/fx_shot_probe.tscn -- "$FX"
|
||||
st=$?; kill_orphans
|
||||
grep -E "\[fx_shot_probe\]" "$TMP/fx.log" | tail -4
|
||||
if [ "$st" -eq 124 ] || [ "$st" -eq 137 ]; then
|
||||
@@ -108,7 +108,7 @@ fx_evidence "fx_final.png" 1
|
||||
|
||||
echo "======== board_shot_probe L1-L3 取证(Q7) ========"
|
||||
BD="$TMP/boardshots"
|
||||
timeout 180 "$G" --path "$GAME_WIN" res://probe/board_shot_probe.tscn -- "$BD" >"$TMP/bd.log" 2>&1
|
||||
gate_run_timeout 180 "$TMP/bd.log" "$G" --path "$GAME_WIN" res://probe/board_shot_probe.tscn -- "$BD"
|
||||
st=$?; kill_orphans
|
||||
grep -E "\[board_shot\]" "$TMP/bd.log" | tail -6
|
||||
if [ "$st" -eq 124 ] || [ "$st" -eq 137 ]; then
|
||||
@@ -172,7 +172,7 @@ fi
|
||||
|
||||
echo "======== 残留检查(批末闸) ========"
|
||||
left="$(orphans | wc -l | tr -d ' ')"
|
||||
total="$(tasklist 2>/dev/null | grep -ci '^Godot' || true)"
|
||||
total="$(gate_godot_count_all)"
|
||||
echo "本闸残留 Godot=$left(必须0) 全局 Godot 进程=$total(其他会话的仅报数不算账)"
|
||||
if [ "$left" -ne 0 ]; then echo "[render_gate] FAIL — 本闸残留未清零"; kill_orphans; _rc=1; fi
|
||||
if [ "$_rc" -eq 0 ]; then echo "[render_gate] 全绿"; else echo "[render_gate] 存在 FAIL,见上"; fi
|
||||
|
||||
@@ -44,6 +44,7 @@ GAME="$REPO/game"
|
||||
STAMP_DIR="$GAME/tests/.gates"
|
||||
RECEIPT="$STAMP_DIR/receipt.json"
|
||||
BASELINE="$STAMP_DIR/baseline.json"
|
||||
. "$REPO/tools/gate_platform.sh" # 跨平台件(平台探测/路径形式/带超时执行)
|
||||
|
||||
QUICK=0
|
||||
DOMAIN="full"
|
||||
@@ -93,8 +94,10 @@ fi
|
||||
# ── python 解释器解析:优先带 PIL 的 gamedev venv(渲染闸的 shot_checker/golden_compare 依赖),
|
||||
# 回落 PATH 上的 python。渲染闸的三个脚本要 PIL,用错解释器会假红。
|
||||
PY=""
|
||||
for cand in "/d/dev/python/envs/gamedev/Scripts/python.exe" "$(command -v python 2>/dev/null)" "python"; do
|
||||
for cand in "/d/dev/python/envs/gamedev/Scripts/python.exe" "$(command -v python 2>/dev/null)" "python3" "python"; do
|
||||
[ -z "$cand" ] && continue
|
||||
# 存在性守卫先行:Windows venv 路径在非 Windows 平台不存在,误选会让 PY 指向幽灵路径整批崩。
|
||||
command -v "$cand" >/dev/null 2>&1 || [ -x "$cand" ] || continue
|
||||
if "$cand" -c "import PIL" >/dev/null 2>&1; then PY="$cand"; break; fi
|
||||
[ -z "$PY" ] && PY="$cand"
|
||||
done
|
||||
@@ -348,7 +351,7 @@ gate_unit() { # run_all 是 --script 模式,退出码为唯一判据;分
|
||||
echo "════════════════════════════════════════════"
|
||||
local rc=0
|
||||
if [ "$_shards" -le 1 ]; then
|
||||
local -a _cmd=(--headless --path "$(cygpath -m "$GAME")" --script res://tests/run_all.gd)
|
||||
local -a _cmd=(--headless --path "$(gate_game_path "$GAME")" --script res://tests/run_all.gd)
|
||||
[ ${#_user_args[@]} -gt 0 ] && _cmd+=(-- "${_user_args[@]}")
|
||||
( cd "$REPO" && "$GODOT" "${_cmd[@]}" ) \
|
||||
>"$STAMP_DIR/unit.log" 2>&1
|
||||
@@ -360,7 +363,7 @@ gate_unit() { # run_all 是 --script 模式,退出码为唯一判据;分
|
||||
local -a _pids=()
|
||||
local k
|
||||
for k in $(seq 1 "$_shards"); do
|
||||
( cd "$REPO" && "$GODOT" --headless --path "$(cygpath -m "$GAME")" --script res://tests/run_all.gd \
|
||||
( cd "$REPO" && "$GODOT" --headless --path "$(gate_game_path "$GAME")" --script res://tests/run_all.gd \
|
||||
-- "${_user_args[@]}" "--shard=$k" "--shard-count=$_shards" ) \
|
||||
>"$STAMP_DIR/unit_shard_$k.log" 2>&1 &
|
||||
_pids+=($!)
|
||||
|
||||
+3
-1
@@ -18,13 +18,15 @@ r"""run_smoke.py — 冒烟测试运行器(脚本错误外部门禁)
|
||||
③ 输出无「SCRIPT ERROR」「Parse Error」标记行(标记清单供 tools/error_scan.py 复用,禁另写一份)。
|
||||
"""
|
||||
import argparse
|
||||
import os
|
||||
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"
|
||||
# 引擎定位:GODOT_BIN 环境变量优先(远端 CI 与非 Windows 平台的注入口),Windows 本机固定路径保底。
|
||||
DEFAULT_GODOT = os.environ.get("GODOT_BIN") or r"D:\code\godot\Godot_v4.7.2-stable_win64_console.exe"
|
||||
DEFAULT_SLICE = ROOT / "game"
|
||||
DEFAULT_SCENE = "res://tests/smoke_boot.tscn"
|
||||
SUMMARY_RE = re.compile(r"\[smoke\] 摘要:(\d+) 项检查,(\d+) 项失败")
|
||||
|
||||
@@ -19,13 +19,15 @@ r"""run_system_test.py — 系统测试运行器(脚本错误外部门禁)
|
||||
③ 输出无「SCRIPT ERROR」「Parse Error」标记行(标记清单经 tools/error_scan.py 复用,禁另写一份)。
|
||||
"""
|
||||
import argparse
|
||||
import os
|
||||
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"
|
||||
# 引擎定位:GODOT_BIN 环境变量优先(远端 CI 与非 Windows 平台的注入口),Windows 本机固定路径保底。
|
||||
DEFAULT_GODOT = os.environ.get("GODOT_BIN") or r"D:\code\godot\Godot_v4.7.2-stable_win64_console.exe"
|
||||
DEFAULT_SLICE = ROOT / "game"
|
||||
DEFAULT_SCRIPT = "res://tests/system_test.gd" # 系统测试宿主
|
||||
SUMMARY_RE = re.compile(r"(?:冒烟完成|\[system_test\] 摘要):(\d+) 项检查,(\d+) 项失败")
|
||||
|
||||
Reference in new issue
Block a user