# 自动更新与管理控制台 当前项目版本:MVP0.5.5 / v0.5.5。[当前开发总结](../Development/DevelopmentSummary.md)为统一现状入口。本页旧版本、日期和验收数值保留为历史记录,不能作为本次重复验收。 2026-10-21:新增启动器、独立 Docker 更新服务与只读管理控制台。本次MVP0.5.5统一打包完整游戏与更新服务,独立启动器暂提供本机测试包;暂无公网HTTPS启动器。没有修改已经发布的 v0.5.3 标签或四个正式游戏包。用户确认暂不租服务器,先在 Docker 验证,随后迁移。 ## 当前入口 - 玩家下载主页:http://localhost:18080/ - 管理控制台:http://localhost:18080/admin - 独立文件服务:http://localhost:18081/ - 正式更新清单:http://localhost:18081/service.json - 自动构建测试清单:http://localhost:18081/preview-service.json(首次成功同步后存在) - GitHub 自动同步记录:https://github.com/liu-jingjie/sanguo-cards/actions/workflows/update-service.yml 本机 HTTP 仅为环回地址开发验收,不能作为公网 HTTPS。后台明确显示公网未接通;未来有域名后使用独立服务器的 Caddy 自动签发证书。游戏账号 API、数据库、更新服务三者分开,更新服务没有数据库连接与账号凭证。 本机 Mac M 系列启动器测试包可在控制台的“更新服务”中下载。它固定连接当前电脑的18081端口,首次安装完整游戏,之后读取正式通道;仅适合当前本机Docker验证,不作为公网正式启动器。 ## 玩家启动行为 第一次需要安装含启动器的新包。现有 MVP0.5.3 原包无法自己获得启动器。启动器是独立自包含程序,玩家不需要安装 Python 或 .NET;本阶段用系统浏览器显示更新进度,后续可替换为原生窗口,更新协议不变。 启动器打开后自动检查签名清单,下载有变化的文件、校验后安装并自动运行游戏。未变化的图片、音乐等文件从已有安装复制,跨平台相同内容在下载服务中按 SHA-256 去重。当前采用文件粒度更新,Unity 重新生成的大型资源文件仍可能导致较大更新;二进制差分与 Addressables 远程资源拆分尚未实现。 - 每个文件支持 Range 断点续传;服务器忽略 Range 时安全重新下载该文件。大小、SHA-256 或返回范围不符则拒绝。 - 清单使用 RSA 至少3072位、SHA-256签名,启动器内固定公钥;拒绝篡改、错误平台、过旧发布序号、路径穿越、不安全符号链接与 HTTP 公网下载。禁止跨地址重定向。 - 所有文件先安装到独立暂存目录;完成后原子切换当前版本指针。下载失败不更改正在使用的版本,不触碰 Unity 存档或云端账号。 - 保留当前与上一版;可主动恢复上一版。签名清单可指定最低允许游戏版本,强制更新时禁止启动旧版和恢复过旧版本;该下限在下载前保存,失败也不会绕过限制。 - 正式/测试通道及不同下载地址使用独立安装目录,发布序号和续传数据不会交叉污染;下载过程中可安全关闭,下次继续。 - 游戏运行期间禁止更新操作。启动器全程持有本机独占锁。发现当前版本文件损坏时可重新校验修复。 - 启动器本身需要升级时,提示重新获取启动器;本阶段没有启动器自身的在线替换机制。 - 状态窗口包含12种语言机器翻译,未称为专业母语审校;不改变游戏现有1807条语言资源。 - Mac 启动器及现有游戏尚未完成开发者签名公证;Windows/Intel Mac 实机启动仍待验收。构建成功不等同各设备实测。 ## GitHub 提交后自动同步 `build-clients.yml` 继续构建四平台完整游戏包。`update-service.yml` 监听其成功完成事件,仅接受同仓库 main 的可信构建,并下载对应 ci 标签的四个包与外部清单;校验来源提交、四平台一致性、ZIP 与 SHA-256 后自动导出和同步 **preview 测试通道**。构建失败也会写入后台可读的失败状态,但不导出、不切换更新;校验失败同样保留旧通道;较早提交较晚完成时跳过,不能覆盖新提交。 发布正式 `vX.Y.Z` GitHub Release 时,自动同步 **stable 正式通道**;不把普通 main 提交直接推给正式玩家。GitHub `GITHUB_TOKEN` 生成的测试发布不会触发另一条 release 流水线,因此测试同步使用 `workflow_run`。正式发布应由用户授权的发布身份触发,或同一发布流程显式调用同步入口。可选的手动 dispatch 只用于失败重试,日常无需手动同步。 更新内容按 SHA-256 存储,四个平台在一次原子目录指针切换中同时启用。保留旧发布与旧 blob,不自动清空版本。发布锁由内核管理,中途退出不遗留阻塞锁。启动器构建机需要.NET 10 SDK,四平台构建已实际通过;文件服务器本身只需Docker。签名私钥只在构建机私有目录,不进入 Git、GitHub 变量、客户端、Docker 文件服务或发布附件。CI 使用只读仓库令牌下载私有附件,玩家下载无需 GitHub 登录。 构建机私有部署配置 `Backend/.local/update-deployment.json`: ```json { "publicRoot": "/srv/sanguo-updates/public", "signingKey": "/srv/sanguo-updates/private/update-signing.pem", "origin": "http://localhost:18081", "mode": "docker", "minimumGameVersion": "0.0.0" } ``` GitHub 仓库变量 `SANGUO_UPDATE_DEPLOY_CONFIG` 指向构建机上的该文件。此变量仅包含路径,不含私钥或密码。以后迁移时改为 `mode: ssh`、真实 `https://下载域名`,增加 `host` 和 `remoteRoot`;SSH 使用构建机安全保存的身份;迁移时一次性配置经过核对的主机密钥与免交互部署身份,并在两端安装 rsync。自动任务启用 BatchMode 和严格主机密钥检查,不会停下来询问密码。上传顺序先 blob/不可变发布,再通道指针,最后状态文件;完成后检查四平台签名与实际 Range 下载。失败记录写入 `automation-{channel}.json`,管理后台显示结果;账号数据库不参与。 正式 HTTPS 启动器的自动构建使用三个公开仓库变量:`SANGUO_UPDATE_ORIGIN`、`SANGUO_UPDATE_PUBLIC_KEY_PEM`、`SANGUO_DOWNLOAD_PAGE`。没有真实域名时不生成伪公网启动器。当前本机测试包明确使用环回 HTTP;不能将其原样发给远程玩家,迁移公网后需要生成固定真实 HTTPS 地址的正式启动器。 ## 初始化与本机运行 只需初始化一次并安全备份私钥: ```sh mkdir -p Backend/.local/secrets Backend/.local/update-service openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out Backend/.local/secrets/update-signing.pem chmod 600 Backend/.local/secrets/update-signing.pem docker compose --env-file Backend/.local/compose.env up -d --no-deps updates ``` 已有私钥时不得重新生成覆盖;公钥变更需要给启动器升级信任配置。首次从已验证正式包导入示例: ```sh python3 tools/release/update_service.py --release-dir Backend/.local/downloads/v0.5.3 --output Backend/.local/update-service --private-key Backend/.local/secrets/update-signing.pem --origin http://localhost:18081 --sequence 1 ``` 这只是首次导入和诊断入口;后续 GitHub 自动同步不要求每次执行。原 `sync_portal.py` 正式主页同步也已接入 stable 导出并启动 updates 容器。后台页面同步只重建 API,不清库。单独的更新内容同步无需重启 API 或 Docker,挂载目录实时生效。 ## 迁移到独立 HTTPS 服务器 1. 创建下载域名 A/AAAA 记录,开放服务器80/443;准备 Docker。 2. 只迁移 `Backend/.local/update-service` 的公开内容至服务器公开目录。私钥仍留在可信构建机,另外离线备份;不要拷贝账号配置、数据库卷或整个 `.local`。 3. 上传 `Backend/Updates/Caddyfile` 与 `compose.https.yaml`;复制 `https.env.example` 为私有环境文件,填写真实域名和公开文件目录。 4. 执行 `docker compose --env-file 私有环境文件 -f Backend/Updates/compose.https.yaml up -d`,Caddy 自动申请/续期证书。此步骤需要真实 DNS 与可达端口,本地不冒充已验收。 5. 更改构建机私有部署配置为 `ssh` 模式与 HTTPS origin,更新三个公开构建变量;首次同步后检查 `deploy_updates.py --probe-only`。正式启动器内固定公钥与 HTTPS 通道。 6. 保留旧服务直到新 HTTPS 域名实际可用;完整哈希由启动器再次验证。正式用户启动器地址应保持域名不变,后续只改 DNS/后端,避免再发安装器。 配置样例在 `Backend/Updates/`。域名、服务器费用与公网证书验收均未完成。 ## 管理界面 侧边导航包含总览、版本与下载、更新服务、开发资料、运行状态。展示已发布包、签名更新入口、GitHub 自动同步结果、账号服务与数据库连接。后台目前只读,不提供数据库清理或远程发布按钮;新增写操作时必须先增加管理员身份验证,不能复用普通玩家权限。 ## 验证 复跑: ```sh python3 -m unittest discover -s Tests/Release -v dotnet run --project Tests/Updater/Updater.csproj -c Release dotnet run --project Tests/Updater/Updater.csproj -c Release -- --service Backend/.local/update-service python3 tools/localization/catalog.py --check ``` 实际检查与截图见同目录 `Validation.json`。真实 Docker Mac 完整安装与无变化重查没有运行游戏或登录账号。公网 HTTPS、跨设备长途网络及Windows原生启动尚待具备环境后验证。 本次真实自动验收:GitHub构建39525831722四平台全部成功,其workflow_run自动触发同步39528419594并成功;自动测试通道标签ci-20-559f5c24135e,来源559f5c24135e3dbb14de748d806575844300c28f。正式通道首次验收39525988230成功。启动器61项、发布62项及界面/实际断点重开均通过;完整差量、范围及限制见Validation.json。公网HTTPS仍未上线。