Files
update-client/Docs/01-客户端接入打包部署指南.md
T

275 lines
12 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.
# SimCAE Hub 客户端接入、打包和部署指南
本文说明 `update-client` 的当前实现。它保留 Launcher / Updater / Bootstrap 的桌面客户端机制,服务端协议使用 SimCAE Hub 当前 Go API。
## 1. 适用范围
当前客户端只覆盖项目已有页面和接口对应的能力:
1. 产品版本、软件发布、发布包和 Manifest。
2. 客户授权、在线命名用户席位和门户受控下载。
3. 在线检查更新、Manifest 拉取、受控下载、SHA-256 校验。
4. Manifest 签名验签、临时文件、断点重试、安装前后完整性校验。
邮箱、支付、灰度、告警等页面上没有的能力不属于当前范围。崩溃报告是 SimCAE Hub 保留的旧系统兼容后端接口,不属于 Launcher / Updater / Bootstrap 的更新链路;接入方需要崩溃上报时,按 `使用教学.md` 里的崩溃报告接口说明调用。
## 2. 客户端程序组成
| 程序 | 作用 |
| --- | --- |
| `Launcher` | 客户日常启动入口,负责导入配置、使用 `client_token` 检查更新、启动 Updater 或主程序 |
| `Updater` | 负责拉取 Manifest、下载发布包、校验文件、准备安装事务 |
| `Bootstrap` | 负责在需要替换运行中文件时接管安装,并把结果交回 Updater |
| `MainApp` | 示例主程序,用来验证 launch ticket 和安装后完整性校验 |
| `Common` | 配置、HTTP、票据、完整性校验等公共代码 |
## 3. 当前在线更新链路
1. `Launcher` 启动后读取服务端生成的 `config/app_config.json`,并把静态配置导入当前用户的运行配置。
2. 如果配置里没有 `api_base_url`,客户端会回退到编译进 EXE 资源中的 `server_config.json`
3. `Launcher` 确保存在 `device_id`,并检查 `client_token` 是否存在。
4. `Launcher` 调用 `GET /api/v1/client/update/authorized-check`,请求头带 `X-Client-Token`
5. 如果服务端返回可用发布,`Launcher` 启动 `Updater`,并传入产品编码、渠道、目标版本和发布 ID。
6. `Updater` 调用 `GET /api/v1/client/update/manifest`,请求头继续带 `X-Client-Token`
7. `Updater` 先校验服务端返回的 `manifestSha256`,再按配置决定是否强制要求 RSA-SHA256 签名。
8. `Updater` 从 Manifest 中读取每个文件的 `downloadUrl``sizeBytes``sha256`
9. 下载请求统一带 `X-Client-Token`
10. 下载使用 `.part` 临时文件保存进度,请求失败后按网络重试策略处理。
11. 文件下载完成后,客户端按 Manifest 校验文件大小和 SHA-256。
12. 安装前校验 staging 目录,安装完成后保存 Manifest 缓存,并可在主程序启动时再次校验已安装文件。
## 4. 关键配置字段
正式客户安装包里的 `config/app_config.json` 由服务端在上传发布包 ZIP 时自动生成。常用字段如下:
| 字段 | 说明 |
| --- | --- |
| `product_code` | SimCAE Hub 后台产品目录中的产品编码,例如 `stage2-dap` |
| `app_id` | 本地应用标识,默认和产品编码一致 |
| `channel` | 发布渠道,例如 `stable` |
| `current_version` | 当前本地安装版本,例如 `1.0.0` |
| `api_base_url` | 后端 API 地址,例如 `http://192.168.1.158:18000` |
| `client_token` | Launcher/Updater 调更新接口使用的部署级令牌,不绑定某一个客户 |
| `install_root` | 相对 Launcher/Updater 所在运行目录解析的更新根目录,决定 Updater、Bootstrap 和启动校验作用在哪棵目录 |
| `main_executable` | 相对运行目录解析的业务入口程序,通常是 `MainApp.exe` 或真实软件入口 |
| `launcher_executable` | 相对运行目录解析的 Launcher 文件名,主要用于提示和保持启动链路配置一致 |
| `updater_executable` | 相对运行目录解析的 Updater 文件名,Launcher 检查到更新后会启动它 |
| `bootstrap_executable` | 相对运行目录解析的 Bootstrap 文件名,Updater 需要替换文件时会启动它 |
| `platform` | 操作系统,例如 `windows``linux` |
| `arch` | 架构,例如 `x86_64` |
| `abi` | ABI,例如 `msvc`;没有时可留空 |
| `launch_token` | Launcher 和 MainApp 之间生成一次性启动票据的本地密钥 |
| `require_manifest_signature` | 是否强制要求 Manifest 必须带签名 |
| `verify_installed_on_start` | 主程序启动时是否按 Manifest 缓存校验已安装文件 |
`config/server_config.json` 会编译进客户端资源,作为 `api_base_url` 缺失时的兜底地址,当前测试服务器地址为:
`http://192.168.1.158:18000`
如果换服务器,可以改完该文件后重新编译客户端;正式客户包通常由服务端写入 `api_base_url`,不需要把 `server_config.json` 暴露给客户。
## 5. 编译
Windows Release 编译:
```powershell
cd update-client
cmake --preset x64-release
cmake --build --preset x64-release
```
Linux Release 编译:
```bash
cd update-client
cmake --preset linux-x64-release
cmake --build --preset linux-x64-release
```
## 6. 打包 SDK
Windows 示例:
```powershell
cd update-client
.\scripts\package-sdk.ps1 `
-SourceDir .\out\bin\Release `
-OutputDir .\dist\SimCAEHubUpdateClientSDK `
-ZipFile .\dist\SimCAEHubUpdateClientSDK.zip `
-SdkVersion 0.1.0
```
执行成功后会生成:
1. 展开目录:`update-client\dist\SimCAEHubUpdateClientSDK`
2. 对外提供的 SDK 压缩包:`update-client\dist\SimCAEHubUpdateClientSDK.zip`
默认不会打包 Qt DLL 和 Qt 插件目录,适合接入方已经有 Qt 运行环境,或者希望自己控制依赖部署的情况。
如果希望 SDK 包里带上 Qt runtime
```powershell
cd update-client
.\scripts\package-sdk.ps1 `
-SourceDir .\out\bin\Release `
-OutputDir .\dist\SimCAEHubUpdateClientSDK-with-qt `
-ZipFile .\dist\SimCAEHubUpdateClientSDK-with-qt.zip `
-SdkVersion 0.1.0 `
-IncludeQtRuntime
```
执行成功后会生成:
1. 展开目录:`update-client\dist\SimCAEHubUpdateClientSDK-with-qt`
2. 对外提供的 SDK 压缩包:`update-client\dist\SimCAEHubUpdateClientSDK-with-qt.zip`
其中 `-OutputDir` 是脚本整理 SDK 的展开目录,`-ZipFile` 是最终要交给接入方的 SDK 压缩包。接入方没有单独准备 Qt 运行库时,优先使用带 Qt runtime 的压缩包。
Linux 示例:
```bash
cd update-client
./scripts/package-sdk.sh \
--source-dir ./out/linux/bin \
--output-dir ./dist/SimCAEHubUpdateClientSDK-linux \
--archive ./dist/SimCAEHubUpdateClientSDK-linux.tar.gz \
--sdk-version 0.1.0
```
Linux 如需带上 Qt runtime,追加 `--include-qt-runtime`
SDK 包不会包含最终 `app_config.json``server_config.json``server_config.qrc``manifest_public_key.pem`。这些最终配置在完整客户软件包上传到 SimCAE Hub 后由服务端生成。
## 7. 客户安装包配置
接入方应把以下文件放到客户软件目录的根目录或 `bin/` 目录:
1. `Launcher`
2. `Updater`
3. `Bootstrap`
4. `MainApp` 或真实业务主程序
5. `config/` 目录,可以先为空
### 7.1 标准目录结构和路径口径
更新系统不要求必须放在客户软件根目录。它可以放在 `SimCAE/` 根目录,也可以放在 `SimCAE/bin/` 目录。关键是让客户端配置里的 `install_root` 和服务端 Manifest 文件路径使用同一套口径。
先区分三个目录概念:
| 概念 | 说明 |
| --- | --- |
| 运行目录 | Launcher、Updater、Bootstrap 所在目录,由客户端自动识别 |
| `install_root` | 相对运行目录解析的更新根目录,Updater 下载、校验、备份、回滚和 Bootstrap 替换文件都以它为范围 |
| Manifest `files[].path` | 服务端生成的安装相对路径,客户端会把它拼到 `install_root` 下面 |
目录结构一:更新系统放在软件根目录。
```text
SimCAE/
Launcher.exe
Updater.exe
Bootstrap.exe
MainApp.exe
config/
app_config.json
App/
...
```
对应配置:
```json
{
"install_root": ".",
"main_executable": "MainApp.exe",
"launcher_executable": "Launcher.exe",
"updater_executable": "Updater.exe",
"bootstrap_executable": "Bootstrap.exe"
}
```
目录结构二:更新系统和启动入口放在 `bin/`
```text
SimCAE/
bin/
Launcher.exe
Updater.exe
Bootstrap.exe
MainApp.exe
config/
app_config.json
App/
...
```
如果希望整个 `SimCAE/` 都属于更新范围,对应配置:
```json
{
"install_root": "..",
"main_executable": "MainApp.exe",
"launcher_executable": "Launcher.exe",
"updater_executable": "Updater.exe",
"bootstrap_executable": "Bootstrap.exe"
}
```
这表示 Launcher 从 `bin/` 启动 `MainApp.exe`Updater 和 Bootstrap 更新的是 `bin/` 的上一级,也就是整个 `SimCAE/`
服务端发布包路径要和客户端 `install_root` 对应:
| 客户端配置 | 服务端 Manifest 路径口径 |
| --- | --- |
| 更新系统在根目录,`install_root``.` | `MainApp.exe``App/xxx.dll` 相对 `SimCAE/` |
| 更新系统在 `bin/``install_root``..` | `bin/MainApp.exe``App/xxx.dll` 相对 `SimCAE/` |
当前管理后台“发布包”上传接口会使用上传文件名作为 `artifactName`,后端按安全文件名校验。当前稳定支持的是发布一个完整安装包或压缩包文件,或者把文件放在 `install_root` 根层级;还不是“自动解析压缩包并生成 App/bin 多文件 Manifest”的完整安装器。后续如果要让在线 Updater 直接把多个文件铺到 `App/``bin/` 等子目录,需要在现有发布包页面和 Go 后端上继续增强安全相对路径或 Manifest 文件清单生成能力。
如果后续要支持“更新系统在 `bin/`,但只校验和更新 `App/`”这类更窄的安装根目录,需要在管理后台和 Go 后端增加对应配置项,让服务端生成 `../App` 这类定制 `install_root`。当前服务端自动生成配置时只使用标准的 `.``..`
如果开启 `verify_installed_on_start`,客户端会扫描 `install_root` 下的 EXE 和 DLL。整包 Manifest 中 `required=true` 的核心文件必须存在且 SHA-256 匹配;`required=false` 的可选组件文件可以由 MaintenanceTool 管理,缺失时不会阻止启动。可选组件建议放在独立目录中,例如 `plugins/dap/`,不要和核心程序 DLL 混放。
上传完整客户软件 ZIP 时,服务端会根据发布包记录自动写入这些关键值:
```json
{
"product_code": "stage2-dap",
"channel": "stable",
"current_version": "1.1.0",
"api_base_url": "http://192.168.1.158:18000",
"client_token": "<由服务器 .env 配置>",
"install_root": ". 或 ..",
"platform": "windows",
"arch": "x86_64",
"abi": "msvc"
}
```
`install_root` 由服务端根据 Launcher 所在位置自动判断:更新系统在软件根目录时写 `.`,在 `bin/` 目录时写 `..`
## 8. 运行数据位置
Windows 运行数据目录:
`%LOCALAPPDATA%\SimCAE\HubUpdateClient\installations\<安装目录SHA256>\`
Linux 运行数据目录:
`$XDG_DATA_HOME/SimCAE/HubUpdateClient/installations/<安装目录SHA256>/`
未设置 `XDG_DATA_HOME` 时通常是:
`~/.local/share/SimCAE/HubUpdateClient/installations/<安装目录SHA256>/`
Manifest 缓存保存在运行数据目录下的 `update/manifest_cache`
## 9. 常见问题
1. 客户门户登录失败:检查客户门户账号是否已激活、客户是否生效、密码是否正确。
2. 检查更新没有结果:检查后台发布是否已发布、发布包是否可用、产品编码、渠道和平台参数是否一致。
3. 下载 401:检查发布包中的 `config/app_config.json` 是否由服务端生成,`client_token` 是否和服务器 `.env` 中的 `SIMCAE_CLIENT_TOKEN` 一致。
4. Manifest 校验失败:检查服务端 Manifest 是否被篡改、发布包 SHA-256 是否和实际文件一致。
5. 强制签名失败:确认 `manifest_public_key.pem` 与服务端私钥匹配;如果服务端暂未启用签名,测试环境可先把 `require_manifest_signature` 设为 `false`
6. 启动主程序失败:检查 `main_executable``install_root` 是否指向真实文件。