Files
opendance-windows/tasks/018-release-acceptance.md
zijunchiang e4e534f2a2 test(accept): 发布包级端到端验收(读包内 pck 而非源码)+ T-WIN-018
`build/verify.sh` 跑的是仓库源码(`godot --path .`),交付给用户的是 zip 里的
OpenDance.pck + OpenDance.exe,差别全在「导出」这一步:导出预设漏资源、pck 没
重新生成、版本号没同步、契约快照与 pck 不一致 —— 都只在包里才暴露。
本仓 v0.2.1 的 PE 版本元数据就是这么翻的车。

新增:
  * build/probe-release.gd —— 包内运行时探针。用
    `godot --headless --main-pack <pck> --script <探针>` 只读包内资源,断言并
    quit(0/1):
      1) application/config/version == 期望版本(界面版本唯一来源,§11.1);
      2) AboutScreen.app_version() == 期望版本(「关于」清单真正显示的值);
      3) 主场景可加载、四个 autoload 都在场景树里;
      4) 15 个关键资源(UI/模型/场景/网络/评分)在包内都可加载;
      5) 包内 Credits.CONTRACT_VERSIONS 与包内 contracts/VERSION 快照逐项一致
         (抓「pck 用旧契约构建、快照却拷了新的」)。
  * build/accept-release.sh —— 一个 zip(或已解压目录)跑完:sha256 → 解压
    (deflate 用 unzip / LZMA 用 7z,并检查没有 .partN 残留)→ 文件清单 →
    check-pe-version.sh → 包内 pck 启动 180 帧无 SCRIPT ERROR → 探针。
  * package-release.sh 结尾打印下一步验收命令;README 补用法。

实测(对**已发布**的 v0.2.2 资产重新下载后跑):
  sha256 OK;PE 版本资源 0.2.2;包内 pck 启动 180 帧无错误;
  包内 version=0.2.2;AboutScreen.app_version()=0.2.2;主场景
  res://scenes/main.tscn;autoload 齐备;15 项关键资源可加载;
  pck 内契约表与包内 contracts/VERSION 一致 → 发布包级验收全部通过。

反向验证:
  * 篡改包内 contracts/VERSION 的 rest-api=0.4.0 →
    ✗ ["rest-api: pck=0.5.0 快照=0.4.0"],退出码 1;
  * 期望版本写 0.2.1 对 v0.2.2 的包 → 三处版本断言全失败,退出码 1。

顺带修掉脚本自身一个缺陷:SHA256SUMS 用相对路径 + cd 到包目录后被二次拼接成
dist-release/dist-release/SHA256SUMS,导致 sha256 校验假失败(其余检查仍全绿,
很容易被忽略)。首跑时正是它把「全部通过」变成了失败。

verify.sh 仍全绿(754 通过 / 0 失败 / 5 跳过)。
2026-09-17 04:50:40 +08:00

4.1 KiB
Raw Permalink Blame History

T-WIN-018:发布包级端到端验收(读包内 pck,不是读源码)

  • 状态: done
  • 依赖: T-WIN-014(整包发布)/ T-WIN-017(PE 版本元数据)
  • 文档: v1.6 §5.7 / §7.5 / §11
  • 契约: 不涉及(验收流程)

为什么需要

build/verify.sh 跑的是仓库源码(godot --path .),而交付给用户的是 zip 里的 OpenDance.pck + OpenDance.exe。差别全在「导出」这一步:

只在导出后才可能出现的问题 源码侧能发现吗
导出预设漏了资源 / 资源没导入 ❌
pck 没重新生成(用了上一次的) ❌
版本号没同步进预设 → PE 资源与 pck 里都是旧值 ❌(v0.2.1 就这么翻的车)
契约快照文件拷了新的、pck 却是旧契约构建的 ❌

本项目已在两端因此翻车(本仓 v0.2.1 的 PE 版本元数据、Web v0.7.4 的实体注册), 所以三端统一要求:每次发布都要有一条读产物本身的验收(文档 §7.5)。

实现

文件 作用
build/probe-release.gd(新增) 包内运行时探针:用 godot --headless --main-pack <pck> --script <探针> 只读包内资源,断言并 quit(0/1)
build/accept-release.sh(新增) 对一个 zip(或已解压目录)跑完整验收

探针断言(5 类)

  1. ProjectSettings 的 application/config/version == 期望版本 —— 这是「关于」清单与 pck 的唯一来源(§11.1);
  2. AboutScreen.app_version() == 期望版本 —— 界面真正会显示的值;
  3. 主场景非空且可加载;四个 autoload(AppConfig / CatalogStore / PoseReceiver / ScoreService)都在场景树里;
  4. 15 个关键资源(UI / 模型 / 场景 / 网络 / 评分)在包内都可加载;
  5. 包内 Credits.CONTRACT_VERSIONS 与包内 contracts/VERSION 快照逐项一致 —— 抓「pck 用旧契约构建、快照却拷了新的」。

验收脚本步骤

  1. sha256 校验(有 SHA256SUMS 时);
  2. 解压(deflate 用 unzip,LZMA 用 7z)+ 文件清单完整性 (OpenDance.exe / OpenDance.pck / README.txt / THIRD_PARTY.md / contracts/VERSION); 顺带检查不允许有 .partN 分卷残留;
  3. exe 的 PE 版本资源 = 发布版本(复用 build/check-pe-version.sh);
  4. 用 Godot 直接加载包内 pck 跑 180 帧,断言无 SCRIPT ERROR;
  5. 执行包内运行时探针。

实测(对已发布的 v0.2.2 资产,重新下载后跑)

[accept] sha256 校验:opendance-windows-v0.2.2.zip: OK
  ✓ OpenDance.exe / OpenDance.pck / README.txt / THIRD_PARTY.md / contracts/VERSION
  ✓ PE 版本资源一致:FileVersion 0.2.2.0 / 资源字符串 0.2.2
  ✓ 包内 pck 启动 180 帧无错误(退出码 0)
  ✓ 包内 application/config/version = 0.2.2(期望 0.2.2)
  ✓ AboutScreen.app_version() = 0.2.2(「关于」清单会显示这个值)
  ✓ 主场景可加载:res://scenes/main.tscn
  ✓ autoload 齐备 ["AppConfig", "CatalogStore", "PoseReceiver", "ScoreService"]
  ✓ 关键资源全部可加载(15 项)
  ✓ pck 内契约表与包内 contracts/VERSION 快照一致
 发布包级验收全部通过

反向验证

负例 结果
把包内 contracts/VERSION 的 rest-api 改成 0.4.0(快照与 pck 不一致) ✗ pck 内契约表与包内 contracts/VERSION 快照一致:["rest-api: pck=0.5.0 快照=0.4.0"],退出码 1
期望版本写错(如 0.2.1 对 v0.2.2 的包) ✗ 三处版本断言全失败,退出码 1

首次运行还暴露了脚本自身的一个缺陷:SHA256SUMS 用相对路径 + cd 到包目录后 被二次拼接成 dist-release/dist-release/SHA256SUMS,导致 sha256 校验假失败 (而其余检查全绿,很容易被忽略)。已改为绝对路径,并把这条记在脚本注释里。

用法

GODOT_BIN=/path/to/godot bash build/accept-release.sh dist-release/opendance-windows-v0.2.2.zip
# 或对已解压目录:bash build/accept-release.sh dist-release/opendance-windows-v0.2.2