Files
cmshoppe/docs/tasks/T-703.md
T

89 lines
5.2 KiB
Markdown
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.
---
id: T-703
title: 修复打包版缺少 backports 并增加 EXE 启动自检
phase: 8
deps: [T-625]
status: TODO
created: 2026-07-27
---
## 问题 / 背景
使用 `scripts/build_exe.ps1` 生成 `0.1.5.2` 发布包后,PyInstaller 和发布目录校验均显示成功,但运行 `cmshopee.exe` 会在应用入口执行前崩溃:
```text
File "PyInstaller\hooks\rthooks\pyi_rth_pkgres.py", line 170, in <module>
File "jaraco\context.py", line 17, in <module>
ModuleNotFoundError: No module named 'backports'
```
当前 Python 3.10 构建环境为 `PyInstaller 6.11.1`、`pyinstaller-hooks-contrib 2026.6`、`setuptools 80.9.0`。`setuptools` 内置的 `jaraco.context` 在 Python 3.12 以下执行 `from backports import tarfile`,但环境中没有独立的 `backports.tarfile` 分发包。PyInstaller 收集了 `setuptools/_vendor/jaraco`,没有收集对应的 `backports`;`build/cmshopee/warn-cmshopee.txt` 已记录 `missing module named backports`。
`requirements-build.txt` 目前只锁定 PyInstaller,没有锁定 `setuptools`、hooks 或 `backports.tarfile`,构建环境会随全局 Python 包变化。构建脚本只检查 EXE、`_internal` 和排除目录是否存在,没有真正启动产物,因此无效发布包仍被压缩并生成元数据。
## 方案
### 1. 锁定构建依赖
- `requirements-build.txt` 在继承运行依赖的基础上精确锁定:
- `pyinstaller==6.11.1`
- `pyinstaller-hooks-contrib==2026.6`
- `setuptools==80.9.0`
- `backports.tarfile==1.2.0`
- 构建文档明确打包前必须执行 `py -3.10 -m pip install -r requirements-build.txt`。
- 不把构建依赖加入普通用户运行依赖;最终用户仍只使用打包产物。
### 2. 显式收集 backports
- `cmshopee.spec` 在分析前确认 `backports.tarfile` 可导入;缺失时给出明确安装命令并终止构建。
- 把 `backports.tarfile` 加入主程序 `hiddenimports`,不再依赖 PyInstaller 对 `setuptools` vendored alias 的隐式分析。
- 独立更新器不导入 `pkg_resources/jaraco`,保持现有最小依赖配置。
### 3. 增加无副作用启动自检
- `main.py` 支持仅供构建使用的内部参数 `--startup-smoke-test`。
- 参数判断发生在 `app.gui` 导入成功之后,因此 PyInstaller 运行时钩子、`pkg_resources` 和 GUI 模块缺失仍会导致非零退出;导入成功后立即返回 0。
- 自检不得创建 `QApplication`、准备 `data/`、检查更新、启动会员检测、打开 Chrome、连接蝦皮或修改业务数据。
### 4. 构建脚本阻断无效发布
- PyInstaller 生成主程序并确认 onedir 结构后,使用隐藏窗口启动 `cmshopee.exe --startup-smoke-test`。
- 最长等待 30 秒;超时应终止自检进程并判定构建失败,非零退出码也判定失败。
- 只有启动自检通过后,才组装 release 目录、生成 manifest、压缩 ZIP 和生成 release metadata。
- 保留现有用户数据排除、独立更新器、版本命名和 SHA-256 逻辑。
### 5. 回归测试与发布复测
- 扩展 `tests/test_packaging.py`,检查构建依赖锁定、spec hidden import、内部自检参数以及构建脚本的超时/退出码检查顺序。
- 运行源码级 `main.py --startup-smoke-test`,确认不启动 GUI 且退出码为 0。
- 安装锁定构建依赖并真实运行一次打包脚本;运行打包后的 smoke test,确认不再出现 `No module named 'backports'`。
- 本轮重新生成的发布包仍按用户要求临时关闭并隐藏尚未完成的会员订阅检测;打包完成后恢复开发源码开关,不把临时关闭状态提交到 Git。
## 验收要点
- [ ] 构建环境安装 `requirements-build.txt` 后可导入 `backports.tarfile`。
- [ ] `cmshopee.spec` 显式包含 `backports.tarfile`,缺少依赖时构建立即失败。
- [ ] `py -3.10 main.py --startup-smoke-test` 正常退出,不创建 GUI 或业务数据。
- [ ] 构建脚本在压缩发布包前运行打包 EXE 启动自检,并处理非零退出和 30 秒超时。
- [ ] 新打包的 `cmshopee.exe --startup-smoke-test` 返回 0,不再出现 `No module named 'backports'`。
- [ ] 发布目录和 ZIP 不包含 `data/`、配置、数据库、图片、日志或登录态。
- [ ] 本轮发布包关闭并隐藏会员订阅检测,但源码在打包后恢复当前开发状态。
- [ ] 验证通过:
- `py -3.10 -m unittest discover -s tests -p test_packaging.py`
- `py -3.10 -m unittest discover -s tests`
- `py -3.10 -m ruff check app tests main.py`
- `py -3.10 -m compileall app main.py`
- `powershell -ExecutionPolicy Bypass -File scripts\build_exe.ps1`
- `git diff --check`
## 边界(不改什么)
- 不修改应用运行依赖、AI、数据库、Chrome/CDP、蝦皮采集或更新流程。
- 不移除软件版本更新检查、自动更新器、发布清单或 SHA-256 校验。
- 不把会员订阅临时关闭状态提交到 Git;只用于本轮修复后的发布包。
- 不提交构建目录、发布包、本地数据或真实配置。
## 执行记录
- 2026-07-27:根据 `0.1.5.2` 打包版真实启动异常创建任务。确认异常发生在 PyInstaller `pyi_rth_pkgres` 运行时钩子,早于 `main.py`;构建警告和发布目录共同证明 `setuptools` vendored `jaraco.context` 已收集、`backports` 未收集,与会员订阅临时开关无关。