test(release): 逐文件核对「发布包 == 打标签的树」(T-AND-018)

新增 build/check_tracked_release.py(纯标准库):对包内每个文件按路径决定比较基准 ——
app-release.apk 比工作树构建结果,其余比 git show <tag>:<路径>;内容不一致 / 多余 /
构建产物缺失都会列出并退出 1。已接入 accept-release.sh(第 0 步)与 package-release.sh 提示。

实测(已发布的 v0.2.2 资产重新下载后):
  包内 12 个文件:源码/文档 11(与 tag v0.2.2 比)+ 构建产物 1(APK 比工作树构建)
  ✓ 逐文件一致:0 处不一致 / 0 处多余 / 0 处缺失
同行产品级验收(版本元数据 0.2.2/202、native 体检、契约快照、验签)同时全绿。

踩坑:第一版把 BUILD_OUTPUTS 的键一律当目录前缀,而 APK 是单文件,拼出
app-release.apk/ 导致「工作树缺失」误报;现区分目录前缀与精确文件名。
This commit is contained in:
2026-09-18 03:10:35 +08:00
parent c0d0937023
commit 0ee95c46e0
5 changed files with 243 additions and 1 deletions
+42
View File
@@ -0,0 +1,42 @@
# T-AND-018:逐文件核对「发布包 == 打标签的树」
- **状态**: done
- **依赖**: T-AND-014(发布包级验收)
- **文档**: v1.6 §6.3 / §7.7
- **契约**: 不涉及
## 为什么需要
「发布包里的东西必须等于打标签的那棵树」此前只靠抽查几个文件,
而抽查必然会漏(Web 端实测:发布包其实**包含** `web-server/test/**` 33 个文件,
且另有 177 个构建产物必须与工作树构建比对)。
## 实现
`build/check_tracked_release.py`(纯标准库,`.zip` 直接读)对包内**每一个**文件
按路径决定基准:
| 路径 | 比较基准 |
|--|--|
| `app-release.apk`(`BUILD_OUTPUTS`) | 工作树 `app/build/outputs/apk/release/app-release.apk` |
| 其余全部 | `git show <tag>:<路径>` |
任一内容不一致 / 包内多余 / 构建产物缺失都会列出并以非 0 退出。
已接入 `build/accept-release.sh`(第 0 步)与 `build/package-release.sh` 的提示。
## 实测(**已发布**的 v0.2.2 资产重新下载后跑)
```
[accept] 逐文件核对:发布包 == tag v0.2.2
包内 12 个文件:源码/文档 11(与 tag 比)、构建产物 1(与工作树构建比)
✓ 逐文件一致:0 处不一致 / 0 处多余 / 0 处缺失
✓ APK 版本元数据一致:0.2.2(versionCode 202)
✓ native 库体检通过 | ✓ 包内契约快照与仓库一致
发布包级验收全部通过
```
## 踩坑
脚本第一版把 `BUILD_OUTPUTS` 的键一律当**目录前缀**处理,而 APK 是**单文件**
(键不带 `/`),于是拼出 `app/build/outputs/.../app-release.apk/` 这种路径,
误报「构建产物在工作树缺失」。现在区分「以 `/` 结尾的目录前缀」与「精确文件名」。