release-plz 驱动的 Rust 工作区发布流水线:OpenLogi 版本管理全流程拆解
2026/8/30 10:05:03 网站建设 项目流程

release-plz 驱动的 Rust 工作区发布流水线:OpenLogi 版本管理全流程拆解

【免费下载链接】OpenLogi⚡️A native, local-first alternative to Logitech Options+, written in Rust 🦀 — remap buttons, DPI, and SmartShift over HID++. No account, no telemetry.项目地址: https://gitcode.com/GitHub_Trending/op/OpenLogi

OpenLogi 是一个用 Rust 编写的本地优先(local-first)罗技外设管理工具,作为 Logitech Options+ 的开源替代:重映射按键、调节 DPI 与 SmartShift,无需账号、无遥测。这篇文章拆解它的 Rust 工作区发布流水线——如何用 release-plz 统一管理 19 个 crate 的版本号、自动生成发布 PR、用 git-cliff 生成变更日志,再到打 tag 触发签名打包与多渠道发布。

📦 先看全景:19 个 crate,一个版本号

打开根目录的 Cargo.toml,你会发现一个关键设计:

  • 工作区包含 19 个成员 crate(HID 协议、设备驱动、GUI、Agent、CLI 等),见 Cargo.toml
  • 所有 crate 共享一个版本号:[workspace.package]下声明version = "0.8.1",各 crate 通过version.workspace = true继承

这意味着整个项目"同进同退"——发版时只改一处,所有 crate 一起升版本、一起打一个v{version}tag。对新手来说,这是多 crate 项目最省心的一种版本模型。

整条流水线可以用一张图概括:

push master ──▶ release-plz 自动开 PR(升版本 + 预览) │ 合并 "chore: release" PR │ release job:xtask 校验 ──▶ 打 v0.9.0 tag │ release.yml:编译 ──▶ 签名公证 ──▶ 校验和 ──▶ 发布 │ GitHub Release + 更新通道 latest.json + homebrew-tap

⚙️ 配置核心:release-plz.toml 如何把版本"锁"在一起

一切从根目录的 release-plz.toml 开始。核心配置只有三点,却回答了多 crate 发布最常见的三个难题:

1️⃣version_group:强制版本同步

在 release-plz.toml 中,11 个要发布到 crates.io 的 crate(openlogiopenlogi-coreopenlogi-hidppopenlogi-cli等)都归入version_group = "openlogi"。这样它们永远联动升级,避免"A crate 依赖的 B crate 还没发布"这种地狱场景。

2️⃣release = false:应用 crate 不参与发版

release-plz.toml 里,openlogi-desktop(GUI)、openlogi-agent(托盘后台)、openlogi-overlay等 6 个"应用型"crate 被标记为不发布——OpenLogi 以安装程序形态交付,不是给人cargo install的 API 库。

3️⃣ 职责切分:谁管 tag、谁管 Release、谁管 CHANGELOG

这是最容易踩坑的地方,配置文件头部的注释写得很直白:

职责归属原因
升版本号release-plz它的看家本领
v*tagrelease-plz(仅openlogi根 crate)一个 tag 代表整个工作区
GitHub Releaserelease.yml的 softprops若 release-plz 先建 Release,后续上传资产时会遇到 "release immutable" 错误
CHANGELOG.mdgit-cliffrelease-plz 按 crate 路径过滤,看不到不发布的应用 crate,无法覆盖全仓库

另外几个细节值得新手注意:

  • semver_check = false:release-plz.toml 里禁用了 semver 破坏性检查——应用项目不需要在发布 PR 里看"API breaking"噪音
  • release_always = false:release-plz.toml 确保只有发布 PR 合并时才发版,master 上后续的提交绝不会误切 tag

🚀 第一棒:push master 自动打开发布 PR

工作流 .github/workflows/release-plz.yml 监听 master 的每次 push,运行release-plz release-pr

  1. release-plz/前缀的分支打开一个 PR,内容是各 crate 的版本号 bump + 按 crate 的变更预览
  2. 通过 1Password 中的本地 Action 铸造 GitHub App token(.github/workflows/release-plz.yml),因为 GITHUB_TOKEN 推送无法触发下游工作流

亮点动作:PR 打开后,流水线会用git cliff为这个即将发布的版本写入整库 CHANGELOG,然后直接把发布 PR 的正文替换成这份 changelog(见 release-plz.yml)。也就是说,评审发布 PR = 阅读版本说明,合并 PR = 确认发版,流程非常直觉。

📝 CHANGELOG.md 为什么交给 git-cliff

.config/cliff.toml 定义了 changelog 生成规则:

  • 只认 Conventional Commits:feat→ Added、fix→ Fixed、perf→ Changed(cliff.toml)
  • 覆盖全仓库,不按 crate 路径过滤——GUI 的改动同样进 changelog
  • #123自动转换为 PR 链接

xtask 中对应的命令是 xtask/src/commands/release/changelog.rs:它以最近一个vX.Y.Ztag 为下界运行git cliff,且每次重跑都会先删除旧的同版本段落,保证发布 PR 反复更新时结果幂等。

🛡️ 第二棒:合并前的三道 xtask 保险

发布 PR 合并后,触发条件苛刻的releasejob 才会执行(仅当提交信息以chore: release开头,或手动 dispatch,见 release-plz.yml)。它先运行两个 xtask 子命令,全部定义在 xtask/src/commands/release.rs:

checkout-version-bump:把发布钉死在正确的 commit 上

checkout_version_bump.rs 会先按提交信息chore: release v0.9.0查找升版提交,找不到再回退到"首次把 Cargo.toml 改成该版本"的提交,然后强制检出到它。目的:绝不让比升版提交更新的 master 尖端被发版——如果 crates.io 发布失败,你可以修好凭据后在同一 SHA 上重试,而不是切出一个错误的版本。若该版本已打过 tag,直接输出skip=true跳过。

check-publish:发布闭包校验

check_publish.rs 解析cargo metadata,确保:

  • 每个可发布 crate 对内部 path 依赖都声明了 registry 版本号(req == "*"直接报错)
  • 可发布 crate 不能依赖未发布的内部 crate

这正是 release-plz.toml 中openlogi-camera必须留在版本组里的原因:crates.io 上的包无法依赖"未发布的路径依赖"。

🏷️ 第三棒:tag 触发 release.yml,签名、校验、发布一条龙

release-plz 打完v*tag 后,接力棒交给 .github/workflows/release.yml,它由四个 job 组成:

build:复用同一构建矩阵为 macOS / Windows / Linux 编译安装程序,sign: true启用签名与公证(macOS DMG 是发布门禁)。

release-notes:用 Node 脚本生成 GitHub Release 说明(generate.ts),仅 tag 运行时执行。

publish:真正的发布中枢,注意它的门禁条件(release.yml)——只要求macOS 腿成功,Windows/Linux 腿尽力而为。这样实验性的 arm64 Windows 构建失败不会拖垮 macOS 发布。具体步骤:

  1. 生成SHA256SUMS校验和(DMG 缺失则大声失败)
  2. 用 minisign 对所有产物生成.minisig分离签名并回验
  3. 运行cargo run -p xtask -- release latest-json生成静态更新清单 latest.json(供 gpui-updater 消费)
  4. 产物上传 R2(版本目录 +channels/stable/latest.json更新通道)
  5. 最后一步才用 softprops 创建 draft → 上传全部资产 → 转正式,规避 "immutable release" 陷阱(release.yml)

homebrew-tap:向 Homebrew tap 仓库发送update-openlogi事件,让brew install openlogi自动跟进新版本。

✅ 清单:这套流水线值得抄的设计

🎯 给维护多 crate Rust 项目的朋友,OpenLogi 的做法浓缩为 6 条:

  1. 单版本号 +version_group:工作区同进同退,一个 tag 代表一次发版
  2. 发布 PR 即 changelog:git-cliff 全库视角,合并 PR = 审批发版
  3. 职责单一化:release-plz 只管升版本和打 tag,Release 生命周期交给专门工作流
  4. 发布钉在升版 commit:失败可在同一 SHA 安全重试
  5. 发布闭包前置校验:在打 tag 前发现"依赖了未发布 crate"的硬失败
  6. 门禁分级:核心平台是硬门禁,实验性平台降级为尽力而为,绝不让旁路拖垮主发布

完整细节可继续阅读仓库文档 docs/DEVELOPMENT.md 与 xtask/README.md,或直接在 release-plz.toml 中查看每行配置的注释——那是本文信息量最密集的一处"活文档"。

【免费下载链接】OpenLogi⚡️A native, local-first alternative to Logitech Options+, written in Rust 🦀 — remap buttons, DPI, and SmartShift over HID++. No account, no telemetry.项目地址: https://gitcode.com/GitHub_Trending/op/OpenLogi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询