发布流程
cnb-rs 的版本号真值源是根 Cargo.toml 中 [workspace.package] 的 version。一次正式发布分为五步:
- 在
main上提交准备 commit(chore(release): prepare for vX.Y.Z) - 在 CNB 上打
vX.Y.Ztag - 手动 dispatch GitHub 仓库
wwvl/Mia的build-prerelease.yml工作流 - 工作流构建全部产物并发布到 CNB Release(不发 GitHub Release)
- 收尾:核对产物、抽查分发渠道、确认 issue 已收到发布评论、触发文档站部署
关于仓库布局的说明:
wwvl/Mia是 GitHub 上的运行仓库,只放build-prerelease.yml这一份工作流和 README;该工作流是本仓库.github/workflows/build-prerelease.yml的逐字节运行副本,修改方式见下文「修改工作流」
1. 准备 commit
下一个版本号以 git cliff --bumped-version 为准:按 Conventional Commits 推导,feat → minor,fix 等 → patch,! / BREAKING CHANGE → major。
直接在 main 上提交 chore(release): prepare for vX.Y.Z,包含以下改动:
Cargo.toml:把 workspace version 改为X.Y.Z,然后运行cargo update --workspace刷新Cargo.lockscripts/install.sh:更新default_version="vX.Y.Z"scripts/install.ps1:更新$DefaultVersion = "vX.Y.Z"CHANGELOG.md:运行git cliff --tag vX.Y.Z -o CHANGELOG.md重新生成。cliff.toml已配置ignore_tags忽略 alpha / beta / rc tag,预发布之间的提交会并入下一个正式版章节;chore(release): prepare for提交本身会被 cliff 跳过README.md:按版本性质调整与预发布相关的说明(如 npm@next、pip--pre)
推送后等待 CNB CI(fmt / check / clippy / test / regen-check / cargo-deny)全绿,再进行下一步。覆盖率由每日定时或手动触发的 coverage 任务生成。
2. 打 tag
git tag -a vX.Y.Z -m "Release vX.Y.Z"
git push origin vX.Y.Ztag 推到 CNB 的 origin。tag 名必须以 v 开头,且去掉 v 后与 Cargo.toml 中的版本完全一致。
tag 推送后 CNB 会自动运行 release-tag-check;如果校验变红,不要 dispatch Mia,先修正版本或 tag。
3. dispatch 构建工作流
gh workflow run -R wwvl/Mia build-prerelease.yml -f version=vX.Y.Z前置条件:已 gh auth login,且 token 带有 workflow scope。
version 输入留空时,工作流会用 git -c versionsort.suffix=- ls-remote --sort=-version:refname 从 CNB 选出最新 tag;正式版发布建议显式传入 version,避免选错。
查看进度:
gh run list -R wwvl/Mia --limit 3
gh run watch -R wwvl/Mia <run-id>4. 工作流各 job
build-prerelease.yml 按依赖顺序执行以下 job:
resolve:解析本次发布的版本号build:构建 10 个 target——linux gnu / musl(x86_64、aarch64)、macOS(x86_64、aarch64)、windows msvc(x86_64、aarch64)、windows gnu 等,并附带.deb/.rpm/.msi打包build-msix+smoke-test-msix:构建并冒烟测试签名的 MSIX 包,需要 secretsWINDOWS_MSIX_PFX_BASE64/WINDOWS_MSIX_PFX_PASSWORD,缺失则跳过publish:从 CNB clone 对应 tag,下载构建产物并生成sha256sum.txt,用git cliff --latest生成发布说明,然后cnb-rs release create创建 Release(版本号含-时加-p标为预发布,否则加--make-latest),cnb-rs release upload --clobber上传全部资产,最后运行scripts/release/comment-resolved-issues.sh给本次解决的 issue 留评论(见下文)。产物发布在 CNB Release 上,不创建 GitHub Releasepublish-npm:发布@cnb-rs/cli、@cnb-rs/mcp及各平台子包;版本号含-时使用 dist-tagnext,否则latestbuild-pypi-wheels/build-pypi-sdist/publish-pypi:构建并发布cnb-rs、cnb-rs-mcp,版本号跟随 Cargoupdate-setup-action:更新 CNB 上setup-cnb-rs的默认版本update-package-repos:运行scripts/release/update_package_repos.py更新 Homebrew tapwwvo/cnb-rs/homebrew-cnb-rs与 Scoop bucketwwvo/cnb-rs/scoop-cnb-rs;脚本只接受正式版 tag,预发布会跳过trigger-plugin-image:通过cnb-rs build start -e api_trigger_build-plugin-image重建 Docker 插件镜像update-readme:同步 README 里的 help 输出
Secrets 配置
GitHub 仓库 wwvl/Mia 需要以下 secrets:
CNB_TOKEN:clone 仓库、创建 release、推送 Homebrew / Scoop tap、触发 CNB 构建NPM_TOKEN:发布 npm 包WINDOWS_MSIX_PFX_BASE64/WINDOWS_MSIX_PFX_PASSWORD:MSIX 签名证书及其密码,缺失时build-msix/smoke-test-msix跳过
PyPI 发布走 GitHub environment release 的 trusted publishing,不需要 token。
5. 收尾
发布成功后按以下顺序收尾:
核对 CNB Release:
bashcnb-rs release view vX.Y.Z --repo wwvo/cnb-rs/cnb-rs确认它不是预发布、已标为 latest、资产数量符合预期(上一次 rc.2 发布为 24 个资产,可作参照)。
抽查外部分发渠道:
bashnpm view @cnb-rs/cli dist-tags pip index versions cnb-rs确认 issue 收到发布评论:
publishjob 会对上一个 tag 到本 tag 之间 commit footer 里Closes/Fixes/Resolves #n指向的 issue 逐个评论「已随 vX.Y.Z 发布:Release 链接」。抽查一两个 issue;若该步失败(continue-on-error,不影响发布),本地补跑:bashgit fetch --tags RELEASE_TAG=vX.Y.Z REPO=wwvo/cnb-rs/cnb-rs bash scripts/release/comment-resolved-issues.sh # 加 DRY_RUN=1 先预览脚本幂等:已有同版本评论的 issue 会跳过。
触发文档站部署:
bashcnb-rs build start -b main -e api_trigger_deploy-docsmain分支 push 不会自动发布文档站(Cloudflare Pages 有构建配额),需要手动触发。
Issue 与版本的关联
不再使用按版本号命名的标签(target:vX.Y.Z / released:vX.Y.Z):CNB 没有 Milestone,这类标签随版本线性增长且无法归档。版本归属靠三处信息,全部自动产生:
- issue 评论:发版时
comment-resolved-issues.sh写入「已随 vX.Y.Z 发布」(参考 semantic-release 的 successComment),前提是修复 commit 的 footer 写了Closes #n(或Fixes/Resolves;Refs #n只表示关联,不会触发评论) - CHANGELOG / Release notes:
cliff.toml会把上述 footer 渲染成条目末尾的 issue 链接,每个版本章节即「本版本处理了哪些 issue」 - 按关闭时间查询:
cnb-rs issue list -s closed --closed-before <本版发布日> --closed-after <上一版发布日> -L 200 --json;JSON 中用state_reason字段区分completed/not_planned。--closed-after当前因上游参数失效而由客户端分页过滤
「计划进入哪个版本」不再单独标记:合入 main 的改动进入下一个版本,优先级用 issue 的原生优先级字段(P0–P3)。历史上已打的 released:v0.x 标签保留作为老 issue 的归属记录,不再新增。
失败处理
publish及之后的 job 失败(如包仓库同步、插件镜像、某个 npm 平台包):修复原因后重跑失败 job,不要重打 tag:bashgh run rerun -R wwvl/Mia <run-id> --failedbuild阶段失败且需要改代码:删掉远端 tag 后重走第 1–3 步:bashgit push origin :refs/tags/vX.Y.Znpm / PyPI 已发布的版本号不可复用;如果包已推上去,只能 bump 版本号重新发布。
修改工作流
工作流的真实源码在本仓库 .github/workflows/build-prerelease.yml。修改后需要同步到 wwvl/Mia 才能生效:
gh api -X PUT repos/wwvl/Mia/contents/.github/workflows/build-prerelease.yml调用时需带上 Mia 侧现有文件的 sha;同步后两边应保持逐字节一致。
预发布 tag
nightly-* / alpha-* / preview-* 这类预发布 tag 仍由 CNB 上的 .cnb/workflows/release-temp.yml 处理,只产出 linux-musl 二进制到预发布 Release,与上述正式流程无关。
已停用的 CNB 原生流程
旧的 CNB 原生五阶段流程已于 2026-09-17 删除(#322),仅保留 release-temp.yml 处理 nightly / alpha / preview tag。