Repository navigation
feat(updater): 更新清单改由 CDN 提供,客户端不再读 release 里的 json - #1277
Conversation
窗口内的更新器原先从 GitHub Release 资产取清单
(releases/latest/download/latest-{target}-{arch}[-beta].json),于是每个 release
要挂 14 个 latest-*.json(7 个 target/arch × mirror 双份),且 Stable 走滚动
指针 → 每次发版都要把同名文件重新传一遍。
改成读项目自己的 CDN:
https://dl.aeoform.com/updates/stable/latest-{target}-{arch}.json
https://dl.aeoform.com/updates/beta/latest-{target}-{arch}-beta.json
- 每个平台/渠道只有一个滚动文件,发版覆盖即可,不再往 release 累积副本。
- 渠道隔离从「文件名后缀」变成「URL 路径」,Stable 客户端拿不到 Beta 清单。
- 清单格式不变(version/pub_date/url/signature),plugin-updater 继续负责下载、
minisign 校验与安装;清单里的下载地址也指向 CDN,国内下载不再经过 github.com。
- Beta 不再需要拉 releases.atom 找 tag,整条链路去掉一个 github.com 依赖。
- Android 更新检查同步改为 CDN 单地址;SSRF 白名单加入 CDN,同时保留旧
GitHub/fastgit 前缀,已缓存的旧清单仍可安装。
release 侧发布流程与既有资产完全不动。
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
客户端已经改读 dl.aeoform.com 的 /updates/{stable,beta}/ 清单(上一提交),
release 里那 14 个 latest-*.json 没有任何客户端再读,继续上传只会让每个
release 多背 14 个几乎相同的文件。
- release-tauri.yml:softprops files 去掉 bundle/latest-*.json。桌面清单仍然
通过既有的 openless-macos-<arch>-updater / openless-windows-x64-updater
产物离开 workflow(CDN 同步从那里取)。
- android-apk.yml:release 文件列表去掉 latest-android-*.json;新增
openless-android-updater-manifests 产物,否则 Android 清单会随删除一起丢失
(原来它只存在于 release 资产里)。顺带把 release 正文里的清单说明改成 CDN
口径。
- 契约测试跟着收紧:
- release-publication-contract:两个 workflow 的发布者 files 不得含
latest-*.json,且必须有且仅有一个 upload-artifact 携带这些清单。
- android-apk-workflow-contract:把清单文件放进 fixture,断言它们不会进
release 资产,并断言清单产物步骤存在。
- README / README.zh / RELEASING:说明清单由运行产物手动同步到 CDN,以及
改动前的客户端读的是旧 GitHub 路径、因此需要一次手动下载。
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ecc9994309
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const DIRECT_BASE: &str = "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/Open-Less/openless"; | ||
| const MIRROR_BASE: &str = "https://fastgit.cc/https://github.com/Open-Less/openless"; | ||
| if !url.starts_with(DIRECT_BASE) && !url.starts_with(MIRROR_BASE) { | ||
| if !url.starts_with(CDN_BASE) |
There was a problem hiding this comment.
Validate the CDN hostname rather than its string prefix
On Android, an update manifest containing a URL such as https://dl.aeoform.com@attacker.example/package.apk now passes this allowlist even though the request goes to attacker.example. Unlike the existing GitHub prefixes, which include a path after the hostname, the new CDN prefix ends at the authority and therefore accepts userinfo and hostname-suffix tricks. android::updater::download_and_install makes the request before verifying the signature, so signature verification does not prevent the unintended network access. Parse the URL and require the HTTPS scheme and exact CDN hostname before downloading.
Useful? React with 👍 / 👎.
摘要
Fixes #(无关联 issue:来自 release 资产里 14 个
latest-*.json的整理诉求)。更新器的清单来源从 GitHub Release 资产搬到项目 CDN,并停掉「把 14 个
latest-*.json挂到每个 release」这一步:清单格式完全不变(
version/pub_date/url/signature),tauri-plugin-updater继续负责下载、minisign 校验和平台安装,只换「去哪里取清单」。历史 release 里的 json 一份没删;新 release 不再产生它们。修复 / 新增 / 改进
src-tauri/src/update_source.rs:CDN 基址 + 清单 URL 模板的唯一来源(endpoint_template/manifest_url),带 5 个单测覆盖 stable/beta 路径、7 个 target/arch 组合与 token 替换。tauri.conf.json:plugins.updater.endpoints从 GitHub 直连 + fastgit 两条改成 CDN Stable 一条({{target}}/{{arch}}占位符保留,由插件在 check 时替换)。commands/settings.rs:Beta 渠道不再走「拉releases.atom找最新 prerelease tag → 拼releases/download/{tag}/...-beta.json」,改成直接切 CDN 的/updates/beta/路径;resolve_beta_manifest_endpoints(含 mirror/direct 拼装)整段删除,Beta 检查少一次 github.com 往返。android/updater.rs+android/updater_logic.rs:Android 检查改为 CDN 单地址(manifest_url(channel, "android", arch)),删掉stable_manifest_urls/beta_manifest_urls与parse_beta_atom死代码及其 4 个测试;atom 解析本身与它的测试保留(IPCfetch_latest_beta_release仍在用)。app_download_and_install_android_update的 SSRF 白名单加入 CDN 前缀,并保留旧 GitHub/fastgit 前缀(旧清单里缓存的地址仍可安装)。repository-owner-contract:原来断言「endpoints 必须指向当前 GitHub 仓库」,改断言 endpoints 指向update_source.rs里CDN_BASE声明的同一 CDN、走/updates/stable/latest-、保留占位符、且不得再指向github.com(把两个文件里的约定钉在一起,避免以后单边漂移)。README.md/README.zh.md的更新说明与 Beta 分发说明改为 CDN 口径;RELEASING.md补一条「发版后清单必须从 run artifact 同步到 CDN」;shared_types.rs里UpdateChannel的注释同步。release-tauri.yml的 softpropsfiles去掉bundle/latest-*.json;android-apk.yml的 release 文件列表去掉latest-android-*.json,并新增openless-android-updater-manifests产物(否则 Android 清单会随删除一起丢失,原来它只活在 release 资产里)。桌面清单继续通过既有的openless-macos-<arch>-updater/openless-windows-x64-updater产物离开 workflow,CDN 同步从那里取。兼容
write-updater-manifest.mjs的生成逻辑(含-mirror变体,历史仍在读它的旧客户端不受影响)、不改签名材料与 AGC、不删除任何历史 release 的资产。releases/latest/download/latest-*.json。新 release 不再带这些文件,因此它们无法自动更新到本版本之后,需要手动下载一次。这是「让新 release 干净」的必然代价;如果不接受,把第二个提交(ci(release):)单独回滚即可,客户端改动与它互不依赖。RELEASING.md已写明。github.com(清单 + 安装包都走dl.aeoform.com),fastgit 兜底随之取消——CDN 成为单一源,若 CDN 不可用则更新检查失败(旧版本仍可用 GitHub 路径)。releases.atom请求;渠道隔离从文件名后缀(-beta.json)变成 URL 路径(/updates/beta/)。2.0.1的.sigtrusted comment 里没有version:段(早于 Tauri CLI--app-version),2.0.2-Beta.3有。本方案走插件标准check()路径,不要求签名内嵌版本(未使用restore_update,那条路会强制require_signed_version并对 2.0.1 的包报MissingSignedVersion)。若将来想改成「客户端直接从 tag +.sig推导,彻底不要清单」,这个差异会变成阻塞点。测试计划
node scripts/*contract*.test.mjs(44 个)repository-owner-contract、android-apk-workflow-contract、release-publication-contract)npm run check:android-updater-pubkeyOK(pubkey 未变)cargo check --locked --manifest-path src-tauri/Cargo.toml --target aarch64-linux-android(NDK 26.1.10909125,SHERPA_ONNX_LIB_DIR就绪)Finished dev profile in 1m 07s,新增/改动的 android 侧与update_source无 error、无 warning(其余 374 条 warning 为既有)update_source.rs单测(把该文件原样挂进独立 crate 跑,因为本机没有 macOS/Windows 工具链可编 Tauri 桌面配置)5 passedmacOS checks12m21s ✅、Windows checks18m20s ✅(本机无 macOS/Windows 工具链,本地无法编译该 cfg)。scripts/*.test.mjs全部通过;YAML 解析由release-publication-contract/android-apk-workflow-contract用 js-yaml 加载校验。200且为当前版本(stable2.0.1+build.20261016,beta2.0.2-Beta.3+build.20261026-c9f49c60):updates/{stable,beta}/latest-{darwin,windows,android}-{aarch64,x86_64,armv7,i686}[-beta].json(含 armv7/i686 等全部组合)。url指向的 CDN 安装包可下载:HTTP 200。signature与上游 release 资产*.sig逐字节一致(2.0.1darwin-aarch64、Beta.3windows-x86_64 各验一次),即 CDN 只是镜像、签名绑定未变。latest-{{target}}-{{arch}}.json→url::Url编码为%7B%7Btarget%7D%7D→ 插件 replace 后得到https://dl.aeoform.com/updates/stable/latest-darwin-aarch64.json,与上面 200 的地址一致(单独跑了一段模拟插件替换的验证)。