Files
opendance-windows/build/accept-integration.sh
T
zijunchiang 6238873312 chore(accept): accept-integration.sh 拒绝未知参数
首跑时把 --expect <path> 当成位置参数传进来,被静默忽略(期望值路径只认
EXPECT_PATH 环境变量),于是 --skip-seed 时找不到期望值文件才报错 —— 属于
「参数写错却先跑一半」的糟糕体验。现在除 --skip-seed 外一律报错退出。

不影响发布产物(accept-integration.sh 不在 zip 内),故不新发版本。
2026-09-17 05:21:54 +08:00

143 lines
5.9 KiB
Bash
Executable File
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 bash
# ============================================================
# OpenDance Studio Windows 客户端 —— **跨端集成验收**(T-WIN-019)
#
# Windows 发布包里的客户端(包内 pck) × 真实 Web 服务端
#
# 为什么需要它:本仓单测打的是**假 HTTP 夹具**,Web 端测试只验自己那一侧。
# 两端各自绿灯 ≠ 契约字段真的对得上(字段名/嵌套/null/单位/范围都可能一侧对一侧错)。
# 契约 0.5.0 新增的 `scenes[]` 与重力/风向参数尤其如此。
#
# 本脚本:
# 1. 要求一个**已部署好的** Web 服务端(不做部署,与项目边界一致);
# 2. 用真实素材播种一份目录(真 VMD → 内部标准;真 PMX → VRM;场景 GLB + 物理参数),
# 并写出期望值 JSON(`--skip-seed` 可跳过,复用已有目录);
# 3. 用 Godot 加载**发布包里的 pck**(`--main-pack`)跑
# `build/integration/probe-integration.gd`,逐项断言并给出退出码。
#
# 用法:
# GODOT_BIN=/path/to/godot API_BASE=http://127.0.0.1:3000 \
# bash build/accept-integration.sh dist-release/opendance-windows-v0.2.3.zip
#
# # 已播种过、只重跑探针:
# GODOT_BIN=... API_BASE=... bash build/accept-integration.sh <zip> --skip-seed
#
# 环境变量:
# API_BASE Web 服务端基地址(默认 http://127.0.0.1:3000)
# OPENDANCE_SAMPLES_DIR 真实素材目录(默认 仓库根/示例文件)
# EXPECT_PATH 期望值 JSON 输出路径(默认 $WORK_DIR/catalog-expect.json)
# WORK_DIR 解包目录(默认 mktemp -d)
# ============================================================
set -uo pipefail
PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cd "$PROJECT_DIR"
TARGET="${1:-}"
SKIP_SEED=0
# 只认 --skip-seed;其余参数一律报错退出,避免「参数写错被静默忽略」
for arg in "$@"; do
case "$arg" in
--skip-seed) SKIP_SEED=1 ;;
"$TARGET") : ;;
*) echo "✗ 未知参数:$arg(只支持 --skip-seed;期望值路径用 EXPECT_PATH 环境变量)" >&2; exit 2 ;;
esac
done
API_BASE="${API_BASE:-http://127.0.0.1:3000}"
SAMPLES_DIR="${OPENDANCE_SAMPLES_DIR:-$PROJECT_DIR/../示例文件}"
WORK_DIR="${WORK_DIR:-$(mktemp -d)}"
EXPECT_PATH="${EXPECT_PATH:-$WORK_DIR/catalog-expect.json}"
FAILED=0
log() { printf '\033[1;34m[accept-int]\033[0m %s\n' "$*"; }
fail() { printf '\033[1;31m[accept-int] ✗ %s\033[0m\n' "$*" >&2; FAILED=1; }
if [ -z "$TARGET" ] || [ ! -e "$TARGET" ]; then
echo "用法:GODOT_BIN=... API_BASE=... bash build/accept-integration.sh <发布包 zip 或已解压目录> [--skip-seed]" >&2
exit 2
fi
# 必须**先**建目录:期望值 JSON 默认就落在 $WORK_DIR 下,播种阶段就要写它
mkdir -p "$WORK_DIR"
# ---- 0. 服务端可达性 ----
log "服务端:$API_BASE"
HEALTH="$(curl -sf -m 10 "$API_BASE/health" || true)"
if [ -z "$HEALTH" ]; then
fail "GET $API_BASE/health 不可达 —— 请先部署 Web 服务端(本项目不部署它)"
exit 1
fi
echo "$HEALTH" | node -e '
let s = ""; process.stdin.on("data", (d) => (s += d)).on("end", () => {
const j = JSON.parse(s);
console.log(` ✓ 服务端版本 ${j.version}|数据库 ${j.database?.connected ? "已连接" : "未连接"}|scenes.available=${j.scenes?.available}`);
});'
# ---- 1. 播种目录 ----
if [ "$SKIP_SEED" = "1" ]; then
log "跳过播种(--skip-seed);期望值文件:$EXPECT_PATH"
else
log "播种真实目录(真 VMD / 真 PMX / 场景 GLB + 物理参数)…"
if [ ! -d "$SAMPLES_DIR" ]; then
fail "找不到素材目录 $SAMPLES_DIR(用 OPENDANCE_SAMPLES_DIR 指定)"
exit 1
fi
if ! command -v node >/dev/null 2>&1; then
fail "播种需要 node(Web 端已依赖 node,本机应已安装)"
exit 1
fi
API_BASE="$API_BASE" OPENDANCE_SAMPLES_DIR="$SAMPLES_DIR" EXPECT_PATH="$EXPECT_PATH" \
node "$PROJECT_DIR/build/integration/seed-catalog.mjs" || { fail "播种失败"; exit 1; }
fi
if [ ! -f "$EXPECT_PATH" ]; then
fail "缺少期望值文件 $EXPECT_PATH(首次运行不要加 --skip-seed)"
exit 1
fi
# ---- 2. 取包内 pck ----
if [ -f "$TARGET" ]; then
log "解压发布包…"
if ! unzip -qq -o "$TARGET" -d "$WORK_DIR" 2>/dev/null; then
command -v 7z >/dev/null 2>&1 && 7z x -y -o"$WORK_DIR" "$TARGET" >/dev/null || { fail "解压失败"; exit 1; }
fi
PACKAGE_DIR="$(find "$WORK_DIR" -maxdepth 1 -mindepth 1 -type d | head -1)"
else
PACKAGE_DIR="$TARGET"
fi
PCK="$PACKAGE_DIR/OpenDance.pck"
[ -f "$PCK" ] || { fail "找不到包内 pck:$PCK"; exit 1; }
log "包内 pck:$PCK($(stat -c%s "$PCK") 字节)"
# ---- 3. Godot ----
GODOT_BIN="${GODOT_BIN:-}"
if [ -z "$GODOT_BIN" ]; then
for candidate in godot godot4 Godot; do
command -v "$candidate" >/dev/null 2>&1 && { GODOT_BIN="$candidate"; break; }
done
fi
[ -n "$GODOT_BIN" ] || { fail "未找到 Godot(用 GODOT_BIN=<路径> 指定,需与本项目同版本 4.7.x)"; exit 1; }
# ---- 4. 跨端探针 ----
log "跨端集成探针(包内客户端 × $API_BASE)…"
PROBE_LOG="$WORK_DIR/probe-integration.log"
if timeout 600 "$GODOT_BIN" --headless --main-pack "$PCK" \
--script "$PROJECT_DIR/build/integration/probe-integration.gd" \
-- --api-base "$API_BASE" --expect "$EXPECT_PATH" >"$PROBE_LOG" 2>&1; then
PROBE_OK=1
else
PROBE_OK=0
fi
grep -vE "^Godot Engine|^$" "$PROBE_LOG" | sed 's/^/ /'
[ "$PROBE_OK" = 1 ] || fail "跨端集成探针未通过"
echo ""
if [ "$FAILED" -ne 0 ]; then
echo "============================================================"
echo " 跨端集成验收失败(工作目录:$WORK_DIR)"
echo "============================================================"
exit 1
fi
echo "============================================================"
echo " 跨端集成验收全部通过(工作目录:$WORK_DIR)"
echo "============================================================"