Compare commits
13 Commits
f02e34525d
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 6fe4ae9b17 | |||
| 4edcdd733a | |||
| 087cc49118 | |||
| 397a4f1785 | |||
| 5745b27d66 | |||
| 17d23f8dab | |||
| 2b80c6de9f | |||
| 990fe8e771 | |||
| c291a36772 | |||
| d042f087db | |||
| 3be5101932 | |||
| da3a428a54 | |||
| 7887f31001 |
+12
-7
@@ -1,8 +1,13 @@
|
|||||||
**
|
**
|
||||||
!server/Dockerfile
|
!update-server/
|
||||||
!server/requirements.txt
|
!update-server/Dockerfile
|
||||||
!server/main.py
|
!update-server/requirements.txt
|
||||||
!server/db.py
|
!update-server/main.py
|
||||||
!server/minio_tool.py
|
!update-server/db.py
|
||||||
!server/tables.sql
|
!update-server/minio_tool.py
|
||||||
!server/admin.html
|
!update-server/tables.sql
|
||||||
|
!update-server/app/
|
||||||
|
!update-server/app/**
|
||||||
|
!update-server/admin-ui/
|
||||||
|
!update-server/admin-ui/dist/
|
||||||
|
!update-server/admin-ui/dist/**
|
||||||
|
|||||||
+82
-44
@@ -27,12 +27,20 @@ Desktop.ini
|
|||||||
*.rar
|
*.rar
|
||||||
|
|
||||||
# Requirement / handover documents kept outside Git
|
# Requirement / handover documents kept outside Git
|
||||||
client/*.pdf
|
update-client/*.pdf
|
||||||
client/*.doc
|
update-client/*.doc
|
||||||
client/*.docx
|
update-client/*.docx
|
||||||
server/*.doc
|
update-client/Docs/*.pdf
|
||||||
server/*.docx
|
update-client/Docs/*.doc
|
||||||
server/*交付说明*.md
|
update-client/Docs/*.docx
|
||||||
|
update-client/private/
|
||||||
|
update-client/pdf_requirements.txt
|
||||||
|
update-server/*.pdf
|
||||||
|
update-server/*.doc
|
||||||
|
update-server/*.docx
|
||||||
|
update-server/Docs/*.pdf
|
||||||
|
update-server/Docs/*.doc
|
||||||
|
update-server/Docs/*.docx
|
||||||
|
|
||||||
# C/C++ generated artifacts outside build directories
|
# C/C++ generated artifacts outside build directories
|
||||||
*.obj
|
*.obj
|
||||||
@@ -48,53 +56,88 @@ server/*交付说明*.md
|
|||||||
*.exe
|
*.exe
|
||||||
|
|
||||||
# Client: CMake / Visual Studio build outputs
|
# Client: CMake / Visual Studio build outputs
|
||||||
client/out/
|
update-client/out/
|
||||||
client/build/
|
update-client/build/
|
||||||
client/build-*/
|
update-client/build-*/
|
||||||
client/cmake-build-*/
|
update-client/cmake-build-*/
|
||||||
client/.cmake/
|
update-client/.cmake/
|
||||||
client/CMakeFiles/
|
update-client/CMakeFiles/
|
||||||
client/CMakeCache.txt
|
update-client/CMakeCache.txt
|
||||||
client/CMakeSettings.json
|
update-client/CMakeSettings.json
|
||||||
client/CMakeUserPresets.json
|
update-client/CMakeUserPresets.json
|
||||||
client/Testing/
|
update-client/Testing/
|
||||||
|
|
||||||
# Client: third-party/business binary drops and generated packages
|
# Client: third-party/business binary drops and generated packages
|
||||||
client/App/
|
update-client/thirdparty/
|
||||||
client/dist/
|
update-client/App/
|
||||||
|
update-client/dist/
|
||||||
|
|
||||||
# Client: local runtime state and credentials
|
# Client: local runtime state and credentials
|
||||||
|
update-client/config/app_config.json
|
||||||
|
update-client/config/client_identity.dat
|
||||||
|
update-client/config/local_state.json
|
||||||
|
update-client/config/version_policy.dat
|
||||||
|
update-client/config/*.local.json
|
||||||
|
update-client/config/*private*.pem
|
||||||
|
update-client/config/*private*.key
|
||||||
|
update-client/update/
|
||||||
|
update-client/update_temp/
|
||||||
|
|
||||||
|
# Server: Python environments and caches
|
||||||
|
update-server/venv/
|
||||||
|
update-server/.venv/
|
||||||
|
update-server/__pycache__/
|
||||||
|
update-server/**/*.py[cod]
|
||||||
|
update-server/.pytest_cache/
|
||||||
|
update-server/.mypy_cache/
|
||||||
|
update-server/.ruff_cache/
|
||||||
|
update-server/.coverage
|
||||||
|
update-server/htmlcov/
|
||||||
|
|
||||||
|
# Server: local configuration and secrets
|
||||||
|
update-server/.env
|
||||||
|
update-server/.env.*
|
||||||
|
!update-server/.env.example
|
||||||
|
!update-server/.env.docker.example
|
||||||
|
update-server/admin_token.sha256
|
||||||
|
update-server/keys/*private*.pem
|
||||||
|
update-server/keys/*private*.key
|
||||||
|
|
||||||
|
# Server: runtime databases, uploads, object storage and generated packages
|
||||||
|
update-server/*.db
|
||||||
|
update-server/*.db-journal
|
||||||
|
update-server/*.db-wal
|
||||||
|
update-server/*.db-shm
|
||||||
|
update-server/local_uploads/
|
||||||
|
update-server/upload_spool/
|
||||||
|
update-server/crash_storage/
|
||||||
|
update-server/minio_data/
|
||||||
|
update-server/runtime/
|
||||||
|
update-server/dist/
|
||||||
|
update-server/minio
|
||||||
|
|
||||||
|
# Server: runtime files
|
||||||
|
update-server/*.pid
|
||||||
|
update-server/*.log
|
||||||
|
|
||||||
|
# Docker/local generated files
|
||||||
|
.dockerignore.local
|
||||||
|
|
||||||
|
# Legacy paths before splitting into update-client/update-server submodules
|
||||||
|
client/out/
|
||||||
|
client/build/
|
||||||
|
client/App/
|
||||||
|
client/dist/
|
||||||
client/config/app_config.json
|
client/config/app_config.json
|
||||||
client/config/client_identity.dat
|
client/config/client_identity.dat
|
||||||
client/config/local_state.json
|
client/config/local_state.json
|
||||||
client/config/version_policy.dat
|
client/config/version_policy.dat
|
||||||
client/config/*.local.json
|
|
||||||
client/config/*private*.pem
|
|
||||||
client/config/*private*.key
|
|
||||||
client/update/
|
|
||||||
client/update_temp/
|
|
||||||
|
|
||||||
# Server: Python environments and caches
|
|
||||||
server/venv/
|
server/venv/
|
||||||
server/.venv/
|
server/.venv/
|
||||||
server/__pycache__/
|
server/__pycache__/
|
||||||
server/**/*.py[cod]
|
server/**/*.py[cod]
|
||||||
server/.pytest_cache/
|
|
||||||
server/.mypy_cache/
|
|
||||||
server/.ruff_cache/
|
|
||||||
server/.coverage
|
|
||||||
server/htmlcov/
|
|
||||||
|
|
||||||
# Server: local configuration and secrets
|
|
||||||
server/.env
|
server/.env
|
||||||
server/.env.*
|
server/.env.*
|
||||||
!server/.env.example
|
|
||||||
!server/.env.docker.example
|
|
||||||
server/admin_token.sha256
|
|
||||||
server/keys/*private*.pem
|
|
||||||
server/keys/*private*.key
|
|
||||||
|
|
||||||
# Server: runtime databases, uploads, object storage and generated packages
|
|
||||||
server/*.db
|
server/*.db
|
||||||
server/*.db-journal
|
server/*.db-journal
|
||||||
server/*.db-wal
|
server/*.db-wal
|
||||||
@@ -106,10 +149,5 @@ server/minio_data/
|
|||||||
server/runtime/
|
server/runtime/
|
||||||
server/dist/
|
server/dist/
|
||||||
server/minio
|
server/minio
|
||||||
|
|
||||||
# Server: runtime files
|
|
||||||
server/*.pid
|
server/*.pid
|
||||||
server/*.log
|
server/*.log
|
||||||
|
|
||||||
# Docker/local generated files
|
|
||||||
.dockerignore.local
|
|
||||||
|
|||||||
+4
-4
@@ -1,8 +1,8 @@
|
|||||||
[submodule "server"]
|
[submodule "update-server"]
|
||||||
path = server
|
path = update-server
|
||||||
url = https://git.alimzs.com:6443/nikelaluo/update-server.git
|
url = https://git.alimzs.com:6443/nikelaluo/update-server.git
|
||||||
branch = master
|
branch = master
|
||||||
[submodule "client"]
|
[submodule "update-client"]
|
||||||
path = client
|
path = update-client
|
||||||
url = https://git.alimzs.com:6443/nikelaluo/update-client.git
|
url = https://git.alimzs.com:6443/nikelaluo/update-client.git
|
||||||
branch = master
|
branch = master
|
||||||
|
|||||||
-1
Submodule client deleted from b06e003502
-1
Submodule server deleted from 9a6ac1e4ed
Submodule
+1
Submodule update-client added at d9e32c6cea
Submodule
+1
Submodule update-server added at 801622904c
@@ -0,0 +1,73 @@
|
|||||||
|
# 项目交付状态一页纸
|
||||||
|
|
||||||
|
这份只看当前状态,不记录开发历史。更详细的背景和概念看 `项目总览.md`。
|
||||||
|
|
||||||
|
## 项目是什么
|
||||||
|
|
||||||
|
这是 SimCAE 自动升级、授权、版本发布和崩溃报告服务的一套客户端 SDK + 服务端后台。
|
||||||
|
|
||||||
|
```text
|
||||||
|
update-client/ Launcher / Updater / Bootstrap、SDK 打包、客户端接入文档
|
||||||
|
update-server/ FastAPI 后端、Vue 管理后台、Docker 离线部署包
|
||||||
|
```
|
||||||
|
|
||||||
|
## 当前可以交付什么
|
||||||
|
|
||||||
|
- Windows/Linux 客户端升级运行时:`Launcher`、`Updater`、`Bootstrap`。
|
||||||
|
- 客户端 SDK 包:包含运行程序、配置模板、接入文档、最终客户端打包脚本。
|
||||||
|
- 服务端 Docker 离线部署包:包含 API 镜像、管理后台、MinIO、compose 文件、配置模板和 Manifest 签名密钥。
|
||||||
|
- 管理后台:基于 pure-admin-thin / Vue3 / Element Plus / TypeScript / Vite。
|
||||||
|
- 后端:基于 FastAPI,已经按 routes / services / repositories / schemas / core 分层,并支持 JWT / RBAC。
|
||||||
|
- 后端自动化测试:pytest,覆盖登录/JWT、License/设备、更新检查、发布和崩溃报告核心流程。
|
||||||
|
|
||||||
|
## 已完成的核心功能
|
||||||
|
|
||||||
|
- 应用、渠道、版本发布、策略管理。
|
||||||
|
- License 授权、设备登记、设备数限制。
|
||||||
|
- Manifest 生成、SHA-256 文件校验、私钥签名、公钥验签。
|
||||||
|
- 客户端检查更新、下载、安装、健康检查、失败回滚。
|
||||||
|
- 升级日志、下载日志、管理员审计日志。
|
||||||
|
- 发布清单 `发布清单.txt` / `release_manifest.txt`,支持选择发布哪些文件、排除哪些文件。
|
||||||
|
- 发布压缩包支持 zip、tar.gz、tgz、tar.bz2、tbz2、rar。
|
||||||
|
- 发布任务后台化:上传完成后,服务端后台继续处理,页面轮询任务状态。
|
||||||
|
- 崩溃报告上传、查询、文件下载和符号包上传接口。
|
||||||
|
- Git 标签清单:管理后台策略可控制 Launcher 是否生成 `tags.txt`;服务端用 `GITEA_TOKEN` 拉取仓库 tags,客户端永远拿不到 token,只拿整理后的文本。
|
||||||
|
|
||||||
|
## 当前要特别注意
|
||||||
|
|
||||||
|
- `keys/manifest_private_key.pem` 必须在真实服务端部署包里,但不能进 Git、不能给客户端、不能公开传播。
|
||||||
|
- 客户端 SDK 里的 `manifest_public_key.pem` 必须和服务端私钥配套。
|
||||||
|
- `config/server_config.json` 会编进客户端程序;改服务端地址后必须重新编译 Launcher / Updater / Bootstrap。
|
||||||
|
- `GITEA_TOKEN` 只允许放在服务端 `.env`,不要写进客户端配置、不要给 Launcher、不要提交 Git。
|
||||||
|
- `app_config.json` 首次启动会导入当前用户配置区,非空配置导入后会清空为 `{}`。
|
||||||
|
- Manifest 缓存和设备身份等运行态文件默认在当前用户数据目录,不再默认写安装目录。
|
||||||
|
- 公网部署前仍建议改默认 token/password、配置 HTTPS、限制 MinIO 控制台暴露范围、收紧 CORS。
|
||||||
|
|
||||||
|
## 打包入口
|
||||||
|
|
||||||
|
客户端 SDK:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cd update-client
|
||||||
|
.\scripts\package-sdk.ps1 -SourceDir .\out\bin\Release -OutputDir .\dist\UpdateClientSDK -ZipFile .\dist\UpdateClientSDK.zip -SdkVersion 0.1.0
|
||||||
|
```
|
||||||
|
|
||||||
|
服务端 Docker 离线包:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd update-server
|
||||||
|
bash ./scripts/package-offline-server.sh --version 0.1.0 --output-dir ./dist/SimCAEServerDockerPackage
|
||||||
|
```
|
||||||
|
|
||||||
|
服务端自动化测试:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd update-server
|
||||||
|
./venv/bin/python3 -m pytest -q
|
||||||
|
```
|
||||||
|
|
||||||
|
## 还不算完成的事情
|
||||||
|
|
||||||
|
- 真实 Linux 版 SimCAE 主程序还没有交付联调。
|
||||||
|
- 公网生产级安全加固还未全部自动化,例如登录限流、HTTPS 自动化、默认密钥强制替换。
|
||||||
|
- 数据库迁移仍是 `tables.sql` + 手写兼容逻辑,长期维护可考虑 Alembic。
|
||||||
@@ -2,15 +2,25 @@
|
|||||||
|
|
||||||
本文档用于总览当前项目的目标、已实现能力、主要目录、交付物和后续注意事项。适合在提交代码、交接项目或给他人快速了解项目时阅读。
|
本文档用于总览当前项目的目标、已实现能力、主要目录、交付物和后续注意事项。适合在提交代码、交接项目或给他人快速了解项目时阅读。
|
||||||
|
|
||||||
|
如果只想快速判断“现在能交付什么、还要注意什么”,先看根目录的 `项目交付状态一页纸.md`。
|
||||||
|
|
||||||
## 一、项目整体是什么
|
## 一、项目整体是什么
|
||||||
|
|
||||||
本项目是一套面向 Windows 客户端软件的自动升级与版本控制系统,并补充实现了 SimCAE 崩溃报告后端接口。
|
本项目是一套面向 Windows/Linux 客户端软件的自动升级与版本控制系统,并补充实现了 SimCAE 崩溃报告后端接口。
|
||||||
|
|
||||||
整体分为两部分:
|
整体分为两部分:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
client/ Windows 客户端升级运行时、SDK 打包脚本、接入说明文档
|
update-client/ Windows/Linux 客户端升级运行时、SDK 打包脚本、接入说明文档
|
||||||
server/ FastAPI 服务端、后台页面、Docker 部署和离线交付脚本
|
update-server/ FastAPI 服务端、后台页面、Docker 部署和离线交付脚本
|
||||||
|
```
|
||||||
|
|
||||||
|
文档放置约定:
|
||||||
|
|
||||||
|
```text
|
||||||
|
项目总览.md 项目整体说明,保留在总仓库根目录
|
||||||
|
update-client/Docs/ 客户端说明文档
|
||||||
|
update-server/Docs/ 服务端说明文档
|
||||||
```
|
```
|
||||||
|
|
||||||
客户端负责:
|
客户端负责:
|
||||||
@@ -37,18 +47,19 @@ server/ FastAPI 服务端、后台页面、Docker 部署和离线交付脚本
|
|||||||
客户端核心程序:
|
客户端核心程序:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Launcher.exe 用户入口,检查更新并启动业务主程序
|
Launcher.exe / Launcher 用户入口,检查更新并启动业务主程序
|
||||||
Updater.exe 下载、校验、安装、提交或回滚
|
Updater.exe / Updater 下载、校验、安装、提交或回滚
|
||||||
Bootstrap.exe 辅助替换运行中的 EXE/DLL
|
Bootstrap.exe / Bootstrap 辅助替换运行中的 EXE/DLL 或 Linux 可执行文件
|
||||||
MainApp.exe 当前仓库内的示例业务程序
|
MainApp.exe / MainApp 当前仓库内的示例业务程序
|
||||||
```
|
```
|
||||||
|
|
||||||
已经实现的能力:
|
已经实现的能力:
|
||||||
|
|
||||||
- 读取 `config/app_config.json` 配置。
|
- 首次启动时把 `config/app_config.json` 导入当前 Windows 用户注册表,后续普通运行配置优先从注册表读取;如果解析后的 JSON 内容变化,下一次启动会自动重新导入,并清理 `config/client_identity.dat` 和 `config/version_policy.dat`。
|
||||||
|
- 服务端 API 地址 `api_base_url` 不再写入 `app_config.json` 或注册表,而是写入 `config/server_config.json` 并通过 `config/server_config.qrc` 编译进 Launcher / Updater。
|
||||||
- 首次设备登记和本地设备身份校验。
|
- 首次设备登记和本地设备身份校验。
|
||||||
- License 校验。
|
- License 校验。
|
||||||
- `license_key` 为空时,`Launcher.exe` 会弹窗让用户粘贴后台创建的 License,并写入 `config/app_config.json`。当前实现会先检查配置项;即使本地已有 `config/client_identity.dat`,只要清空 `license_key` 仍会提示用户补填 License。
|
- `license_key` 为空时,`Launcher.exe` 会弹窗让用户粘贴后台创建的 License,并写入注册表。当前实现会先检查配置项;即使本地已有 `config/client_identity.dat`,只要清空 `license_key` 仍会提示用户补填 License。
|
||||||
- License 过期、错误、禁用、设备数达到上限或设备身份凭证与授权不匹配时,`Launcher.exe` 会引导用户重新输入 License,而不是要求用户手动查找配置文件。
|
- License 过期、错误、禁用、设备数达到上限或设备身份凭证与授权不匹配时,`Launcher.exe` 会引导用户重新输入 License,而不是要求用户手动查找配置文件。
|
||||||
- 版本策略校验。
|
- 版本策略校验。
|
||||||
- 防止策略序号回退。
|
- 防止策略序号回退。
|
||||||
@@ -60,33 +71,53 @@ MainApp.exe 当前仓库内的示例业务程序
|
|||||||
- 升级后健康检查 `--health-file`,业务程序启动成功后写入 `ok`。
|
- 升级后健康检查 `--health-file`,业务程序启动成功后写入 `ok`。
|
||||||
- 升级失败回滚。
|
- 升级失败回滚。
|
||||||
- 升级日志和下载日志上报服务端。
|
- 升级日志和下载日志上报服务端。
|
||||||
- `server/admin.html` 管理后台布局已优化,升级日志和下载日志默认折叠。
|
- Git 标签清单生成:如果服务端策略开启,`Launcher` 会请求服务端生成 Git tags 文本,并写入 `Launcher` 同目录下的 `tags.txt`;客户端不会接触 Git token。
|
||||||
|
- Launcher / Updater / Bootstrap 已支持 Windows 和 Linux Qt 跨平台编译。
|
||||||
|
|
||||||
## 三、客户端 SDK 交付状态
|
## 三、客户端 SDK 交付状态
|
||||||
|
|
||||||
已经提供 SDK 打包脚本:
|
已经提供 Windows 和 Linux SDK/客户端打包脚本:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
client/package-sdk.ps1
|
update-client/scripts/package-sdk.ps1
|
||||||
client/package-client.ps1
|
update-client/scripts/package-client.ps1
|
||||||
|
update-client/scripts/package-sdk.sh
|
||||||
|
update-client/scripts/package-client.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
`package-sdk.ps1` 用于生成给业务开发者接入的 SDK 包。当前 SDK 包结构设计为:
|
客户端文档现在统一放在:
|
||||||
|
|
||||||
|
```text
|
||||||
|
update-client/Docs/00-先读我-客户端文档入口.txt
|
||||||
|
update-client/Docs/01-客户端接入打包部署指南.md
|
||||||
|
update-client/Docs/02-编译环境和第三方依赖说明.md
|
||||||
|
```
|
||||||
|
|
||||||
|
`package-sdk.ps1` / `package-sdk.sh` 用于生成给业务开发者接入的 SDK 包。当前 SDK 包结构设计为:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
UpdateClientSDK/
|
UpdateClientSDK/
|
||||||
SimCAE自动升级SDK接入说明_v0.1.docx
|
|
||||||
sdk_manifest.json
|
sdk_manifest.json
|
||||||
|
Docs/
|
||||||
|
00-先读我-客户端文档入口.txt
|
||||||
|
01-客户端接入打包部署指南.md
|
||||||
|
02-编译环境和第三方依赖说明.md
|
||||||
bin/
|
bin/
|
||||||
config/
|
config/
|
||||||
app_config.json
|
app_config.json
|
||||||
manifest_public_key.pem
|
manifest_public_key.pem
|
||||||
|
Common/
|
||||||
|
ConfigHelper.h/.cpp
|
||||||
|
TicketHelper.h/.cpp
|
||||||
scripts/
|
scripts/
|
||||||
|
SimCAE自动升级SDK接入说明_v0.1.docx 可选,本地存在时才会随包复制
|
||||||
```
|
```
|
||||||
|
|
||||||
为了降低接入方理解成本,SDK 根目录只保留一个 Word 说明文档作为入口。
|
为了降低接入方理解成本,SDK 包内默认带 `Docs/00-先读我-客户端文档入口.txt`。Word 接入说明是可选增强,`.docx` 不进 Git;fresh clone 没有 Word 时也能打包 SDK。
|
||||||
|
|
||||||
Word 文档已经说明:
|
Linux 当前已完成 Qt 跨平台编译、Linux SDK 打包脚本、Linux 最终客户端打包脚本、Linux 配置模板和部署说明。真实 Linux 版 SimCAE 主程序还未由业务开发方交付,因此真实业务联调暂未完成。
|
||||||
|
|
||||||
|
客户端接入文档已经说明:
|
||||||
|
|
||||||
- 拿到 `UpdateClientSDK.zip` 后怎么操作。
|
- 拿到 `UpdateClientSDK.zip` 后怎么操作。
|
||||||
- 如何复制 SDK 运行时到业务软件 Release 目录。
|
- 如何复制 SDK 运行时到业务软件 Release 目录。
|
||||||
@@ -99,14 +130,37 @@ Word 文档已经说明:
|
|||||||
|
|
||||||
## 四、服务端当前已实现
|
## 四、服务端当前已实现
|
||||||
|
|
||||||
服务端使用 FastAPI,主要文件:
|
服务端采用的成熟框架和模板生态:
|
||||||
|
|
||||||
|
- 后端 HTTP 框架:`FastAPI`,运行服务使用 `Uvicorn`,请求模型和参数校验使用 FastAPI 自带的 `Pydantic` 体系。
|
||||||
|
- 后端工程结构:参考 FastAPI 官方 full-stack 模板、FastAPI Users 等成熟 FastAPI 后台项目的分层方式,拆成 `routes / services / repositories / schemas / core`。
|
||||||
|
- 管理后台前端:使用 GitHub 上的 `pure-admin-thin` / `vue-pure-admin` 生态,技术栈是 `Vue3 + Element Plus + TypeScript + Vite`。
|
||||||
|
- 存储组件:元数据使用 SQLite,版本文件和崩溃文件使用 MinIO 对象存储。
|
||||||
|
- Git 标签清单:服务端支持通过 `GITEA_BASE_URL` / `GITEA_TOKEN` 访问 Gitea API,管理后台策略页可以控制 Launcher 是否生成 `tags.txt`,并在后台预览当前仓库 tags。`GITEA_TOKEN` 只保存在服务端 `.env`,不会返回给客户端。
|
||||||
|
- 当前说明:后端已经完成工程化分层,并已加入用户名/密码登录、Argon2 密码哈希、JWT access/refresh token、RBAC 权限检查和管理员用户管理页面。当前实现是轻量用户体系,后续仍可继续接入 FastAPI Users 等更完整的成熟认证组件。
|
||||||
|
- 自动化测试:使用 pytest,测试会创建隔离的临时数据库、临时 Manifest 私钥和临时存储目录,覆盖管理员登录/JWT、License/设备登记、更新检查、发布事务和崩溃报告核心流程。
|
||||||
|
|
||||||
|
当前后端已经从早期单文件形态拆成分层结构,主要入口和目录:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
server/main.py
|
update-server/main.py 应用启动、数据库初始化、MinIO 初始化、全局客户端鉴权
|
||||||
server/db.py
|
update-server/app/api/routes/ 管理端、客户端更新、崩溃报告等 HTTP 路由
|
||||||
server/tables.sql
|
update-server/app/services/ 发布、签名、License、设备凭证、崩溃报告等业务逻辑
|
||||||
server/minio_tool.py
|
update-server/app/repositories/ SQLite 数据库读写层
|
||||||
server/admin.html 服务端管理后台页面,Docker 构建时复制进镜像
|
update-server/app/schemas/ Pydantic 请求模型
|
||||||
|
update-server/db.py
|
||||||
|
update-server/tables.sql
|
||||||
|
update-server/minio_tool.py
|
||||||
|
update-server/admin-ui/ 新版管理后台源码
|
||||||
|
```
|
||||||
|
|
||||||
|
服务端文档现在统一放在:
|
||||||
|
|
||||||
|
```text
|
||||||
|
update-server/Docs/00-先读我-服务端文档入口.txt
|
||||||
|
update-server/Docs/01-服务端Docker打包部署指南.md
|
||||||
|
update-server/Docs/02-崩溃报告接口联调指南.md
|
||||||
|
update-server/Docs/03-后端工程化结构说明.md
|
||||||
```
|
```
|
||||||
|
|
||||||
已经实现的能力:
|
已经实现的能力:
|
||||||
@@ -116,6 +170,7 @@ server/admin.html 服务端管理后台页面,Docker 构建时复制进镜像
|
|||||||
- License 管理。
|
- License 管理。
|
||||||
- 设备首次登记。
|
- 设备首次登记。
|
||||||
- 版本发布。
|
- 版本发布。
|
||||||
|
- 版本发布已支持后台任务模式:浏览器上传完成后,服务端继续在后台校验、入库和上传 MinIO,管理页面轮询任务状态。
|
||||||
- 版本发布支持两种方式:选择软件发布根目录,或上传压缩好的发布包。管理页面已经拆成“软件根目录/压缩发布包”两个发布方式,避免用户误以为只能选择文件夹。
|
- 版本发布支持两种方式:选择软件发布根目录,或上传压缩好的发布包。管理页面已经拆成“软件根目录/压缩发布包”两个发布方式,避免用户误以为只能选择文件夹。
|
||||||
- 压缩发布包支持 `zip`、`tar.gz`、`tgz`、`tar.bz2`、`tbz2`、`rar`;服务端会先解压,再按 `RELEASE_MAIN_EXECUTABLE` 校验主程序路径。
|
- 压缩发布包支持 `zip`、`tar.gz`、`tgz`、`tar.bz2`、`tbz2`、`rar`;服务端会先解压,再按 `RELEASE_MAIN_EXECUTABLE` 校验主程序路径。
|
||||||
- Manifest 生成和私钥签名。
|
- Manifest 生成和私钥签名。
|
||||||
@@ -125,6 +180,7 @@ server/admin.html 服务端管理后台页面,Docker 构建时复制进镜像
|
|||||||
- 升级结果上报。
|
- 升级结果上报。
|
||||||
- 文件下载日志记录。
|
- 文件下载日志记录。
|
||||||
- 后台管理页面。
|
- 后台管理页面。
|
||||||
|
- 后端已经按 `routes / services / repositories / schemas` 拆分,`main.py` 不再堆业务接口。
|
||||||
- Docker 运行。
|
- Docker 运行。
|
||||||
- Docker 离线部署包生成。
|
- Docker 离线部署包生成。
|
||||||
|
|
||||||
@@ -161,20 +217,20 @@ POST /api/v1/symbols
|
|||||||
服务端 Docker 文件:
|
服务端 Docker 文件:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
server/Dockerfile
|
update-server/Dockerfile
|
||||||
server/docker-compose.yml
|
update-server/docker-compose.yml
|
||||||
server/docker-compose.image.yml
|
update-server/docker-compose.image.yml
|
||||||
server/package-offline-server.sh
|
update-server/scripts/package-offline-server.sh
|
||||||
server/.env.example
|
update-server/.env.example
|
||||||
server/.env.docker.example
|
update-server/.env.docker.example
|
||||||
```
|
```
|
||||||
|
|
||||||
Ubuntu 主流程使用:
|
Ubuntu 主流程使用:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd server
|
cd update-server
|
||||||
|
|
||||||
bash ./package-offline-server.sh \
|
bash ./scripts/package-offline-server.sh \
|
||||||
--version 0.1.0 \
|
--version 0.1.0 \
|
||||||
--output-dir ./dist/SimCAEServerDockerPackage
|
--output-dir ./dist/SimCAEServerDockerPackage
|
||||||
```
|
```
|
||||||
@@ -182,7 +238,7 @@ bash ./package-offline-server.sh \
|
|||||||
生成:
|
生成:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
server/dist/SimCAEServerDockerPackage.tar.gz
|
update-server/dist/SimCAEServerDockerPackage.tar.gz
|
||||||
```
|
```
|
||||||
|
|
||||||
该包中包含:
|
该包中包含:
|
||||||
@@ -202,8 +258,8 @@ server/dist/SimCAEServerDockerPackage.tar.gz
|
|||||||
注意:Docker 镜像包只包含软件本体和部署配置,不包含已经运行出来的数据。当前服务器上的数据库、上传过的版本文件、崩溃报告等数据在:
|
注意:Docker 镜像包只包含软件本体和部署配置,不包含已经运行出来的数据。当前服务器上的数据库、上传过的版本文件、崩溃报告等数据在:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
server/runtime/
|
update-server/runtime/
|
||||||
server/minio_data/
|
update-server/minio_data/
|
||||||
```
|
```
|
||||||
|
|
||||||
如果要完整迁移现有服务数据,需要额外备份和恢复这两个目录。
|
如果要完整迁移现有服务数据,需要额外备份和恢复这两个目录。
|
||||||
@@ -257,15 +313,15 @@ manifest_public_key.pem
|
|||||||
|
|
||||||
不建议提交:
|
不建议提交:
|
||||||
|
|
||||||
- `client/App/`
|
- `update-client/App/`
|
||||||
- `client/out/`
|
- `update-client/out/`
|
||||||
- `client/dist/`
|
- `update-client/dist/`
|
||||||
- `server/dist/`
|
- `update-server/dist/`
|
||||||
- `server/runtime/`
|
- `update-server/runtime/`
|
||||||
- `server/minio_data/`
|
- `update-server/minio_data/`
|
||||||
- `server/*.db`
|
- `update-server/*.db`
|
||||||
- `server/.env`
|
- `update-server/.env`
|
||||||
- `server/keys/manifest_private_key.pem`
|
- `update-server/keys/manifest_private_key.pem`
|
||||||
- 任何真实 token、License、私钥和运行日志。
|
- 任何真实 token、License、私钥和运行日志。
|
||||||
|
|
||||||
## 九、SimCAE 安装根目录模式
|
## 九、SimCAE 安装根目录模式
|
||||||
@@ -291,9 +347,9 @@ SimCAE/
|
|||||||
|
|
||||||
## 十、运行目录权限说明
|
## 十、运行目录权限说明
|
||||||
|
|
||||||
当前客户端 SDK 默认把运行时状态写在 `Launcher.exe` 所在目录下,包括 `config/app_config.json`、`config/client_identity.dat`、`config/local_state.json`、`config/version_policy.dat`、`update/` 和 `update_temp/`。当 SDK 放在 `SimCAE/bin` 时,更新事务、备份、暂存文件、下载断点和 Manifest 缓存都在 `SimCAE/bin/update/`,不会再在 `SimCAE/` 根目录生成顶层 `update/`。因此联调目录必须允许当前 Windows 用户写入。
|
当前客户端 SDK 把部署配置源放在 `Launcher.exe` 所在目录下的 `config/app_config.json`,启动时同步到当前用户的 QSettings 配置区;Windows 下对应注册表路径 `HKEY_CURRENT_USER\Software\Marsco\UpdateClientSDK\installations\<安装目录SHA256>\config`,Linux 下由 Qt QSettings 写入当前用户配置目录。服务端 API 地址 `api_base_url` 是例外:它位于源码 `config/server_config.json`,通过 `config/server_config.qrc` 编译进程序,不再写入 `app_config.json` 或注册表。如果检测到 `app_config.json` 变化,SDK 会删除当前用户数据目录里的 `client_identity.dat`、`version_policy.dat` 和 `local_state.json`,避免旧授权身份、旧策略或旧防回滚状态继续生效。设备身份、状态、策略、更新事务、备份、暂存文件、下载断点和 Manifest 缓存默认位于当前用户数据目录,例如 Windows:`%LOCALAPPDATA%\Marsco\UpdateClientSDK\installations\<安装目录SHA256>\`。当 SDK 放在 `SimCAE/bin` 时,不会再在 `SimCAE/` 根目录生成顶层 `update/`。
|
||||||
|
|
||||||
如果把软件放在 `C:\Program Files\SimCAE\bin` 并用普通用户启动,Windows 会拒绝写入,首次启动可能提示 `cannot save installation id`。当前建议先在 `D:\SimCAE_Release` 或桌面目录联调;正式要安装到 `Program Files` 时,需要补管理员提权、Windows 服务,或将运行时状态迁移到 `ProgramData` / `AppData`。
|
如果把软件放在 `C:\Program Files\SimCAE\bin` 并用普通用户启动,普通配置值已经不需要写回 `app_config.json`;但设备身份、状态、策略、更新缓存等文件仍可能需要写安装目录。当前代码对小型状态文件写入已有管理员权限确认;正式要完整安装到 `Program Files` 并自动升级大文件时,后续仍建议补 Windows 服务,或将更多运行时状态迁移到 `ProgramData` / `AppData`。
|
||||||
|
|
||||||
## 十一、后续待办
|
## 十一、后续待办
|
||||||
|
|
||||||
@@ -309,12 +365,12 @@ SimCAE/
|
|||||||
|
|
||||||
## 附录:原项目进度记录
|
## 附录:原项目进度记录
|
||||||
|
|
||||||
以下内容迁移自原 `client/项目进度.txt`,用于保留更详细的阶段性进度、功能清单和概念说明。
|
以下内容迁移自原 `update-client/项目进度.txt`,用于保留更详细的阶段性进度、功能清单和概念说明。
|
||||||
|
|
||||||
```text
|
```text
|
||||||
软件自动升级与版本控制系统——项目进度
|
软件自动升级与版本控制系统——项目进度
|
||||||
更新时间:2026-07-07
|
更新时间:2026-07-07
|
||||||
依据:《软件自动升级与版本控制系统开发设计文档 v0.1》、《SimCAE_Crash_Report后端接口规范》及当前 server/client 源码
|
依据:《软件自动升级与版本控制系统开发设计文档 v0.1》、《SimCAE_Crash_Report后端接口规范》及当前 update-server/update-client 源码
|
||||||
|
|
||||||
============================================================
|
============================================================
|
||||||
一、项目进度概述
|
一、项目进度概述
|
||||||
@@ -360,17 +416,22 @@ SimCAE 崩溃报告后端已经完成第一阶段核心接口:接收 SimCAECra
|
|||||||
|
|
||||||
说明:MainApp 当前读取 Demo DLL 内容并显示 Hash 标识,但还没有通过 QLibrary 真正加载并调用插件接口,因此“插件实际加载”只算部分完成。
|
说明:MainApp 当前读取 Demo DLL 内容并显示 Hash 标识,但还没有通过 QLibrary 真正加载并调用插件接口,因此“插件实际加载”只算部分完成。
|
||||||
|
|
||||||
2.2 本地 JSON 配置
|
2.2 本地配置
|
||||||
|
|
||||||
已实现:
|
已实现:
|
||||||
|
|
||||||
1. 使用 config/app_config.json 保存客户端配置。
|
1. 使用 `config/app_config.json` 作为部署配置源文件。
|
||||||
2. 支持旧 client.ini 自动迁移。
|
2. Launcher / Updater / MainApp 启动时按解析后的 JSON 内容 SHA-256 判断配置是否变化,变化后自动导入当前 Windows 用户注册表。
|
||||||
3. 保存 API 地址、App ID、当前版本、渠道、设备 ID、客户端 Token、启动 Token、平台和架构。
|
3. 注册表路径为 `HKEY_CURRENT_USER\Software\Marsco\UpdateClientSDK\installations\<安装目录SHA256>\config`。
|
||||||
4. 更新成功后写入 current_version。
|
4. 后续运行配置优先从注册表读取,运行时动态值写入注册表。
|
||||||
5. 使用 QSaveFile 原子写入主要配置。
|
5. 检测到 JSON 变化后自动清理 `client_identity.dat` 和 `version_policy.dat`。
|
||||||
6. 运行时配置不进入发布包。
|
6. 支持旧 client.ini 自动迁移。
|
||||||
7. 已配置项目 .gitignore。
|
7. 保存 App ID、当前版本、渠道、设备 ID、客户端 Token、启动 Token、平台和架构。
|
||||||
|
8. 使用 `config/server_config.json` + `config/server_config.qrc` 把 API 地址编译进程序,避免写入 `app_config.json` 或注册表。
|
||||||
|
8. 更新成功后写入 current_version。
|
||||||
|
9. 文件型本地状态仍使用 QSaveFile 原子写入。
|
||||||
|
10. 运行时配置不进入发布包。
|
||||||
|
11. 已配置项目 .gitignore。
|
||||||
|
|
||||||
2.3 服务端基础能力
|
2.3 服务端基础能力
|
||||||
|
|
||||||
@@ -614,20 +675,23 @@ Updater 启动时会读取旧事务,并根据状态尝试恢复或回滚。
|
|||||||
|
|
||||||
已实现:
|
已实现:
|
||||||
|
|
||||||
1. 管理员令牌输入、隐藏、显示和保存。
|
1. 用户名和密码登录管理后台。
|
||||||
2. 修改管理员令牌。
|
2. 登录成功后由服务端签发 JWT access token 和 refresh token,管理接口使用 `Authorization: Bearer ...` 调用。
|
||||||
3. 创建和选择应用。
|
3. 管理员密码修改。
|
||||||
4. 选择软件根目录发布。
|
4. RBAC 角色权限校验,目前内置超级管理员、发布管理员、授权管理员、审计人员和崩溃报告管理员。
|
||||||
5. 切换到“压缩发布包”模式上传压缩包发布,支持 zip、tar.gz、tgz、tar.bz2、tbz2、rar。
|
5. 管理员用户管理:创建用户、编辑显示名称和角色、启用/禁用、重置密码,并防止禁用最后一个超级管理员。
|
||||||
6. stable、preview、dev 渠道选择。
|
6. 创建和选择应用。
|
||||||
7. 版本列表。
|
7. 选择软件根目录发布。
|
||||||
8. 设置最新版本。
|
8. 切换到“压缩发布包”模式上传压缩包发布,支持 zip、tar.gz、tgz、tar.bz2、tbz2、rar。
|
||||||
9. 删除版本和云端文件。
|
9. stable、preview、dev 渠道选择。
|
||||||
10. 版本策略读取和保存。
|
10. 版本列表。
|
||||||
11. 升级日志。
|
11. 设置最新版本。
|
||||||
12. 调试输出。
|
12. 删除版本和云端文件。
|
||||||
13. 发布文件预览、大小和状态提示。
|
13. 版本策略读取和保存。
|
||||||
14. 页面美化和响应式布局。
|
14. 升级日志。
|
||||||
|
15. 调试输出。
|
||||||
|
16. 发布文件预览、大小和状态提示。
|
||||||
|
17. 页面美化和响应式布局。
|
||||||
|
|
||||||
|
|
||||||
2.16 一次性短期启动票据
|
2.16 一次性短期启动票据
|
||||||
@@ -665,14 +729,14 @@ Updater 启动时会读取旧事务,并根据状态尝试恢复或回滚。
|
|||||||
3. 服务端逐请求验证设备凭证、授权状态、设备禁用状态、app_id 和 channel。
|
3. 服务端逐请求验证设备凭证、授权状态、设备禁用状态、app_id 和 channel。
|
||||||
4. License 授权:licenses 和 license_devices 表,支持有效期、启用/禁用、最大设备数和设备占用。
|
4. License 授权:licenses 和 license_devices 表,支持有效期、启用/禁用、最大设备数和设备占用。
|
||||||
5. 授权密钥只保存 SHA-256,明文只在创建时返回一次。
|
5. 授权密钥只保存 SHA-256,明文只在创建时返回一次。
|
||||||
6. Launcher 首次启动时如果没有 License,会弹窗要求用户输入并自动写入配置;当前实现会先检查 `license_key` 配置项,即使本地已有 `client_identity.dat`,清空 `license_key` 仍会触发输入框。
|
6. Launcher 首次启动时如果没有 License,会弹窗要求用户输入并自动写入注册表;当前实现会先检查 `license_key` 配置项,即使本地已有 `client_identity.dat`,清空 `license_key` 仍会触发输入框。
|
||||||
7. License 错误、过期、禁用、设备数达到上限或设备身份与授权不匹配时,Launcher 会清理旧设备身份并引导用户重新输入 License。
|
7. License 错误、过期、禁用、设备数达到上限或设备身份与授权不匹配时,Launcher 会清理旧设备身份并引导用户重新输入 License。
|
||||||
8. 动态渠道:channels 表按 app_id 隔离,管理后台支持新增、编辑、启用和停用。
|
8. 动态渠道:channels 表按 app_id 隔离,管理后台支持新增、编辑、启用和停用。
|
||||||
9. 发布、策略、授权、设备登记和更新检查统一校验渠道。
|
9. 发布、策略、授权、设备登记和更新检查统一校验渠道。
|
||||||
10. 离线更新包:管理后台可生成 MUPD0001/.upd 包,包内包含签名 Manifest、包头签名、文件偏移、大小和 SHA-256。
|
10. 离线更新包:管理后台可生成 MUPD0001/.upd 包,包内包含签名 Manifest、包头签名、文件偏移、大小和 SHA-256。
|
||||||
11. Launcher/Updater 支持导入离线包,离线安装复用现有事务、Bootstrap、校验、健康确认和回滚机制。
|
11. Launcher/Updater 支持导入离线包,离线安装复用现有事务、Bootstrap、校验、健康确认和回滚机制。
|
||||||
12. 下载日志:记录下载授权、客户端完成结果、文件大小、IP、User-Agent 和时间。
|
12. 下载日志:记录下载授权、客户端完成结果、文件大小、IP、User-Agent 和时间。
|
||||||
13. 管理员审计日志:记录 /admin 写操作、管理员令牌指纹、路径、结果、状态码、IP 和 User-Agent。
|
13. 管理员审计日志:记录 /admin 写操作、管理员账号、角色、鉴权方式、路径、结果、状态码、IP 和 User-Agent。
|
||||||
|
|
||||||
2.19 SimCAE Crash Report 后端第一阶段
|
2.19 SimCAE Crash Report 后端第一阶段
|
||||||
|
|
||||||
@@ -761,16 +825,26 @@ RSA 签名已经实现,但仍缺少:
|
|||||||
|
|
||||||
3.7 管理员登录
|
3.7 管理员登录
|
||||||
|
|
||||||
当前采用单管理员 Token,服务端用 .env 中的 ADMIN_TOKEN 校验,并且已经记录 /admin 写操作审计。
|
当前管理后台已经从单管理员 Token 升级为用户名/密码登录、JWT access/refresh token 和 RBAC 权限检查。
|
||||||
|
|
||||||
尚缺少:
|
已实现:
|
||||||
|
|
||||||
1. admin_users 表。
|
1. admin_users 表。
|
||||||
2. 正式登录接口。
|
2. admin_refresh_tokens 表。
|
||||||
3. Token 过期时间。
|
3. 初始管理员自动创建。
|
||||||
4. 多管理员和角色权限。
|
4. Argon2 密码哈希。
|
||||||
5. 登录失败审计。
|
5. JWT access token 和 refresh token。
|
||||||
6. 会话吊销和 Token 轮换流程。
|
6. 角色权限映射,例如 super_admin、release_admin、license_admin、auditor、crash_admin。
|
||||||
|
7. 管理员用户管理接口和页面:列表、创建、编辑角色、启用/禁用、重置密码。
|
||||||
|
8. 管理后台写操作审计记录管理员用户名、角色、认证方式和操作结果。
|
||||||
|
|
||||||
|
`ADMIN_TOKEN` 仍保留为旧脚本兼容令牌、JWT_SECRET 未配置时的默认签名密钥,以及 CRASH_ADMIN_TOKEN 为空时的崩溃报告管理兜底令牌。
|
||||||
|
|
||||||
|
仍可继续加强:
|
||||||
|
|
||||||
|
1. 登录失败审计和频率限制。
|
||||||
|
2. 更细粒度的会话管理和 Token 轮换策略。
|
||||||
|
3. 接入 FastAPI Users 或同类成熟用户认证模块,替换当前轻量用户表。
|
||||||
|
|
||||||
3.8 数据库结构
|
3.8 数据库结构
|
||||||
|
|
||||||
@@ -905,12 +979,12 @@ RSA 签名已经实现,但仍缺少:
|
|||||||
|
|
||||||
1. admin_audit_logs 表。
|
1. admin_audit_logs 表。
|
||||||
2. 统一中间件记录所有 /admin 写操作。
|
2. 统一中间件记录所有 /admin 写操作。
|
||||||
3. 记录管理员令牌截断 Hash 指纹,不保存令牌明文。
|
3. 记录管理员账号、角色、鉴权方式和兼容令牌截断 Hash 指纹,不保存令牌明文。
|
||||||
4. 记录操作路径、HTTP 方法、查询目标、成功/失败、状态码、IP、User-Agent 和时间。
|
4. 记录操作路径、HTTP 方法、查询目标、成功/失败、状态码、IP、User-Agent 和时间。
|
||||||
5. 鉴权失败及业务失败同样进入审计。
|
5. 鉴权失败及业务失败同样进入审计。
|
||||||
6. 审计日志查询 API 和管理后台列表。
|
6. 审计日志查询 API 和管理后台列表。
|
||||||
|
|
||||||
审计中间件不保存请求正文,避免 License 密钥、新管理员令牌等敏感内容进入日志。
|
审计中间件不保存请求正文,避免 License 密钥、新密码、兼容令牌等敏感内容进入日志。
|
||||||
|
|
||||||
4.11 代码签名
|
4.11 代码签名
|
||||||
|
|
||||||
@@ -922,7 +996,7 @@ RSA 签名已经实现,但仍缺少:
|
|||||||
|
|
||||||
4.13 多平台
|
4.13 多平台
|
||||||
|
|
||||||
目前只支持 Windows x64,尚未支持 Windows ARM64、Linux、macOS 和多平台 Manifest 分流。
|
Windows x64 已完成主要联调;Linux x64 已完成 Qt 跨平台编译、SDK 打包脚本、客户端打包脚本、配置模板和服务端发布配置支持。尚未完成 Windows ARM64、macOS、多平台 Manifest 分流,以及真实 Linux 版 SimCAE 主程序实机联调。
|
||||||
|
|
||||||
============================================================
|
============================================================
|
||||||
五、需求文档 Demo 里程碑状态
|
五、需求文档 Demo 里程碑状态
|
||||||
@@ -1001,7 +1075,7 @@ SimCAE Crash Report 第一阶段——已实现。
|
|||||||
|
|
||||||
8.1 服务端是什么
|
8.1 服务端是什么
|
||||||
|
|
||||||
服务端在 server/ 下,核心是 FastAPI 应用。它负责:
|
服务端在 update-server/ 下,核心是 FastAPI 应用。它负责:
|
||||||
|
|
||||||
1. 管理应用、版本、渠道和策略。
|
1. 管理应用、版本、渠道和策略。
|
||||||
2. 接收管理员发布的软件文件。
|
2. 接收管理员发布的软件文件。
|
||||||
@@ -1010,7 +1084,7 @@ SimCAE Crash Report 第一阶段——已实现。
|
|||||||
5. 对 Manifest、策略、设备身份、离线包做 RSA 签名。
|
5. 对 Manifest、策略、设备身份、离线包做 RSA 签名。
|
||||||
6. 给客户端签发临时下载 URL。
|
6. 给客户端签发临时下载 URL。
|
||||||
7. 接收升级结果、下载结果、设备登记和 License 授权。
|
7. 接收升级结果、下载结果、设备登记和 License 授权。
|
||||||
8. 提供 admin.html 管理网页。
|
8. 提供新版 admin-ui 管理后台;旧版 admin.html 已在开发阶段移除,不再保留兼容入口。
|
||||||
9. 接收 SimCAE 崩溃报告和符号包。
|
9. 接收 SimCAE 崩溃报告和符号包。
|
||||||
|
|
||||||
服务端主要存储有三类:
|
服务端主要存储有三类:
|
||||||
@@ -1021,7 +1095,7 @@ SimCAE Crash Report 第一阶段——已实现。
|
|||||||
|
|
||||||
8.2 客户端是什么
|
8.2 客户端是什么
|
||||||
|
|
||||||
客户端在 client/ 下,主要由几个程序配合:
|
客户端在 update-client/ 下,主要由几个程序配合:
|
||||||
|
|
||||||
1. Launcher.exe:入口程序。负责检查更新、验证策略、决定是否启动 MainApp 或 Updater。
|
1. Launcher.exe:入口程序。负责检查更新、验证策略、决定是否启动 MainApp 或 Updater。
|
||||||
2. Updater.exe:真正下载和安装文件的程序。负责 Manifest 验证、差异下载、断点续传、备份、校验、提交或回滚。
|
2. Updater.exe:真正下载和安装文件的程序。负责 Manifest 验证、差异下载、断点续传、备份、校验、提交或回滚。
|
||||||
@@ -1233,10 +1307,10 @@ symbols.zip 就是 CI 或发布流程上传的符号包。它按 product、appVe
|
|||||||
1. CLIENT_API_TOKEN:客户端安装包自带的公共门槛,用于首次设备登记等基础访问。
|
1. CLIENT_API_TOKEN:客户端安装包自带的公共门槛,用于首次设备登记等基础访问。
|
||||||
2. license_key:客户授权密钥,证明这个客户/项目有权使用某个 app/channel,并限制设备数和有效期。
|
2. license_key:客户授权密钥,证明这个客户/项目有权使用某个 app/channel,并限制设备数和有效期。
|
||||||
3. device_id/client_identity.dat:服务端给某台安装实例签发的设备身份,之后每次更新请求都要带。
|
3. device_id/client_identity.dat:服务端给某台安装实例签发的设备身份,之后每次更新请求都要带。
|
||||||
4. X-Admin-Token:管理后台请求头里传的管理员令牌;当前服务端用 .env 里的 ADMIN_TOKEN 校验。
|
4. 管理后台 JWT:网页登录成功后使用 `Authorization: Bearer <accessToken>` 调用后台接口。
|
||||||
5. CRASH_REPORT_TOKEN:SimCAECrashReporter.exe 上传崩溃报告用的 Bearer Token。
|
5. CRASH_REPORT_TOKEN:SimCAECrashReporter.exe 上传崩溃报告用的 Bearer Token。
|
||||||
6. CRASH_SYMBOL_TOKEN:CI 上传 symbols.zip 用的 Bearer Token。
|
6. CRASH_SYMBOL_TOKEN:CI 上传 symbols.zip 用的 Bearer Token。
|
||||||
7. CRASH_ADMIN_TOKEN:查询和下载崩溃原始文件用;如果不配置,就复用当前管理员令牌。
|
7. CRASH_ADMIN_TOKEN:查询和下载崩溃原始文件用;如果不配置,就复用 ADMIN_TOKEN 作为崩溃报告管理兜底令牌。
|
||||||
|
|
||||||
简单理解:
|
简单理解:
|
||||||
|
|
||||||
@@ -1257,8 +1331,8 @@ SDK 是 Software Development Kit,中文通常叫“软件开发工具包”。
|
|||||||
|
|
||||||
1. 可直接使用的二进制文件,例如 Launcher.exe、Updater.exe、Bootstrap.exe。
|
1. 可直接使用的二进制文件,例如 Launcher.exe、Updater.exe、Bootstrap.exe。
|
||||||
2. 必要的运行时文件。对 SimCAE 这种自身已带 Qt 的软件,SDK 默认不再携带 Qt DLL,避免覆盖业务软件原有运行库。
|
2. 必要的运行时文件。对 SimCAE 这种自身已带 Qt 的软件,SDK 默认不再携带 Qt DLL,避免覆盖业务软件原有运行库。
|
||||||
3. 配置模板,例如 app_config.example.json。
|
3. 配置模板,例如 app_config.example.json 和 server_config.json。
|
||||||
4. 接入文档,例如如何配置 app_id、channel、api_base_url、license_key。
|
4. 接入文档,例如如何配置 app_id、channel、qrc 服务端地址、license_key。
|
||||||
5. 打包脚本,例如 package-client.ps1。
|
5. 打包脚本,例如 package-client.ps1。
|
||||||
6. 示例项目或 Demo。
|
6. 示例项目或 Demo。
|
||||||
7. API/命令行约定,例如主程序必须由 Launcher 启动,MainApp 需要写健康标记。
|
7. API/命令行约定,例如主程序必须由 Launcher 启动,MainApp 需要写健康标记。
|
||||||
@@ -1305,6 +1379,8 @@ UpdateClientSDK/
|
|||||||
Bootstrap.exe
|
Bootstrap.exe
|
||||||
config/
|
config/
|
||||||
app_config.json
|
app_config.json
|
||||||
|
server_config.json
|
||||||
|
server_config.qrc
|
||||||
manifest_public_key.pem
|
manifest_public_key.pem
|
||||||
scripts/
|
scripts/
|
||||||
install-sdk.ps1
|
install-sdk.ps1
|
||||||
@@ -1313,19 +1389,20 @@ UpdateClientSDK/
|
|||||||
对接方真正拿到后,通常只需要做这些事:
|
对接方真正拿到后,通常只需要做这些事:
|
||||||
|
|
||||||
1. 把 SDK 的 Launcher、Updater、Bootstrap 放到业务软件运行目录。
|
1. 把 SDK 的 Launcher、Updater、Bootstrap 放到业务软件运行目录。
|
||||||
2. 设置 app_config.json:server 地址、app_id、channel、当前版本、主程序名等。`license_key` 可以预先填入;如果为空,用户首次启动 Launcher 时会弹窗粘贴授权密钥。
|
2. 设置 app_config.json:app_id、channel、当前版本、主程序名等。`license_key` 可以预先填入;如果为空,用户首次启动 Launcher 时会弹窗粘贴授权密钥。
|
||||||
3. 以后让用户启动 Launcher.exe。
|
3. 设置 config/server_config.json:服务端 API 地址。该文件必须在编译 Launcher/Updater 前写好,因为它会被 qrc 编进程序。
|
||||||
4. 在管理后台创建应用、License、渠道和发布版本。
|
4. 以后让用户启动 Launcher.exe。
|
||||||
5. 发布新版本时选择干净的 Release 输出目录,或切换到“压缩发布包”模式上传 zip/tar.gz/tar.bz2/rar 等压缩发布包。
|
5. 在管理后台创建应用、License、渠道和发布版本。
|
||||||
|
6. 发布新版本时选择干净的 Release 输出目录,或切换到“压缩发布包”模式上传 zip/tar.gz/tar.bz2/rar 等压缩发布包。
|
||||||
|
|
||||||
10.4 当前已有 package-client.ps1 的作用
|
10.4 当前已有 package-client.ps1 的作用
|
||||||
|
|
||||||
client/package-client.ps1 已经是 SDK/客户端包雏形。
|
update-client/scripts/package-client.ps1 已经是 SDK/客户端包雏形。
|
||||||
|
|
||||||
它目前会做这些事:
|
它目前会做这些事:
|
||||||
|
|
||||||
1. 从 out/bin 收集已编译好的客户端文件。
|
1. 从 out/bin 收集已编译好的客户端文件。
|
||||||
2. 检查必填配置,例如 app_id、channel、api_base_url、current_version、client_token、launch_token、license_key、主程序名等。
|
2. 检查必填配置,例如 app_id、channel、current_version、client_token、launch_token、license_key、主程序名等。
|
||||||
3. 检查 Launcher、Updater、Bootstrap、MainApp 是否存在。
|
3. 检查 Launcher、Updater、Bootstrap、MainApp 是否存在。
|
||||||
4. 拒绝 PDB、ILK、Debug Qt DLL 等调试产物进入发布包。
|
4. 拒绝 PDB、ILK、Debug Qt DLL 等调试产物进入发布包。
|
||||||
5. 检查主程序是否被嵌套放错目录。
|
5. 检查主程序是否被嵌套放错目录。
|
||||||
@@ -1357,11 +1434,11 @@ client/package-client.ps1 已经是 SDK/客户端包雏形。
|
|||||||
- app_id=mycad
|
- app_id=mycad
|
||||||
- channel=stable
|
- channel=stable
|
||||||
- main_executable=MyCAD.exe
|
- main_executable=MyCAD.exe
|
||||||
- api_base_url=http://服务器IP:8000
|
|
||||||
- license_key=服务端生成的授权密钥
|
- license_key=服务端生成的授权密钥
|
||||||
6. 用户桌面快捷方式指向 Launcher.exe。
|
6. config/server_config.json 里写 `api_base_url=http://服务器IP:8000`,并重新编译 Launcher/Updater。
|
||||||
7. 管理员以后在后台发布 MyCAD 的新版本。
|
7. 用户桌面快捷方式指向 Launcher.exe。
|
||||||
8. 用户启动 Launcher.exe 时自动检查、下载、替换并启动 MyCAD.exe。
|
8. 管理员以后在后台发布 MyCAD 的新版本。
|
||||||
|
9. 用户启动 Launcher.exe 时自动检查、下载、替换并启动 MyCAD.exe。
|
||||||
|
|
||||||
这就是“把客户端升级能力作为 SDK 给其他软件使用”。
|
这就是“把客户端升级能力作为 SDK 给其他软件使用”。
|
||||||
|
|
||||||
@@ -1369,7 +1446,7 @@ client/package-client.ps1 已经是 SDK/客户端包雏形。
|
|||||||
|
|
||||||
Docker 可以理解为“把服务端运行环境打包成一个标准盒子”。
|
Docker 可以理解为“把服务端运行环境打包成一个标准盒子”。
|
||||||
|
|
||||||
本机直接运行 server/venv/bin/python3 main.py 时,依赖的是当前机器上的 Python 虚拟环境、当前目录、当前配置文件。
|
本机直接运行 update-server/venv/bin/python3 main.py 时,依赖的是当前机器上的 Python 虚拟环境、当前目录、当前配置文件。
|
||||||
|
|
||||||
Docker 运行时,依赖的是镜像里的 Python、镜像里的依赖、容器里的 /app 目录和 docker-compose.yml 映射进去的数据目录。
|
Docker 运行时,依赖的是镜像里的 Python、镜像里的依赖、容器里的 /app 目录和 docker-compose.yml 映射进去的数据目录。
|
||||||
|
|
||||||
@@ -1383,17 +1460,17 @@ Docker 运行时,依赖的是镜像里的 Python、镜像里的依赖、容器
|
|||||||
|
|
||||||
10.7 当前服务端 Docker 已经具备什么
|
10.7 当前服务端 Docker 已经具备什么
|
||||||
|
|
||||||
当前 server/Dockerfile 已经具备:
|
当前 update-server/Dockerfile 已经具备:
|
||||||
|
|
||||||
1. 使用 python:3.12-slim 作为基础镜像。
|
1. 使用 python:3.12-slim 作为基础镜像。
|
||||||
2. 安装 server/requirements.txt 里的 FastAPI、MinIO、cryptography 等依赖。
|
2. 安装 update-server/requirements.txt 里的 FastAPI、MinIO、cryptography 等依赖。
|
||||||
3. 拷贝 main.py、db.py、minio_tool.py、tables.sql。
|
3. 拷贝 main.py、db.py、minio_tool.py、tables.sql。
|
||||||
4. 拷贝 server/admin.html 到容器内 /app/admin.html。
|
4. 拷贝 admin-ui/dist 管理后台静态文件到容器内 /app/admin-ui/dist。
|
||||||
5. 使用非 root 用户 updateapp 运行。
|
5. 使用非 root 用户 updateapp 运行。
|
||||||
6. 暴露 8000 端口。
|
6. 暴露 8000 端口。
|
||||||
7. 提供 healthcheck。
|
7. 提供 healthcheck。
|
||||||
|
|
||||||
当前 server/docker-compose.yml 已经具备:
|
当前 update-server/docker-compose.yml 已经具备:
|
||||||
|
|
||||||
1. minio:对象存储,保存升级文件。
|
1. minio:对象存储,保存升级文件。
|
||||||
2. minio-init:首次启动时创建 bucket。
|
2. minio-init:首次启动时创建 bucket。
|
||||||
@@ -1411,7 +1488,7 @@ Docker 运行时,依赖的是镜像里的 Python、镜像里的依赖、容器
|
|||||||
|
|
||||||
1. 进入 server 目录。
|
1. 进入 server 目录。
|
||||||
2. 准备 .env。
|
2. 准备 .env。
|
||||||
3. 设置 ADMIN_TOKEN、CLIENT_API_TOKEN、MINIO_ACCESS_KEY、MINIO_SECRET_KEY、MINIO_BUCKET、MINIO_PUBLIC_ENDPOINT、CRASH_REPORT_TOKEN、CRASH_SYMBOL_TOKEN。
|
3. 设置 ADMIN_USERNAME、ADMIN_PASSWORD、ADMIN_JWT_SECRET、ADMIN_TOKEN、CLIENT_API_TOKEN、MINIO_ACCESS_KEY、MINIO_SECRET_KEY、MINIO_BUCKET、MINIO_PUBLIC_ENDPOINT、CRASH_REPORT_TOKEN、CRASH_SYMBOL_TOKEN。
|
||||||
4. 准备签名私钥 keys/manifest_private_key.pem。
|
4. 准备签名私钥 keys/manifest_private_key.pem。
|
||||||
5. 准备 runtime、minio_data 等持久化目录。
|
5. 准备 runtime、minio_data 等持久化目录。
|
||||||
6. 执行 docker compose build。
|
6. 执行 docker compose build。
|
||||||
@@ -1422,7 +1499,7 @@ Docker 运行时,依赖的是镜像里的 Python、镜像里的依赖、容器
|
|||||||
|
|
||||||
示例命令:
|
示例命令:
|
||||||
|
|
||||||
cd server
|
cd update-server
|
||||||
cp -n .env.example .env
|
cp -n .env.example .env
|
||||||
mkdir -p runtime minio_data keys
|
mkdir -p runtime minio_data keys
|
||||||
docker compose config
|
docker compose config
|
||||||
@@ -1477,8 +1554,8 @@ Docker 是给“服务端部署人员”用的。
|
|||||||
|
|
||||||
建议下一步做两个包:
|
建议下一步做两个包:
|
||||||
|
|
||||||
1. server/docker 部署包:给运维或服务器部署人员。
|
1. update-server/docker 部署包:给运维或服务器部署人员。
|
||||||
2. client/UpdateClientSDK.zip:给其他软件开发人员。
|
2. update-client/UpdateClientSDK.zip:给其他软件开发人员。
|
||||||
|
|
||||||
10.11 现在具体怎么做
|
10.11 现在具体怎么做
|
||||||
|
|
||||||
@@ -1488,7 +1565,7 @@ Docker 是给“服务端部署人员”用的。
|
|||||||
|
|
||||||
1. 进入 server 目录。
|
1. 进入 server 目录。
|
||||||
2. 复制 .env.example 为 .env。
|
2. 复制 .env.example 为 .env。
|
||||||
3. 修改 ADMIN_TOKEN、CLIENT_API_TOKEN、MINIO_ACCESS_KEY、MINIO_SECRET_KEY、MINIO_BUCKET、MINIO_PUBLIC_ENDPOINT、CRASH_REPORT_TOKEN、CRASH_SYMBOL_TOKEN。
|
3. 修改 ADMIN_USERNAME、ADMIN_PASSWORD、ADMIN_JWT_SECRET、ADMIN_TOKEN、CLIENT_API_TOKEN、MINIO_ACCESS_KEY、MINIO_SECRET_KEY、MINIO_BUCKET、MINIO_PUBLIC_ENDPOINT、CRASH_REPORT_TOKEN、CRASH_SYMBOL_TOKEN。
|
||||||
4. 准备 keys/manifest_private_key.pem。
|
4. 准备 keys/manifest_private_key.pem。
|
||||||
5. 执行 docker compose config,确认配置无误。
|
5. 执行 docker compose config,确认配置无误。
|
||||||
6. 执行 docker compose build。
|
6. 执行 docker compose build。
|
||||||
@@ -1499,21 +1576,21 @@ Docker 是给“服务端部署人员”用的。
|
|||||||
|
|
||||||
第二步:准备客户端 SDK 包。
|
第二步:准备客户端 SDK 包。
|
||||||
|
|
||||||
1. 确认 client/out/bin 是 Release 输出目录。
|
1. 确认 update-client/out/bin 是 Release 输出目录。
|
||||||
2. 确认 out/bin 里有 Launcher.exe、Updater.exe、Bootstrap.exe。SimCAE 场景下不要把 SDK 自带 Qt DLL 覆盖到 SimCAE 的 bin 目录。
|
2. 确认 out/bin 里有 Launcher.exe、Updater.exe、Bootstrap.exe。SimCAE 场景下不要把 SDK 自带 Qt DLL 覆盖到 SimCAE 的 bin 目录。
|
||||||
3. 确认 config/manifest_public_key.pem 是服务端私钥对应的公钥。
|
3. 确认 config/manifest_public_key.pem 是服务端私钥对应的公钥。
|
||||||
4. 填好 client/config/app_config.example.json 里的示例字段。
|
4. 填好 update-client/config/app_config.example.json 里的示例字段。
|
||||||
5. 在 Windows PowerShell 执行:
|
5. 在 Windows PowerShell 执行:
|
||||||
|
|
||||||
cd client
|
cd update-client
|
||||||
.\package-sdk.ps1 -SourceDir .\out\bin -OutputDir .\dist\UpdateClientSDK -ZipFile .\dist\UpdateClientSDK.zip -SdkVersion 0.1.0
|
.\scripts\package-sdk.ps1 -SourceDir .\out\bin -OutputDir .\dist\UpdateClientSDK -ZipFile .\dist\UpdateClientSDK.zip -SdkVersion 0.1.0
|
||||||
|
|
||||||
第三步:给接入方一个最小验证方式。
|
第三步:给接入方一个最小验证方式。
|
||||||
|
|
||||||
1. 解压 UpdateClientSDK.zip。
|
1. 解压 UpdateClientSDK.zip。
|
||||||
2. 把接入方自己的 YourApp.exe 放到 bin 目录同级的最终产品目录中。
|
2. 把接入方自己的 YourApp.exe 放到 bin 目录同级的最终产品目录中。
|
||||||
3. 把 config/app_config.example.json 复制成 config/app_config.json。
|
3. 把 config/app_config.example.json 复制成 config/app_config.json。
|
||||||
4. 修改 app_id、channel、api_base_url、client_token、license_key、main_executable。
|
4. 修改 app_id、channel、client_token、license_key、main_executable,并确认 SDK 二进制已用正确的 config/server_config.json 编译。
|
||||||
5. 从 Launcher.exe 启动。
|
5. 从 Launcher.exe 启动。
|
||||||
6. 确认能登记设备、拉取策略、启动业务主程序。
|
6. 确认能登记设备、拉取策略、启动业务主程序。
|
||||||
|
|
||||||
@@ -1521,12 +1598,12 @@ cd client
|
|||||||
|
|
||||||
SDK 是给开发者看的;具体产品给客户安装时,使用 package-client.ps1:
|
SDK 是给开发者看的;具体产品给客户安装时,使用 package-client.ps1:
|
||||||
|
|
||||||
cd client
|
cd update-client
|
||||||
.\package-client.ps1 -SourceDir .\out\bin -ConfigFile .\config\app_config.json -OutputDir .\dist\UpdateClient -ZipFile .\dist\UpdateClient.zip
|
.\scripts\package-client.ps1 -SourceDir .\out\bin -ConfigFile .\config\app_config.json -OutputDir .\dist\UpdateClient -ZipFile .\dist\UpdateClient.zip
|
||||||
|
|
||||||
第五步:补接入方文档和 Demo。
|
第五步:补接入方文档和 Demo。
|
||||||
|
|
||||||
1. SDK 根目录只保留一个 Word 接入说明作为入口,打开包后一眼能看到。
|
1. SDK 包内提供 Docs/00-先读我-客户端文档入口.txt 作为默认入口;Word 说明仅作为可选增强。
|
||||||
2. 准备一个最小 MainApp 示例,演示 --ticket-file 和 --health-file。
|
2. 准备一个最小 MainApp 示例,演示 --ticket-file 和 --health-file。
|
||||||
3. 准备一份常见错误说明。
|
3. 准备一份常见错误说明。
|
||||||
4. 准备一份服务端 Docker 部署说明。
|
4. 准备一份服务端 Docker 部署说明。
|
||||||
|
|||||||
Reference in New Issue
Block a user