CodePlanet U 盘离线更新部署规范
下载原文CodePlanet U 盘离线更新部署规范
> 客户端扫描路径:各已挂载卷根目录下的 CodePlanetrUpdate/manifest.json(AppPaths::usbUpdateManifestPath()) > 验签规则:与在线站 完全相同(同一 update.pub、同一 canonical JSON、同一 RSA-SHA256) > 优先级:Launcher 先 U 盘、后在线(U 盘 manifest 可读则不再请求 conbos) > R3 客户端行为:与在线站相同验签规则;Apply 已实装(见 §6)。
---
1. 重要区分:U 盘 ≠ 整个 bin/ 目录
| 概念 | 内容 |
|---|---|
| U 盘更新盘 | CodePlanetrUpdate/ 下的 manifest + 索引内的 zip/安装包 |
| 产线安装包 | 客户机 {InstallRoot}/ 全量运行时(见 [在线更新站部署规范.md](./在线更新站部署规范.md) §6) |
U 盘用于 离线分发项目包(及可选 Runtime 安装包),不是拷贝开发机整个 bin/ 文件夹。
---
2. U 盘目录结构(规范)
zipUrl / setupUrl 均为 相对 CodePlanetrUpdate/manifest.json 所在目录 的路径:
{U盘根}:/
└── CodePlanetrUpdate/
├── manifest.json
├── projects/
│ └── {name}/
│ └── {name}-{version}.zip
├── runtime/ # 可选
│ └── CodeRuntimeSetup-{version}.exe
├── launcher/ # 可选
│ └── CodePlanetrSetup-{version}.exe
└── editor/ # 可选
└── CodeEditorSetup-{version}.exe
离线制作也可直接拷贝本仓库 dist/CodePlanet/Update/{runtime,launcher,editor}/ 下 NSIS 产物到 U 盘对应子目录(与 manifest setupUrl 一致)。
2.1 首批示例(T37 对齐)
E:/
└── CodePlanetrUpdate/
├── manifest.json
└── projects/
└── demo/
└── demo-1.0.0.zip
2.2 与旧简图差异
早期文档曾写扁平路径 projects/demo-1.0.0.zip。以 manifest 内 zipUrl 为准;Launcher 代码使用:
const QDir usbRoot = QFileInfo(usbManifestPath).absoluteDir();
const QString zipPath = usbRoot.filePath(zipUrl);
因此推荐 projects/{name}/{name}-{version}.zip,与在线站布局 一致(便于同一 manifest 复用于线上与 U 盘)。
---
3. manifest.json
字段、签名、canonical JSON 规则 与在线站完全相同。 见:[在线更新站部署规范.md](./在线更新站部署规范.md) §3~§4。
同一份已签名 manifest 可同时:
1. 置于 https://www.conbos.cn/CodePlanetr/Update/manifest.json 2. 复制到 U:/CodePlanetrUpdate/manifest.json
相对路径 zipUrl 不变;只需保证 U 盘上对应 zip 文件存在。
---
4. 项目 zip 规范
与在线站 §5 相同:
| 项 | 规则 |
|---|---|
| 命名 | {name}-{version}.zip |
| 路径 | CodePlanetrUpdate/projects/{name}/{name}-{version}.zip |
| 内容 | 解压到 USER/projects/{folder}/;含 demo.yslib、scripts/ 等 |
| 校验 | manifest 中 zipSha256 为 zip 的 SHA256(hex 小写) |
| 覆盖策略(R3 Apply) | 解压时 保留目标目录已有 logs/ |
4.1 打包命令示例(PowerShell)
$projectDir = "E:\HuaweiMoveData\Users\MateBookXPro\Desktop\CodePlanetr\USER\projects\demoV1.0"
$outZip = "E:\CodePlanetrUpdate\projects\demo\demo-1.0.0.zip"
New-Item -Force -ItemType Directory (Split-Path $outZip) | Out-Null
Compress-Archive -Path "$projectDir\*" -DestinationPath $outZip -Force
Get-FileHash -Algorithm SHA256 $outZip
---
5. 公钥与客户端
- U 盘 不包含 私钥;仅携带 manifest 与数据包
- 验签公钥来自 已安装软件:
{InstallRoot}/config/update.pub - 验签失败 → Launcher 拒绝 该次更新建议,不阻断 用本地旧项目/旧版启动(T31)
---
6. Launcher 行为(R3)
flowchart TD
start[UpdateCheck] --> usb{U盘 manifest 存在?}
usb -->|是| readUsb[读取 U 盘 manifest.json]
usb -->|否| online[HTTPS 拉取 conbos manifest]
readUsb --> verify[RSA 验签]
online --> verify
verify -->|失败| skip[记录日志; 继续 Launch 旧版]
verify -->|成功| zipCheck{U盘: zip 是否存在?}
zipCheck -->|缺失| warn[Warning + 继续旧版]
zipCheck -->|齐全| suggest[建议更新 UI]
suggest --> applyChoice{用户 Apply?}
applyChoice -->|Skip| launchOld[Launch 当前版本]
applyChoice -->|Apply| sha256[zip SHA256]
sha256 --> staging[解压到 staging]
staging --> validator[ProjectValidator]
validator --> replace[原子替换; 保留 logs/]
replace -->|失败| rollback[回滚备份]
replace -->|成功| launchNew[Launch 新版本]
| 场景 | 预期(R3) |
|---|---|
U 盘无 CodePlanetrUpdate/ |
走在线;在线失败则跳过 |
| manifest 验签失败 | 日志 Update rejected;可 Launch |
| manifest 有效但 zip 缺失 | 日志缺包;可 Launch |
| manifest 有效且 zip 齐全 | 显示 Apply / Skip |
| Apply 成功 | 项目目录更新;logs/ 保留;Launch 新 yslib |
| Apply 失败 | 可读错误;旧项目可运行;备份在 %LOCALAPPDATA%/CodePlanet/update/backup/ |
---
7. 制作 U 盘步骤(运维)
1. 格式化 U 盘(FAT32/exFAT,便于产线 Windows 识别) 2. 创建 CodePlanetrUpdate/ 及 projects/{name}/ 3. 打包项目 zip,计算 SHA256 4. 编写 manifest → canonical JSON → RSA 签名 5. 复制 manifest.json 与 zip 到 U 盘 6. 插入产线 PC,启动 Launcher,确认日志/界面行为 7. (可选)使用 examples/update/manifest.bad-signature.json 验证验签失败不阻断
---
8. 测试
在线/U 盘 E2E 统一在 R3 Apply 实装后执行,见 [R3-更新Apply与E2E测试计划.md](../AST审计执行报告/R3-更新Apply与E2E测试计划.md)。
---
9. 参考
- [在线更新站部署规范.md](./在线更新站部署规范.md)
- [
docs/schemas/update-manifest-v1.schema.json](../schemas/update-manifest-v1.schema.json) - [
docs/附录-路径与日志约定.md](../附录-路径与日志约定.md)