并master(闸机提速与防作废批合回)——02分片并行+代码域起手自检+worktree素材同步,与对拍退役批同改闸脚本,冲突就地解

This commit is contained in:
DKChan committed 2026-10-30 02:46:54 +08:00
commit 6b17d8f307
4 files changed
+188 -15

No files matched your search

+57 -5
View File
@@ -300,6 +300,24 @@ if in_domain code; then
fi
fi
# ── 代码域起手自检(闸承载:只省烧闸,不做合回判定——真判定在 00–11 与合回 guard)──
if in_domain code; then
# worktree 素材同步:素材走 gitignore 不入 git,worktree 冷检出缺件=呈现断言红的环境成因;
# 主工作区直跑=脚本内自动无操作。
bash "$REPO/tools/sync_worktree_assets.sh"
# 熵增预检:垃圾目录/越界文件先于长跑批暴露(熵增闸在批末,撞上才红=整轮白烧)。
if ! "$PY" "$REPO/tools/repo_structure_audit.py" >"$STAMP_DIR/entropy_preflight.log" 2>&1; then
echo "[gates] 起手自检红:熵增预检不过——顶层目录越界/根文件异动,先清理再跑闸(日志 $STAMP_DIR/entropy_preflight.log)"
grep -aE "越界|✗|违例" "$STAMP_DIR/entropy_preflight.log" | tail -5 | sed 's/^/ | /'
exit 1
fi
# master 推进预警(worktree 才会触发):master 已越过本分支=合回 guard 第 6 况必拦,
# 先并 master 再出闸,省一轮白烧;本闸回执照出(开发期跑批不受阻)。
if [ -f "$RECEIPT" ] && ! git -C "$REPO" merge-base --is-ancestor master HEAD 2>/dev/null; then
echo "[gates] 警告:master 已推进至本分支之外——本闸回执照出,但合回前须并 master 重出闸。"
fi
fi
echo "闸机跑批 · 域=$DOMAIN · 仓库 $REPO"
echo "起跑 commit: $(git -C "$REPO" rev-parse --short HEAD 2>/dev/null || echo '非git目录')"
echo "python: $PY"
@@ -322,24 +340,58 @@ gate() { # gate <名称> <日志名> <命令...>
return 0
}
gate_unit() { # run_all 是 --script 模式,退出码为唯一判据
gate_unit() { # run_all 是 --script 模式,退出码为唯一判据;分片态=多 Godot 进程各跑一片
local name="02 单元与集成测试"
# 关联档选跑:把套件词列表经 --only= 传给 run_all(闸机来源标记 --only-source=gates,
# 入口据此打关联档横幅、不落「仅供开发期」免责句);全量态不传任何选跑参数。
local -a _user_args=()
if [ "$SCOPE" = related ] && [ -n "$ONLY_TERMS" ]; then
_user_args=(-- "--only=${ONLY_TERMS// /,}" --only-source=gates)
_user_args+=("--only=${ONLY_TERMS// /,}" "--only-source=gates")
fi
local _shards="${GATE_SHARDS:-4}"
echo ""
echo "════════════════════════════════════════════"
echo " $name(--script 模式,退出码为唯一判据)"
if [ "$SCOPE" = related ] && [ -n "$ONLY_TERMS" ]; then
echo " 关联档选跑:--only=$ONLY_TERMS"
fi
if [ "$_shards" -gt 1 ]; then
echo " 分片并行:$_shards 进程(GATE_SHARDS 可调,=1 回落单进程原路径)"
fi
echo "════════════════════════════════════════════"
( cd "$REPO" && "$GODOT" --headless --path "$(cygpath -m "$GAME")" --script res://tests/run_all.gd "${_user_args[@]}" ) \
>"$STAMP_DIR/unit.log" 2>&1
local rc=$?
local rc=0
if [ "$_shards" -le 1 ]; then
local -a _cmd=(--headless --path "$(cygpath -m "$GAME")" --script res://tests/run_all.gd)
[ ${#_user_args[@]} -gt 0 ] && _cmd+=(-- "${_user_args[@]}")
( cd "$REPO" && "$GODOT" "${_cmd[@]}" ) \
>"$STAMP_DIR/unit.log" 2>&1
rc=$?
else
# 分片并行:串行道套件由 run_all 内部分配钉第 1 片(RNG 日志会话跨片互踩,见其头注);
# 各片独立日志,退出码聚合(任一片非 0=闸红);日志按片序合并供错误扫描与指纹取材
#(指纹只取 FAIL 行排序集合、绿闸记 green,片序与合并不改变指纹)。
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 \
-- "${_user_args[@]}" "--shard=$k" "--shard-count=$_shards" ) \
>"$STAMP_DIR/unit_shard_$k.log" 2>&1 &
_pids+=($!)
done
local _shard_rc _any=0
for k in $(seq 1 "$_shards"); do
wait "${_pids[$((k - 1))]}"
_shard_rc=$?
echo "[run_all] 分片 $k/$_shards 退出码 $_shard_rc"
[ "$_shard_rc" -ne 0 ] && _any=1
done
[ "$_any" -ne 0 ] && rc=1
: >"$STAMP_DIR/unit.log"
for k in $(seq 1 "$_shards"); do
echo "── unit 分片 $k/$_shards ──" >>"$STAMP_DIR/unit.log"
cat "$STAMP_DIR/unit_shard_$k.log" >>"$STAMP_DIR/unit.log"
done
fi
# 三硬闸之二(脚本错误扫描):子套件的 SCRIPT ERROR/Parse Error 只写 stderr,入口内收不到,
# 只能在编排层扫本闸日志。命中即红——此类错误不改退出码、且会中断所在函数的剩余断言。
if [ "$rc" -eq 0 ] && ! "$PY" "$REPO/tools/error_scan.py" "$STAMP_DIR/unit.log" >>"$STAMP_DIR/unit.log" 2>&1; then
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env bash
# worktree 素材同步:主工作区 → 本 worktree 增量拷贝 gitignore 面(game/assets/art/ 终稿与 .import 边车)。
# 素材不入 git,worktree 冷检出与主区新收素材之间必然缺件——呈现/样张断言红的环境成因。
# 只在 worktree 生效(主工作区直跑=无操作);有新拷件或缺 .godot 时跑一次编辑器导入刷新
#(headless --script 模式不触发 import,素材在盘而 .ctex 缺位照样加载失败)。
# 用法:tools/sync_worktree_assets.sh(闸机 code 域起手自动调用;可单独手跑)
# 纪律:拷贝一律相对路径定位(在源根 cd 后按相对路径落盘)——绝对路径 --parents 会在
# 目标仓顶层误产盘符目录树(杂散目录即此误产,熵增闸判红)。
set -u
REPO="$(cd "$(dirname "$0")/.." && pwd)"
GITDIR="$(git -C "$REPO" rev-parse --git-dir 2>/dev/null)"
COMMON="$(git -C "$REPO" rev-parse --git-common-dir 2>/dev/null)"
if [ -z "$GITDIR" ] || [ -z "$COMMON" ] || [ "$GITDIR" = "$COMMON" ]; then
echo "[assets] 主工作区:无同步面"
exit 0
fi
MAIN="$(git -C "$REPO" worktree list --porcelain 2>/dev/null | sed -n 's/^worktree //p' | head -1)"
if [ -z "$MAIN" ]; then
echo "[assets] 取不到主工作区路径(git worktree list 为空),跳过同步"
exit 0
fi
MAIN="$(cd "$MAIN" && pwd)"
[ "$MAIN" = "$REPO" ] && exit 0
_copied=0
if [ -d "$MAIN/game/assets/art" ]; then
_new="$(comm -13 <(cd "$REPO/game/assets/art" 2>/dev/null && find . -type f | sort) \
<(cd "$MAIN/game/assets/art" && find . -type f | sort) | wc -l)"
if [ "$_new" -gt 0 ]; then
mkdir -p "$REPO/game/assets/art"
cp -ru "$MAIN/game/assets/art/." "$REPO/game/assets/art/"
_copied=$((_copied + _new))
fi
fi
_imports="$(comm -13 <(cd "$REPO/game" 2>/dev/null && find . -name '*.import' -type f | sort) \
<(cd "$MAIN/game" && find . -name '*.import' -type f | sort) | wc -l)"
if [ "$_imports" -gt 0 ]; then
(cd "$MAIN/game" && find . -name '*.import' -type f -print0) | while IFS= read -r -d '' f; do
if [ ! -f "$REPO/game/$f" ]; then
mkdir -p "$REPO/game/$(dirname "$f")"
cp "$MAIN/game/$f" "$REPO/game/$f"
fi
done
_copied=$((_copied + _imports))
fi
if [ "$_copied" -gt 0 ] || [ ! -d "$REPO/game/.godot" ]; then
echo "[assets] worktree 素材同步:补拷 $_copied 件(含 .import 边车),刷新导入缓存"
"${GODOT_BIN:-/d/code/godot/Godot_v4.7.2-stable_win64_console.exe}" \
--headless --editor --quit --path "$REPO/game" >/dev/null 2>&1
echo "[assets] 导入刷新完成"
else
echo "[assets] worktree 素材同步:无缺件"
fi
exit 0