Rivet 项目版本发布全流程指南:从 cut-release 到 GitHub Actions 监控与失败恢复
【免费下载链接】actorsRivet Actors are the primitive for stateful workloads. Built for AI agents, collaborative apps, and durable execution.项目地址: https://gitcode.com/GitHub_Trending/riv/actors
本篇技术指南完整梳理 Rivet 开源仓库(Rivet Actors 及 rivetkit 多语言 SDK)的版本发布流程:如何确定 patch/minor/major/rc 版本、如何通过cut-release脚本自动完成版本号升级与发布触发、如何监控与修复 GitHub Actions 发布流水线,以及发布后如何执行端到端 sanity check。读完本文,你将掌握在 Rivet 仓库中独立完成一次稳定版或 RC 候选版发布、并在失败时安全恢复的完整实战能力。
一、发布流程总览
Rivet 的发布由三部分协作完成,其设计边界非常清晰:
- 本地编排脚本:
scripts/publish/src/local/cut-release.ts(通过pnpm --filter=publish release调用),负责人为本地执行的版本号解析、源码改写、提交推送与 workflow 触发; - CI 发布流水线:
.github/workflows/publish.yaml,负责跨平台原生产物构建、npm/crates.io 发布、R2 二进制上传与 Docker 镜像多架构 manifest; - 人工/Agent 监督:本文所依据的
.claude/commands/release.md定义了发布 Agent 的完整工作规范,包括信息收集、确认、监控、失败重试与发布后验证。
从源码结构看,该流程刻意把"决策"留在本地、把"执行"交给 CI:cut-release.ts 的文件头注释明确写到"Linear release cutter — called by humans, never by CI"(线性发布切割器——由人工调用,绝不由 CI 调用),而 ci/bin.ts 则声明每个 workflow 步骤只调用一个纯函数子命令,由 GitHub Actions workflow 充当编排者。
二、Step 1:收集发布信息
2.1 发布类型
开始发布前,需要先与用户确认发布类型,Rivet 遵循 semver 语义化版本规范:
| 类型 | 用途 | 示例 |
|---|---|---|
patch | Bug 修复 | 2.1.5 -> 2.1.6 |
minor | 新特性 | 2.1.5 -> 2.2.0 |
major | 破坏性变更 | 2.1.5 -> 3.0.0 |
rc | 发布候选(Release Candidate) | 2.1.6-rc.1 |
2.2 RC 版本的特殊信息收集
对于rc发布,还需额外确认两个信息:
- 基础版本(该 RC 针对哪个版本,如
2.1.6):若用户未指定,则基于当前版本 bump patch 一位得到; - RC 编号(如 1、2、3):若用户未指定,通过现有 git tag 自动推断下一个编号:
git tag -l "v<base_version>-rc.*" | sort -V若该基础版本下不存在任何历史 RC tag,则使用rc.1;否则在最高编号基础上递增。
最终的 RC 版本字符串为<base_version>-rc.<number>,例如2.1.6-rc.1。如果用户在最初的请求中已经提供了上述全部信息,则跳过提问直接进入下一步。
2.3 源码佐证:版本解析逻辑
发布脚本的版本解析实现在 scripts/publish/src/lib/version.ts 的resolveVersion函数中:优先使用--version显式指定的版本(需通过semver.valid校验);否则基于 git 最新 tag 通过semver.inc计算major/minor/patch的下一版本。值得注意的是,当仓库中没有任何版本 tag 时,脚本会拒绝通过 bump 方式推算版本,强制要求使用--version显式指定——这避免了"首个版本无参照"的歧义。
同时,shouldTagAsLatest(version.ts)定义了latest标记的判定规则:只有当版本无 prerelease 标识且高于现有全部稳定版 git tag 时,才会被标记为latest。这从源码层面印证了原文档中"RC 版本永远不标记为 latest"的规则。
三、Step 2:确认发布细节
在任何操作之前,必须先向用户展示并请求明确确认,内容包括:
- 当前版本:通过
git tag -l "v*" | sort -V | tail -1获取最新 git tag - 新版本
- 当前分支
- 是否标记为
latest(RC 版本永远不会标记为 latest)
未获得用户确认前,严禁继续执行。
这一确认环节在脚本中同样存在:cut-release.ts会先打印完整的 "Release plan"(版本、latest 标记、分支、上一版本、最近 10 个版本列表),然后通过交互式提示Proceed with release? (yes/no):等待确认(cut-release.ts),--yes参数可跳过该提示。此外,脚本还会调用validateClean()检查 git 工作区是否干净,存在未提交变更时直接报错中止(scripts/publish/src/lib/git.ts)。
四、Step 3:运行发布脚本
4.1 命令格式
对于major / minor / patch稳定版发布:
pnpm --filter=publish release --<type> --yes对于rc发布(使用显式版本):
pnpm --filter=publish release --version <version> --no-latest --yes其中<type>为major、minor或patch,<version>为完整版本字符串(如2.1.6-rc.1)。
该命令实际映射到 scripts/publish/package.json 中的"release": "tsx src/local/cut-release.ts",即通过tsx直接执行本地发布脚本。
4.2 脚本的十个执行步骤
cut-release.ts是一个线性脚本(没有 phase 划分,也没有--only-steps选项),按顺序执行以下步骤:
- 解析目标版本:通过
--version显式指定,或--major/--minor/--patch自动推算; - 自动检测
latest标记:优先级为 显式参数 > 自动推断(shouldTagAsLatest)> 默认 false; - 校验 git 工作区干净;
- 打印发布计划并要求确认(
--yes跳过提示); - 通过
updateSourceFiles更新非 package.json 源文件:包括Cargo.toml的[workspace.package]版本,以及examples/**/package.json中对rivetkit/@rivetkit/*的依赖规格(version.ts); - 通过
bumpPackageJsons重写所有可发布包的package.json版本:以versionOnly: true模式运行,仅改写version字段,保留workspace:*依赖规格以维持 lockfile 一致性(version.ts); - 运行
./scripts/fern/gen.sh重新生成 Fern 相关产物; - 本地构建 + 类型检查(fail-fast):执行
pnpm build与cargo check,可用--skip-checks跳过; - 提交并推送:提交信息为
chore(release): update version to X.Y.Z,在main分支上直接git push,非 main 分支优先使用 Graphite 的gt submit(失败则回退到git push -u origin <branch>); - 触发
.github/workflows/publish.yaml:通过gh workflow run携带version与latest参数触发(cut-release.ts)。
4.3 两个重要的源码细节
Rust 依赖的精确版本钉扎:在updateSourceFiles之外,脚本还会调用bumpCargoVersions(version.ts),将Cargo.toml中[workspace.dependencies.<internal-crate>]的version = "=X.Y.Z"精确钉扎同步到新版本。代码注释解释得很清楚:如果只更新[workspace.package]版本而不同步内部 crate 的精确钉扎,Rust/wasm 构建会因解析不到上一版本的内部依赖而失败。
dry-run 语义:--dry-run模式仍会改写源文件(便于检查 diff),但跳过 commit/push/workflow 触发。
4.4 失败后的重跑策略
如果某一步失败:修复底层问题后重新执行命令即可。脚本对"已提升过的版本"是幂等的——重复执行不会二次累加版本。若个别步骤已完成,也可以在本地将已完成的步骤注释掉(脚本注释明确建议了这种调试方式)。
五、Step 4:监控 GitHub Actions Workflow
5.1 查找 workflow run
workflow 触发后,先等待约 5 秒让其完成注册,然后开始轮询。使用以下命令查找最近的运行:
gh run list --workflow=publish.yaml --limit=1 --json databaseId,status,conclusion,createdAt,url务必验证该 run 是在最近 2 分钟内创建的,以确认监控的是正确的运行(避免误监控到历史或预览发布)。将返回的databaseId保存为 run ID。
5.2 轮询直至完成
每 15 秒轮询一次:
gh run view <run-id> --json status,conclusion建议每隔约 60 秒或状态变化时向用户汇报进度。状态含义:
queued/in_progress/waiting— 仍在运行,继续轮询;completed— 已结束,检查conclusion。
completed后的三种结论处理方式:
success— 发布成功,进入 Step 6;failure— 进入 Step 5 处理失败;cancelled— 告知用户并停止。
5.3 流水线的真实规模(源码佐证)
从 .github/workflows/publish.yaml 可以看出这条流水线的真实复杂度,有助于理解为什么需要耐心轮询:
- build job:一个 13 行的矩阵(含 rivetkit-napi 的 6 个平台、engine 的 5 个平台、container-runner 的 2 个平台、cli 的 5 个平台),全部通过 depot 远程构建,Windows 目标因 MinGW ld 较慢(约 13 分钟)被标记为
release_only,仅在 release 触发时构建; - build-wasm job:构建
@rivetkit/rivetkit-wasm便携 wasm 包; - docker-images job:为
rivetdev/engine:full与rivetdev/engine:slim构建 arm64/amd64 双架构镜像; - publish job:汇聚所有产物,依次完成 npm 发布(并行度 16、重试 3 次)、R2 上传、SHA256 校验清单生成、Inspector UI 打包进 crate、Rust crate 发布、多架构 manifest 合并,最后执行 release-only 尾部(上传安装脚本、重打 Docker tag、创建 git tag 与 GitHub release)。
发布成功后的产物交付面覆盖了:npm(rivetkit 全家桶 + 平台原生绑定)、crates.io(RUST_CRATES列表中的 18 个 crate,发布顺序严格依赖依赖关系,见 ci/bin.ts)、R2 对象存储(engine 与 container-runner 二进制)、Docker Hub 多架构镜像。
六、Step 5:处理 Workflow 失败
6.1 获取失败日志
gh run view <run-id> --log-failed6.2 错误分类与应对策略
仔细阅读失败日志,常见失败类别及处理方式:
| 失败类别 | 处理方式 |
|---|---|
| 构建失败(cargo build、TypeScript 编译) | 修复代码 |
| 格式化问题(cargo fmt) | 运行格式化修复 |
| 测试失败 | 修复失败的测试 |
| 发布失败(crates.io、npm) | 可能是瞬时错误,检查重试是否有帮助 |
| Docker 构建失败 | 检查 Dockerfile 或构建脚本问题 |
| 基础设施/瞬时失败(网络超时、限流) | 不做代码改动,直接重新触发 |
6.3 修复并重新推送
若需要代码修复:
git add -A git commit --amend --no-edit git push --force-with-lease安全提示:必须使用
--force-with-lease(而非--force)。amend 提交而非新建提交,使发布保持为单一版本升级提交。
然后重新触发 workflow:
gh workflow run .github/workflows/publish.yaml \ -f version=<version> \ -f latest=<true|false> \ --ref <branch>其中<branch>为当前分支(通常是main)。latest参数:RC 发布设为false;比当前 latest tag 更新的稳定版设为true。重新触发后返回 Step 4 监控新 run。
若为瞬时失败(无需代码修复),跳过修复步骤直接重新触发即可。
6.4 重试上限
若 workflow 累计失败 5 次,停止重试,向用户汇报全部错误,并询问是继续重试还是中止发布。不得无限重试。
七、Step 6:报告成功
workflow 成功完成后:
- 输出 GitHub Actions run 的 URL;
- 输出新的版本号。
八、Step 7:Sanity Check 端到端验证
发布成功不等于万事大吉。Rivet 要求对刚发布的版本执行 sanity check,验证包端到端真实可用。
8.1 确定 npm tag
根据版本类型选择正确的 npm tag:
- RC 发布:
rc - 标记为 latest 的稳定版:
latest - 未标记为 latest 的稳定版:使用精确版本字符串(如
2.3.0)
然后以该 tag 调用/sanity-checkskill。例如:对2.3.0-rc.1执行rivetkit@rc的 sanity check;对稳定版2.3.0执行rivetkit@latest的 sanity check。
8.2 sanity check 的实际内容
依据仓库中的 .claude/skills/sanity-check/SKILL.md,该检查是一个真实的端到端冒烟测试:
- 在临时目录中从公共 npm registry安装
rivetkit、@rivetkit/react及平台相关的@rivetkit/rivetkit-napi-*原生绑定(绝不使用本地 workspace 链接); - 启动 hello-world counter actor 服务器(端口 6420),等待
/health就绪(30 秒超时); - HTTP 路径:调用
counter.increment(5)、counter.increment(3)、counter.getCount()并断言返回值(5、8、8); - WebSocket 路径:通过
.connect()建立连接,订阅newCount事件,调用increment(10),同时断言 action 返回值与广播事件值均为 10; - 报告
rivetkit与@rivetkit/rivetkit-napi的实际解析版本。
测试可在宿主机(需 Node.js 22+)或node:22Docker 容器中运行。失败时自动输出服务器日志的最后 2KB 辅助诊断。
若 sanity check 失败:向用户报告失败及错误详情。注意此时发布已经完成,因此 sanity check 失败意味着已发布的产物本身存在问题——需要定位是原生二进制缺失、Node 版本不匹配还是其他发布产物缺陷。
九、关键约定与注意事项
发布 Agent 必须遵守以下硬性约定:
- 产品名称为 "Rivet",域名永远是
rivet.dev,绝不是rivet.gg; - 提交信息中不得包含 co-author;
- 使用 Conventional Commits 风格,如
chore(release): update version to X.Y.Z; - 提交信息保持单行;
- 始终在当前分支工作,发布通常从
main切出; - 未经用户明确确认,绝不向
main推送; - 不要自动运行
cargo fmt或./scripts/cargo/fix.sh。
十、总结:一次成功发布的时间线
综合上述全部环节,一次完整的 Rivet 稳定版发布呈现如下时间线:
- 确认:确定版本类型与目标版本,向用户展示并取得确认;
- 本地执行:运行
pnpm --filter=publish release --<type> --yes,脚本依次完成版本解析、源文件改写、fern gen、本地检查、提交推送、触发 workflow; - CI 构建:depot 远程构建 13+ 个平台产物 + wasm 包 + Docker 双架构镜像;
- CI 发布:npm(
--parallel 16 --retries 3)与 crates.io 按依赖顺序发布,R2 上传二进制与校验清单,Docker manifest 合并; - 发布尾部:上传安装脚本、Docker 重打版本 tag、创建 git tag
vX.Y.Z与 GitHub release(含 prerelease 标记); - 验证:按 npm tag 对
rivetkit执行 sanity check,验证 HTTP actions 与 WebSocket 事件端到端可用。
整条链路体现了"本地决策 + CI 执行 + 人工监督"的工程实践:所有破坏性操作(推送、发布、打 tag)都集中在流水线尾部,且每一步都有明确的确认点、幂等性与重试上限,即使发布 Agent 中途接管,也能清晰判断当前状态并安全恢复。
【免费下载链接】actorsRivet Actors are the primitive for stateful workloads. Built for AI agents, collaborative apps, and durable execution.项目地址: https://gitcode.com/GitHub_Trending/riv/actors
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考