首跑时把 --expect <path> 当成位置参数传进来,被静默忽略(期望值路径只认 EXPECT_PATH 环境变量),于是 --skip-seed 时找不到期望值文件才报错 —— 属于 「参数写错却先跑一半」的糟糕体验。现在除 --skip-seed 外一律报错退出。 不影响发布产物(accept-integration.sh 不在 zip 内),故不新发版本。
143 lines
5.9 KiB
Bash
Executable File
143 lines
5.9 KiB
Bash
Executable File
#!/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 "============================================================"
|