news 2026/9/17 3:13:36

Rivet 项目版本发布全流程指南:从 cut-release 到 GitHub Actions 监控与失败恢复

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Rivet 项目版本发布全流程指南:从 cut-release 到 GitHub Actions 监控与失败恢复

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 语义化版本规范:

类型用途示例
patchBug 修复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发布,还需额外确认两个信息:

  1. 基础版本(该 RC 针对哪个版本,如2.1.6):若用户未指定,则基于当前版本 bump patch 一位得到;
  2. 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>majorminorpatch<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选项),按顺序执行以下步骤:

  1. 解析目标版本:通过--version显式指定,或--major/--minor/--patch自动推算;
  2. 自动检测latest标记:优先级为 显式参数 > 自动推断(shouldTagAsLatest)> 默认 false;
  3. 校验 git 工作区干净
  4. 打印发布计划并要求确认--yes跳过提示);
  5. 通过updateSourceFiles更新非 package.json 源文件:包括Cargo.toml[workspace.package]版本,以及examples/**/package.json中对rivetkit/@rivetkit/*的依赖规格(version.ts);
  6. 通过bumpPackageJsons重写所有可发布包的package.json版本:以versionOnly: true模式运行,仅改写version字段,保留workspace:*依赖规格以维持 lockfile 一致性(version.ts);
  7. 运行./scripts/fern/gen.sh重新生成 Fern 相关产物;
  8. 本地构建 + 类型检查(fail-fast):执行pnpm buildcargo check,可用--skip-checks跳过;
  9. 提交并推送:提交信息为chore(release): update version to X.Y.Z,在main分支上直接git push,非 main 分支优先使用 Graphite 的gt submit(失败则回退到git push -u origin <branch>);
  10. 触发.github/workflows/publish.yaml:通过gh workflow run携带versionlatest参数触发(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:fullrivetdev/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-failed

6.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 成功完成后:

  1. 输出 GitHub Actions run 的 URL;
  2. 输出新的版本号。

八、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,该检查是一个真实的端到端冒烟测试:

  1. 在临时目录中从公共 npm registry安装rivetkit@rivetkit/react及平台相关的@rivetkit/rivetkit-napi-*原生绑定(绝不使用本地 workspace 链接);
  2. 启动 hello-world counter actor 服务器(端口 6420),等待/health就绪(30 秒超时);
  3. HTTP 路径:调用counter.increment(5)counter.increment(3)counter.getCount()并断言返回值(5、8、8);
  4. WebSocket 路径:通过.connect()建立连接,订阅newCount事件,调用increment(10),同时断言 action 返回值与广播事件值均为 10;
  5. 报告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 稳定版发布呈现如下时间线:

  1. 确认:确定版本类型与目标版本,向用户展示并取得确认;
  2. 本地执行:运行pnpm --filter=publish release --<type> --yes,脚本依次完成版本解析、源文件改写、fern gen、本地检查、提交推送、触发 workflow;
  3. CI 构建:depot 远程构建 13+ 个平台产物 + wasm 包 + Docker 双架构镜像;
  4. CI 发布:npm(--parallel 16 --retries 3)与 crates.io 按依赖顺序发布,R2 上传二进制与校验清单,Docker manifest 合并;
  5. 发布尾部:上传安装脚本、Docker 重打版本 tag、创建 git tagvX.Y.Z与 GitHub release(含 prerelease 标记);
  6. 验证:按 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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 3:12:24

S7 Online通信配置指南:打通fe.screen-sim与西门子PLC虚拟调试链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 3:11:52

全球首位HCCDE-GaussDB认证得主:数据库老兵的实战与职业进阶之路

提到HCCDE-GaussDB&#xff0c;可能很多人第一反应是&#xff1a;华为又出新认证了&#xff1f;但当我第一次看到“全球首位”这四个字的时候&#xff0c;还是愣了几秒。HCCDE这个级别在华为认证体系里的分量&#xff0c;懂行的人不用多解释——它不是刷题库、背考点就能糊弄过…

作者头像 李华
网站建设 2026/9/17 3:10:31

嵌入式开发强度刻度线:C语言、单片机与RTOS的硬核标尺

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 3:07:21

MATLAB手写CNN底层:从卷积到反向传播的全流程解析

简介&#xff1a;这是一份面向MATLAB初学者的卷积神经网络模拟程序包&#xff0c;配套完整的网络训练与测试流程&#xff0c;帮助理解卷积层、池化层、全连接层以及反向传播等核心机制。压缩包内共30个M文件&#xff0c;大小仅16KB&#xff0c;涵盖网络初始化、前向传播、反向传…

作者头像 李华