2026-07-13 11:52:43 +08:00
|
|
|
|
---
|
|
|
|
|
|
id: T-617
|
|
|
|
|
|
title: 独立更新器事务替换与失败恢复
|
|
|
|
|
|
phase: 8
|
|
|
|
|
|
deps: [T-615]
|
2026-07-13 12:07:59 +08:00
|
|
|
|
status: DONE
|
2026-07-13 11:52:43 +08:00
|
|
|
|
created: 2026-07-13
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 问题 / 背景
|
|
|
|
|
|
|
|
|
|
|
|
Windows正在运行的 `cmshopee.exe` 和PyInstaller `_internal/` 可能被锁定,主程序不能安全覆盖自身。必须使用运行在安装目录之外的独立更新器,在旧主程序退出后执行完整目录切换;替换中任何失败都要恢复旧程序,不能留下半套版本。
|
|
|
|
|
|
|
|
|
|
|
|
## 方案
|
|
|
|
|
|
|
|
|
|
|
|
1. 新增最小化 `app/updater_entry.py` 与独立PyInstaller配置,构建无控制台、尽量仅依赖标准库的 `cmshopee-updater.exe`。它作为发布包程序文件存在,但执行前复制到 `%TEMP%/cmshopee-update-<随机值>/`,避免锁住安装目录或暂存目录。
|
|
|
|
|
|
2. 主程序以后通过结构化 `update-plan.json` 启动更新器,传入父进程PID、安装根、已验证暂存根、目标版本、事务ID和日志路径。更新器必须重新验证所有路径:绝对路径、安装根可写、暂存根属于 `.cmshopee-update/staging`、版本和manifest匹配;不得信任任意命令行目标。
|
|
|
|
|
|
3. 更新器有上限地等待主程序退出,并使用互斥锁/事务锁避免两个更新器或另一个cmshopee实例同时操作同一安装目录。启动更新器使用Windows隐藏进程标志,不弹黑色控制台窗口。
|
|
|
|
|
|
4. 替换采用根项目事务,不逐文件覆盖 `_internal/`:先将旧 `cmshopee.exe`、整个 `_internal/`、版本/说明/manifest/更新器移动到 `.cmshopee-update/backup/<旧版本>-<事务ID>/`,再把暂存中的对应根项目移动到安装根。这样新版删除的旧依赖不会残留。
|
|
|
|
|
|
5. `data/`、`.cmshopee-update/` 和安装根未知文件永不进入替换清单;更新器不得扫描后删除未知目录。包内清单若声明这些排除项,立即拒绝。
|
|
|
|
|
|
6. 每一步写事务journal。移动、权限、文件锁或启动新版失败时,按journal逆序移走不完整新版并恢复旧根项目;恢复失败要保留备份和中文日志,不得继续反复覆盖。
|
|
|
|
|
|
7. 替换成功后启动新 `cmshopee.exe` 并传入事务/目标版本标识。T-617只确认新进程已成功创建;启动健康确认和早期崩溃回滚由T-619完成。
|
|
|
|
|
|
8. 修改构建脚本和发布包,将 `cmshopee-updater.exe` 纳入manifest和zip,并声明当前更新器协议版本。
|
|
|
|
|
|
|
|
|
|
|
|
## 验收要点
|
|
|
|
|
|
|
|
|
|
|
|
- 更新器运行于安装目录外,等待旧主程序退出后才替换,不出现黑色命令窗口。
|
|
|
|
|
|
- `_internal/` 整目录切换,新版已删除的旧依赖不会残留。
|
|
|
|
|
|
- 注入任意移动失败、只读目录、文件锁、父进程不退出和新版启动失败时,旧程序根项目能恢复。
|
|
|
|
|
|
- `data/` 前后目录树与文件hash完全一致;安装根未知文件保持不变。
|
|
|
|
|
|
- 非法plan、越界路径、版本/manifest不一致、并发更新器均被阻断。
|
|
|
|
|
|
- release包包含可独立运行的更新器,且不包含用户数据。
|
|
|
|
|
|
|
|
|
|
|
|
## 测试要求
|
|
|
|
|
|
|
|
|
|
|
|
- 新增更新器纯逻辑/子进程集成测试:临时安装树成功替换、故障注入回滚、超时、并发锁、路径越界、`data/`不变。
|
|
|
|
|
|
- 更新打包测试,断言独立更新器产物、无控制台配置和manifest协议一致。
|
|
|
|
|
|
- 在Windows 10/11打包环境人工验证一次真实文件锁与自动重启;未执行时必须如实记录。
|
|
|
|
|
|
|
|
|
|
|
|
## 边界(不改什么)
|
|
|
|
|
|
|
|
|
|
|
|
- 不实现版本检查下载窗口;T-618负责GUI编排。
|
|
|
|
|
|
- 不做新版主窗口健康标记和失败版本熔断;T-619负责。
|
|
|
|
|
|
- 不删除用户备份,不修改CDP、AI、Excel、SQLite业务数据或蝦皮流程。
|
|
|
|
|
|
|
|
|
|
|
|
## 执行记录
|
|
|
|
|
|
|
2026-07-13 12:07:59 +08:00
|
|
|
|
- 2026-07-13:新增标准库独立更新器入口、结构化plan、父进程退出等待、安装目录事务锁、根项目整体切换、逐步journal、故障逆序回滚及临时目录隐藏启动能力。
|
|
|
|
|
|
- 2026-07-13:新增无控制台单文件 `cmshopee-updater.spec`,构建脚本将更新器纳入release与manifest;Windows 10 / Python 3.10 / PyInstaller 6.11.1实际构建成功,产物约6.7MB且使用windowed bootloader。
|
|
|
|
|
|
- 2026-07-13:干净worktree验证通过:ruff、compileall、完整unittest(408项)和 `git diff --check`。尚未在正式release上人工执行“锁住运行中主程序后自动退出、替换、重启”的端到端验收,该项留给T-618/T-619集成后执行。
|