feat(runtime): 本体更新时一并更新 Runtime 可执行文件 - #609
Open
qiyinxi wants to merge 2 commits into
Open
Conversation
`auto-mas-runtime.exe` 此前只能靠重装整包升级:`bootstrap --version` 能把本体源码 换成新版本,Runtime 却停在装机那天,于是「新本体 + 旧 Runtime」这种从未联调过的 组合会出现在用户机器上。 把 Runtime 版本钉扎进本体源码,让它跟着源码走: - 新增 `res/runtime.json`(version + sha256),成为版本与哈希的唯一来源。发布 CI 与 `scripts/build-local-package.ps1` 都不再从 `build-app.yml` 的 `RUNTIME_VERSION` 正则 抠版本号,改读它;下载后同时对该 Release 的 SHA256SUMS.txt 与钉扎值各校验一次—— 前者证明文件没坏,后者证明钉扎没抄错版本,而装机后的桌面端只认钉扎值。 - 新增 `runtimeBinaryService`:读钉扎、问现有 exe 自报的版本、按 gh-proxy 家族到 GitHub 官方的顺序轮换下载、校验 SHA-256 后原地替换。 - `backendService` 在 managed 启动链路 `bootstrap --if-needed` 之后、`supervise` 之前 接一次同步——此刻旧监督进程已退出、新的还没起来,是唯一能安全替换 exe 的窗口; `runtimeUpdateService` 在源码换完之后、重启之前加一个 `runtime` 进度段,让界面在 下载那十几兆时有话可说。两处调的是同一个函数。 几处取舍: - 判身份用 exe 自报的版本而不是文件哈希。哈希只能证明「下到的那份没坏」,本地那份 被重签名、杀软隔离后还原之类的后处理动过一个字节就永远对不上,会让每次启动都白 下载十几兆;版本比对不受影响。`scripts/build-local-package.ps1` 早就是这么校验的。 - 判据是版本相等而不是「钉扎的更新才换」,本体回退时 Runtime 必须跟着退回去。 - 取不到新 Runtime 只记警告继续用旧的启动,不阻断;不一致留到下次启动重试。 - 替换首选一次 rename 直接盖过去(Windows 上是原子的),只有目标被占用时才退回 「改名让路 → 挪新文件 → 失败改回来」。避免出现「目录里没有 exe」这种一旦发生就 只能重装的状态:那时 `resolveRuntimeExecutable()` 返回 null,同步逻辑根本进不去。 - 一轮同步有 10 分钟总预算,换源之前查一次。卡死的连接由下载器自己的超时兜住,但 「连得上、就是慢」不会触发那些超时,四个源各拉一遍能把启动挂上一个钟头。 - 取消更新时不核对 Runtime:那条路源码一动没动,没有要对齐的东西,也不该在用户点了 取消之后开一个他取消不掉的下载。 - 镜像顺序自己实现而不复用 `MirrorRotationService`——后者会把 key 含 github 的源提到 最前,正好把国内用户最连不上的官方源排到第一个。 本地验证(`frontend`):`yarn test` 444 用例通过 443,唯一失败的 `backendService.test.ts` 5 秒超时在 dev 基线上把本文件换回原版复跑同样失败; `yarn lint`、`yarn build:main`、`yarn typecheck`、`yarn lint:md` 均通过。 `build-app.yml` 的 pwsh 片段与 `scripts/build-local-package.ps1` 都过了 PowerShell AST 解析,钉扎读取逻辑单独演练过。另用真实 `auto-mas-runtime-v0.1.4.exe` 核对过 `--output ndjson --protocol 1 version` 的 `details.runtimeVersion` 逐字为 `v0.1.4`。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
审查者指南本 PR 将 Runtime 版本及哈希钉扎到本体源码,并在构建、启动和本体更新链路中统一使用该钉扎值:受管 Runtime 会在安全窗口按版本检查、镜像轮换下载、SHA-256 校验后原地替换,失败则保留旧版本继续运行,同时向更新界面报告进度。 受管 Runtime 二进制同步时序图sequenceDiagram
participant BackendService
participant RuntimeBinaryService
participant RuntimeExe
participant Downloader
participant GitHub
BackendService->>RuntimeBinaryService: syncRuntimeBinary(runtimePath, appRoot, sourceRoot)
RuntimeBinaryService->>RuntimeBinaryService: readRuntimeBinaryPin(sourceRoot)
RuntimeBinaryService->>RuntimeExe: version
RuntimeExe-->>RuntimeBinaryService: runtimeVersion
alt version matches pin
RuntimeBinaryService-->>BackendService: current
else version differs or unavailable
loop proxy sources then GitHub
RuntimeBinaryService->>Downloader: download(source.url, downloadPath)
Downloader->>GitHub: GET pinned Runtime asset
GitHub-->>Downloader: executable
RuntimeBinaryService->>RuntimeBinaryService: hashFileSha256(downloadPath)
end
RuntimeBinaryService->>RuntimeBinaryService: replaceRuntimeBinary(runtimePath, downloadPath, backupPath)
RuntimeBinaryService-->>BackendService: upgraded
end
源码替换后的 Runtime 更新时序图sequenceDiagram
participant RuntimeUpdateService
participant BackendService
participant RuntimeBinaryService
participant Supervisor
RuntimeUpdateService->>BackendService: stopBackend()
BackendService->>BackendService: bootstrap --version
BackendService-->>RuntimeUpdateService: repository updated
RuntimeUpdateService->>RuntimeBinaryService: syncRuntimeBinary(runtimePath, appRoot, repo)
alt synchronization succeeds
RuntimeBinaryService-->>RuntimeUpdateService: upgraded or current
else synchronization fails
RuntimeBinaryService-->>RuntimeUpdateService: failed
RuntimeUpdateService->>RuntimeUpdateService: continue with existing Runtime
end
RuntimeUpdateService->>BackendService: startBackend()
BackendService->>Supervisor: supervise()
RuntimeUpdateService-->>RuntimeUpdateService: runtime progress completed
文件级变更
提示和命令与 Sourcery 交互
自定义你的体验访问你的控制面板以:
获取帮助Original review guide in EnglishReviewer's Guide本 PR 将 Runtime 版本及哈希钉扎到本体源码,并在构建、启动和本体更新链路中统一使用该钉扎值:受管 Runtime 会在安全窗口按版本检查、镜像轮换下载、SHA-256 校验后原地替换,失败则保留旧版本继续运行,同时向更新界面报告进度。 Sequence diagram for managed Runtime binary synchronizationsequenceDiagram
participant BackendService
participant RuntimeBinaryService
participant RuntimeExe
participant Downloader
participant GitHub
BackendService->>RuntimeBinaryService: syncRuntimeBinary(runtimePath, appRoot, sourceRoot)
RuntimeBinaryService->>RuntimeBinaryService: readRuntimeBinaryPin(sourceRoot)
RuntimeBinaryService->>RuntimeExe: version
RuntimeExe-->>RuntimeBinaryService: runtimeVersion
alt version matches pin
RuntimeBinaryService-->>BackendService: current
else version differs or unavailable
loop proxy sources then GitHub
RuntimeBinaryService->>Downloader: download(source.url, downloadPath)
Downloader->>GitHub: GET pinned Runtime asset
GitHub-->>Downloader: executable
RuntimeBinaryService->>RuntimeBinaryService: hashFileSha256(downloadPath)
end
RuntimeBinaryService->>RuntimeBinaryService: replaceRuntimeBinary(runtimePath, downloadPath, backupPath)
RuntimeBinaryService-->>BackendService: upgraded
end
Sequence diagram for Runtime update after source replacementsequenceDiagram
participant RuntimeUpdateService
participant BackendService
participant RuntimeBinaryService
participant Supervisor
RuntimeUpdateService->>BackendService: stopBackend()
BackendService->>BackendService: bootstrap --version
BackendService-->>RuntimeUpdateService: repository updated
RuntimeUpdateService->>RuntimeBinaryService: syncRuntimeBinary(runtimePath, appRoot, repo)
alt synchronization succeeds
RuntimeBinaryService-->>RuntimeUpdateService: upgraded or current
else synchronization fails
RuntimeBinaryService-->>RuntimeUpdateService: failed
RuntimeUpdateService->>RuntimeUpdateService: continue with existing Runtime
end
RuntimeUpdateService->>BackendService: startBackend()
BackendService->>Supervisor: supervise()
RuntimeUpdateService-->>RuntimeUpdateService: runtime progress completed
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
复核在 AUTO-MAS-Project#609 上发现的几处问题: - `syncRuntimeBinary` 没有在途互斥:devtools 的重启按钮与 `backend-start` IPC 能在更新 链路的同步还没结束时再触发一次启动,两份下载会写同一个 `.download` 文件,让一个没 校验过的文件盖到 exe 上。加模块级在途记录,后来者复用同一个 promise 的结果,进度 回调也一并转发。 - 单个慢源没有时长上限:10 分钟预算只在换源之前查,分片超时又只管空闲,「连得上但被 限速」的源能跑半小时。给每个源加上限(剩余预算与总预算一半取小),超时就换下一个源。 下载器没有取消接口,被放弃的那次仍会往文件里写,所以每次尝试各用一个 `<exe>.download-<token>` 临时文件,等它自己结束后再清;下次同步按前缀清扫全部残留。 - `-LocalRuntimePath` 打出来的包在首次 managed 启动时会被钉扎版覆盖,开发者以为在验证 自己的 Runtime。安装包不带 `res/runtime.json`,同步逻辑读的是 Runtime 克隆到 `<app-root>/repo/` 的那一份,打包脚本改不了它,所以在 README 写明必须设 `AUTO_MAS_RUNTIME_EXE`,并让脚本在该分支打印提示。 - 补上 `replaceRuntimeBinary` 目标被占用时「改名让路」与「让路后失败回滚」两条路径的 测试;`runtimeUpdateService.test.ts` 里写死反斜杠的路径断言改成 `path.join`。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
auto-mas-runtime.exe现在只能靠重装整包升级:bootstrap --version会把repo/换成新版本源码,Runtime 却停在装机那天,用户机器上会出现「新本体 + 旧 Runtime」这种没联调过的组合。本 PR 把 Runtime 版本钉扎进本体源码,让它跟着源码一起走。
改了什么
res/runtime.json(version+sha256),成为 Runtime 版本与哈希的唯一来源。它随发布分支进到用户的repo/res/runtime.json。build-app.yml与scripts/build-local-package.ps1不再从 workflow 的RUNTIME_VERSIONenv 取版本,改读这个文件;下载后除了对该 Release 的SHA256SUMS.txt校验,再和钉扎值比一次——前者证明文件没坏,后者证明钉扎没抄错版本,而装机后的桌面端只认钉扎值。frontend/electron/services/runtimeBinaryService.ts:读钉扎 → 问现有 exe 自报的版本 → 不一致就按 gh-proxy 家族到 GitHub 官方的顺序轮换下载 → 校验 SHA-256 → 原地替换。backendService在 managed 启动链路bootstrap --if-needed之后、supervise之前(此刻旧监督进程已退出、新的还没起来,是唯一能安全替换 exe 的窗口);runtimeUpdateService在源码换完之后、重启之前加一个runtime进度段。几处取舍
scripts/build-local-package.ps1本来就是这么校验 Runtime 的,口径一致。rename直接盖过去(Windows 上原子),只有目标被占用时才退回「改名让路 → 挪新文件 → 失败改回来」。避免出现「目录里没有 exe」这种一旦发生就只能重装的状态——那时resolveRuntimeExecutable()返回 null,同步逻辑根本进不去。兼容性
res/runtime.json缺失或字段非法一律按「本体没有钉扎」处理,什么都不做——回退到本 PR 之前发布的版本不会让启动失败。development模式与AUTO_MAS_RUNTIME_EXE指定的 Runtime 都不碰。本地验证
frontend目录:yarn test444 用例通过 443。唯一失败的是 dev 上既存的backendService.test.ts里managed 模式 > 不传 --repo、不先跑 environment ensure,--app-root 就是用户数据根(5 秒超时)——把该文件换回 dev 原版复跑同样失败,与本 PR 无关。yarn lint/yarn build:main/yarn typecheck/yarn lint:md均通过。其它:
build-app.yml的 pwsh 片段(${{ }}换占位量后)与scripts/build-local-package.ps1都过了[Parser]::ParseFile语法检查;build-local-package.ps1 -VerifyRuntimeOnly真跑通了一遍(下载 v0.1.4、清单哈希与钉扎哈希比对通过、exe 自报v0.1.4、退出码 0)。auto-mas-runtime-v0.1.4.exe核对过--output ndjson --protocol 1 version的details.runtimeVersion逐字为v0.1.4,与钉扎格式一致。没有验证的:真实受管安装下的整条下载与替换(手上没有受管安装现场);
build-app.yml只能等真发版才跑到。🤖 Generated with Claude Code
Sourcery 摘要
确保托管 Runtime 可执行文件在整个构建、更新和启动过程中始终与应用程序源代码版本保持一致。
新功能:
错误修复:
增强功能:
构建:
文档:
测试:
Original summary in English
Summary by Sourcery
Keep the managed Runtime executable aligned with the application source version throughout builds, updates, and startup.
New Features:
Bug Fixes:
Enhancements:
Build:
Documentation:
Tests:
Original summary in English