MooTool Next Tauri 自动更新清单架构解析:双层清单与独立发布通道的设计与实践 桌面应用开发工具【免费下载链接】MooToolHandy tool set for developers项目地址https://gitcode.com/gh_mirrors/mo/MooTool点击查看免费下载本文基于 next-tauri/doc/adr/008-updater-manifest.md 展开。MooTool 仓库同时维护 Java、Electron 与 Tauri 三条桌面产品线如何让 Tauri 客户端拥有稳定的latest.json静态更新源又不破坏各产品线的独立发布边界是本文要解决的核心问题。读完本文你将理解双层更新清单根update-manifest.jsonnext-tauri-updater/latest.json的职责划分、Rust Core 侧的校验逻辑、CI 发布与人工提升promotion流水线以及防回退与幂等策略的工程细节。背景多产品线共存带来的更新源冲突MooTool 仓库是一个多产品线仓库同时维护Java 桌面版使用v*tag 和version_summary.json更新清单MooTool Next Electron使用next-electron-v*tag 和独立的 Electron 更新清单MooTool Next Tauri基于 Tauri 2、Rust、React 与 TypeScript 的独立产品线。ADR-008 明确指出问题的本质Tauri Updater 需要一个平台级的静态latest.json版本号、发布日期、发行说明、各平台下载 URL 与 updater 签名这是tauri-plugin-updater的常规消费格式仓库又需要一个统一入口来表达不同产品的状态与历史如果直接让 Tauri 客户端读取 Electron 清单或让多个产品共用同一个稳定更新 URL就会破坏独立产品边界——一个产品的回滚、发布或失败会连带影响另一条产品线。因此这份 ADR状态已采纳日期2026-08-17确定了两层清单的架构方案。双层清单根清单只做“产品发现”latest.json才是“更新源”第一层根update-manifest.json只负责产品发现仓库根目录的 update-manifest.json 是仓库级统一入口使用schemaVersion: 1下面挂载java、next-electron、next-tauri三个产品节点。以 Tauri 节点为例当前仓库状态next-tauri: { displayName: MooTool Next Tauri, status: active, updaterManifestUrl: https://github.com/rememberber/MooTool/releases/download/next-tauri-updater/latest.json, releases: [ { version: 0.1.0-rc.1, title: MooTool Next Tauri 0.1.0-rc.1, prerelease: true, releaseUrl: https://github.com/rememberber/MooTool/releases/tag/next-tauri-v0.1.0-rc.1, updaterManifestUrl: https://github.com/rememberber/MooTool/releases/download/next-tauri-updater/latest.json, assets: [ ] } ] }关键约定继承自 ADR-008 决策点 1、3Tauri 客户端固定读取products.next-tauri验证产品名、状态和专属更新 URL不解析其他产品节点首次正式提升前products.next-tauri.status保持planned首次成功提升后才改为active决策点 6 的结果。当前仓库中该节点已是active并记录了0.1.0-rc.1、0.1.0-rc.2两个候选版本只有发布脚本允许修改该节点Java/Electron 的版本、标签、资产与清单节点不在 Tauri 流程范围内。第二层next-tauri-updater/latest.json是 Tauri Updater 的稳定静态清单Tauri 客户端实际消费的更新源是next-tauri-updater这个独立 Release 中的latest.json。其结构在 next-tauri/scripts/prepare-release-assets.mjs 中定义{ version: 0.1.0-rc.2, notes: 发行说明正文, pub_date: 2026-09-05T22:31:09Z, release_url: https://github.com/rememberber/MooTool/releases/tag/next-tauri-v0.1.0-rc.2, platforms: { darwin-x86_64: { signature: base64 minisign 签名, url: https://github.com/rememberber/MooTool/releases/download/next-tauri-v0.1.0-rc.2/MooTool-Next-Tauri-0.1.0-rc.2-mac-x64.app.tar.gz }, darwin-aarch64: { signature: ..., url: ...mac-arm64.app.tar.gz }, windows-x86_64: { signature: ..., url: ...win-x64-setup.exe }, linux-x86_64: { signature: ..., url: ...linux-x64.AppImage } } }它覆盖 ADR-008 决策点 2 要求的所有字段版本、发布日期、发行说明、Release URL以及 macOS x64/arm64、Windows x64、Linux x64 的下载 URL 与 updater 签名。pub_date由发布工作流从 tag 提交时间解析为 RFC 3339 字符串见 next-tauri-release.yml 中git show -s --format%cI ${tag}^{commit}Rust Core 侧再格式化为前端可展示的日期。Rust Core 侧更新源固定且不可由渲染层注入ADR-008 决策点 5结果段强调“更新源固定且由 Rust Core 校验不能由渲染层注入任意端点”。这一约定在 next-tauri/src-tauri/src/commands/update.rs 中直接落地const PRODUCT_ID: str next-tauri; const PRODUCT_NAME: str MooTool Next Tauri; const UPDATE_REGISTRY_URL: str https://raw.githubusercontent.com/rememberber/MooTool/master/update-manifest.json; const UPDATE_MANIFEST_URL: str https://github.com/rememberber/MooTool/releases/download/next-tauri-updater/latest.json; const MAX_REGISTRY_BYTES: usize 1024 * 1024; const MAX_RELEASE_NOTES_BYTES: usize 64 * 1024;根清单的解析与校验链fetch_product_feed()使用仅 HTTPS、最多 3 次重定向、15 秒超时的reqwest客户端拉取根清单并限制响应不超过 1 MiBread_limited。随后product_feed_from_registry()update.rs执行五层校验schema 校验schema_version ! 1报update_manifest_invalid产品存在性根清单缺少next-tauri节点报update_product_missing产品身份displayName必须等于MooTool Next Tauri否则报update_product_mismatch状态机planned返回ProductFeed::Inactive客户端直接判定“无更新”不发起任何网络请求不是active则报update_product_inactive端点白名单updaterManifestUrl必须精确等于编译期常量UPDATE_MANIFEST_URL否则报update_manifest_untrusted。其中第 5 步是“端点不可注入”的关键实现——即使渲染层被攻破或根清单被篡改只要updaterManifestUrl不是 Tauri 专属稳定通道更新就会被拒绝。单元测试对边界的验证同一文件末尾的测试模块直接印证了 ADR 的约束planned_product_does_not_contact_an_update_endpointplanned状态返回Inactive不访问更新端点active_product_accepts_only_the_tauri_channel_endpoint只接受 Tauri 通道 URL伪造的example.invalid/electron.json会被拒绝并返回update_manifest_untrustedproduct_identity_and_schema_are_enforced错误 schema 与错误产品名分别返回update_manifest_invalid、update_product_mismatchrelease_notes_are_truncated_on_a_unicode_boundary发行说明超 64 KiB 时在 Unicode 边界截断publication_date_uses_javascript_compatible_rfc3339发布日期以 RFC 3339 输出前端new Date()可直接解析。客户端完整更新流程检查 → 下载 → 取消 → 安装 → 重启Rust 命令层update.rs暴露四个 Tauri Commandcheck_for_product_updateL115-L172读取当前版本 → 获取产品 feed → 用updater_builder().endpoints(vec![endpoint]).timeout(30s)构建 updater 并check()。仅当raw_json.release_url以https://github.com/rememberber/MooTool/releases/tag/next-tauri-v开头时才透传给前端返回available / upToDate / inactive三种状态install_product_update通过update.download_and_install()流式回调进度事件Started / Progress / Finished / Installed并用tokio::select!支持取消cancel_install唤醒Notify使下载中止返回cancelled错误码cancel_product_update/relaunch_after_product_update分别取消进行中的下载、在重启前flush_window_state后调用app.restart()。前端调用层next-tauri/src/platform/api/updateApi.ts 将上述命令封装为ProductUpdateApicheck / install / cancel / relaunch并在非 Tauri 环境浏览器预览降级为browserProductUpdateApi明确提示“浏览器预览不能安装桌面更新”。事件契约定义在 next-tauri/src/platform/contracts/update.tsProductUpdateEvent涵盖started / progress / finished / cancelled / installed。对应的前端测试 updateApi.test.ts 断言只允许调用这 4 个产品专属命令。“设置 → 关于与更新”界面next-tauri/src/features/settings/UpdateCard.tsx 是用户可感知的完整闭环点击“检查更新”调用check_for_product_update展示最新版本、发布日期与发行说明有可用更新时展示“安装并重启”按钮下载期间实时渲染百分比进度条并允许取消。这印证了 README 中的描述设置中的更新入口“只读取根清单中的products.next-tauri再进入 Tauri 专属静态更新通道不会读取 Electron 更新节点”。发布流水线Draft Pre-release 先行人工发布后才提升稳定通道ADR-008 决策点 3 是发布流程的核心纪律next-tauri-v{version}首先生成 Draft Pre-release只有人工发布后next-tauri-promote-update.yml才验证所有公开资产 URL、提升latest.json随后只更新根清单的products.next-tauri。第一步.github/workflows/next-tauri-release.yml构建并生成 Draft触发条件为next-tauri-v*tag支持workflow_dispatch指定已有 tag 重跑preparejob 校验 tag 格式、package.json版本一致、release-notes/{version}.md存在并执行 check-release-boundaries.mjsbuildjob 在四个平台macOS Intel x64、macOS ARM64、Windows x64、Linux x64构建要求注入TAURI_SIGNING_PRIVATE_KEY/TAURI_SIGNING_PRIVATE_KEY_PASSWORD并在上传前分别完成 macOS codesign 验证 DMG 首次启动、Windows 静默安装/启动/卸载、Linux AppImage/deb 安装/启动/卸载的冒烟检查draft-releasejob 调用prepare-release-assets.mjs prepare统一命名安装包、计算 SHA-512、读取.sig签名文件生成latest.json与next-tauri-release.json然后用gh release create ${RELEASE_TAG} --draft --prerelease --latestfalse创建Draft Pre-release。关键点在于**--latestfalse**决策点 5无论是版本 Release 还是更新通道都显式不竞争仓库级Latest避免 Tauri 的发布状态干扰 Java/Electron 的用户下载页。check-release-boundaries.mjs会硬性断言两个工作流都包含--latestfalse以及tauri.conf.json中bundle.targets为all、createUpdaterArtifacts为true、plugins.updater.endpoints为空数组静态端点只能经products.next-tauri解析、Windows 安装模式为passive等边界。第二步.github/workflows/next-tauri-promote-update.yml人工发布后的提升该工作流由release.published事件触发且仅当 tag 以next-tauri-v开头时运行。它完整实现决策点 3、4断言被发布的是一个非 Draft 的 Pre-releasevalidate-promotion校验latest.json与next-tauri-release.json版本一致、四个platformskey 齐全、每个签名格式合法、每个 URL 都落在next-tauri-v{version}独立版本 Release 下、release_url一致对应 prepare-release-assets.mjs 的validatePromotion用curl --head逐一验证所有公开安装包与 updater 资产 URL 可达创建或更新next-tauri-updater通道 Release同样--latestfalse标题固定为MooTool Next Tauri Update Channel上传latest.json --clobber并回读已发布的latest.json逐字节比对确认稳定通道与本次提升版本完全一致执行update-registry将products.next-tauri.status置为active、写入updaterManifestUrl与releases提交并推送update-manifest.json。防回退与幂等决策点 4updateProductManifestprepare-release-assets.mjs在写入根清单前用完整的 SemVer 比较器含 pre-release 段数值比较检查if (latestExisting compareVersions(release.version, latestExisting.version) 0) { throw new Error(Refusing to downgrade the Tauri update channel from ${latestExisting.version} to ${release.version}) }即拒绝把稳定通道指向低于现有最高版本的 Release而相同版本写入会先过滤同版本旧条目再幂等重排因此重复提升不会报错。release:rehearse脚本见 package.json可在本地演练整条提升路径。独立发布、回滚与故障处理ADR-008 的结果部分承诺的三项收益在 next-tauri/doc/release-runbook.md 中有完整的操作化落地场景处置方式Draft 未发布修复源码后对同一 tag 重跑工作流只允许覆盖仍为 Draft 的 Release已发布但尚未提升修复公开资产或发布更高补丁版本不要手工激活根清单已提升不覆盖既有安装包、不把稳定通道降级到旧版本撤下有问题的 Release 并发布更高补丁版本修复updater 私钥丢失停止发布走经过评审的密钥轮换和人工安装方案不得无提示更换公钥本地发布门禁在next-tauri目录npm ci npm run check npm audit --audit-levelhigh其中npm run check串联发布边界、TypeScript、前端与 Rust 测试、生产 Web 构建、Rustfmt 与 Clippy并强制package.json、src-tauri/Cargo.toml、src-tauri/tauri.conf.json、release-notes/{version}.md四处版本一致。本地带签名构建示例TAURI_SIGNING_PRIVATE_KEY$HOME/.tauri/mootool-next-tauri.key \ TAURI_SIGNING_PRIVATE_KEY_PASSWORD$($HOME/.tauri/mootool-next-tauri.key.password) \ APPLE_SIGNING_IDENTITY- \ npx tauri build --bundles app,dmg仓库中的 src-tauri/tauri.conf.json 只保存 updater 公钥含minisign public key标识签名私钥通过 GitHub Secrets 注入且不得进入日志或 Artifact公钥轮换必须走密钥轮换方案而非直接替换。相关签名决策另见 next-tauri/doc/adr/009-code-signing.md。总结一份 ADR 如何约束整条发布链路ADR-008 的价值在于把“多产品线共存”的架构约束显式化并通过仓库代码、脚本与 CI 逐层落地根 update-manifest.json是仓库统一入口只承担产品发现products.next-tauri是 Tauri 客户端的唯一读取节点next-tauri-updater/latest.json是平台级静态稳定清单承载 Tauri Updater 所需的全部元数据与签名commands/update.rs用编译期常量 五层校验保证更新源固定、状态机清晰、端点不可注入prepare-release-assets.mjs与两个 CI 工作流把 Draft → 人工发布 → 提升 → 根清单激活的全过程脚本化并内置防回退与幂等结果Java、Electron、Tauri 三条产品线可独立发布、回滚与演进Draft 或资产不完整的 Release 不会被客户端发现相同或更低版本不会被错误提示为更新。如需完整阅读决策上下文与实操手册建议依次查看 ADR-008、next-tauri/doc/release-runbook.md 以及上文索引的源码文件。赞分享桌面应用开发工具【免费下载链接】MooToolHandy tool set for developers项目地址https://gitcode.com/gh_mirrors/mo/MooTool点击查看免费下载相关推荐MooTool Next Compose 更新通道 DIFF-027 深度解析独立产品节点、只读清单与「校验后打开安装包」实践MooTool Next Compose 更新通道 DIFF 027 深度解析独立产品节点、只读清单与「校验后打开安装包」实践 导读 本文以 next com桌面应用开发工具Release Please 实现设计解析从发布分支到 Monorepo 清单的自动化发布架构Release Please 实现设计解析从发布分支到 Monorepo 清单的自动化发布架构 本指南基于 release please 仓库的 设计文档 h开发工具CI/CDDevOpsMooTool Next Tauri基于 Tauri 2 Rust 构建独立桌面工具产品线的工程实践指南MooTool Next Tauri基于 Tauri 2 Rust 构建独立桌面工具产品线的工程实践指南 MooTool Next Tauri 是 Moo桌面应用开发工具上一篇Fathom Lite日志管理成本优化采样下一篇Ladda性能基准测试与其他加载按钮库的对比分析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考