跳转到内容

发布流程 ​

cnb-rs 的版本号真值源是根 Cargo.toml 中 [workspace.package] 的 version。一次正式发布分为五步:

  1. 在 main 上提交准备 commit(chore(release): prepare for vX.Y.Z)
  2. 在 CNB 上打 vX.Y.Z tag
  3. 手动 dispatch GitHub 仓库 wwvl/Mia 的 build-prerelease.yml 工作流
  4. 工作流构建全部产物并发布到 CNB Release(不发 GitHub Release)
  5. 收尾:核对产物、抽查分发渠道、确认 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.lock
  • scripts/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 ​

bash
git tag -a vX.Y.Z -m "Release vX.Y.Z"
git push origin vX.Y.Z

tag 推到 CNB 的 origin。tag 名必须以 v 开头,且去掉 v 后与 Cargo.toml 中的版本完全一致。

tag 推送后 CNB 会自动运行 release-tag-check;如果校验变红,不要 dispatch Mia,先修正版本或 tag。

3. dispatch 构建工作流 ​

bash
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,避免选错。

查看进度:

bash
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 包,需要 secrets WINDOWS_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 Release
  • publish-npm:发布 @cnb-rs/cli、@cnb-rs/mcp 及各平台子包;版本号含 - 时使用 dist-tag next,否则 latest
  • build-pypi-wheels / build-pypi-sdist / publish-pypi:构建并发布 cnb-rs、cnb-rs-mcp,版本号跟随 Cargo
  • update-setup-action:更新 CNB 上 setup-cnb-rs 的默认版本
  • update-package-repos:运行 scripts/release/update_package_repos.py 更新 Homebrew tap wwvo/cnb-rs/homebrew-cnb-rs 与 Scoop bucket wwvo/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. 收尾 ​

发布成功后按以下顺序收尾:

  1. 核对 CNB Release:

    bash
    cnb-rs release view vX.Y.Z --repo wwvo/cnb-rs/cnb-rs

    确认它不是预发布、已标为 latest、资产数量符合预期(上一次 rc.2 发布为 24 个资产,可作参照)。

  2. 抽查外部分发渠道:

    bash
    npm view @cnb-rs/cli dist-tags
    pip index versions cnb-rs
  3. 确认 issue 收到发布评论:publish job 会对上一个 tag 到本 tag 之间 commit footer 里 Closes / Fixes / Resolves #n 指向的 issue 逐个评论「已随 vX.Y.Z 发布:Release 链接」。抽查一两个 issue;若该步失败(continue-on-error,不影响发布),本地补跑:

    bash
    git fetch --tags
    RELEASE_TAG=vX.Y.Z REPO=wwvo/cnb-rs/cnb-rs bash scripts/release/comment-resolved-issues.sh   # 加 DRY_RUN=1 先预览

    脚本幂等:已有同版本评论的 issue 会跳过。

  4. 触发文档站部署:

    bash
    cnb-rs build start -b main -e api_trigger_deploy-docs

    main 分支 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:

    bash
    gh run rerun -R wwvl/Mia <run-id> --failed
  • build 阶段失败且需要改代码:删掉远端 tag 后重走第 1–3 步:

    bash
    git push origin :refs/tags/vX.Y.Z
  • npm / PyPI 已发布的版本号不可复用;如果包已推上去,只能 bump 版本号重新发布。

修改工作流 ​

工作流的真实源码在本仓库 .github/workflows/build-prerelease.yml。修改后需要同步到 wwvl/Mia 才能生效:

bash
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。

Released under the MIT License.