news 2026/9/17 6:55:13

Rivet Actors 发布机制全解:前端 prod 分支晋升、just release 与“本地切版 + CI 发布”两级流水线

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Rivet Actors 发布机制全解:前端 prod 分支晋升、just release 与“本地切版 + CI 发布”两级流水线

Rivet Actors 发布机制全解:前端 prod 分支晋升、just release 与“本地切版 + CI 发布”两级流水线

【免费下载链接】actorsRivet Actors are the primitive for stateful workloads. Built for AI agents, collaborative apps, and durable execution.项目地址: https://gitcode.com/GitHub_Trending/riv/actors

本文基于仓库内部发布文档 RELEASING.md,完整拆解 Rivet Actors 的三类发布路径:前端服务经prod分支强推晋升到生产、官网直接从main部署、以及引擎(Engine)与 SDK 通过just release命令触发的完整版本切分流程。读完本文,你能掌握just release各参数的实际行为、本地切版脚本cut-release.ts的十步编排逻辑,以及与之配套的 CI 发布工作流 publish.yaml 中 npm 包、crates.io、R2 制品与 Docker 镜像的产出关系。

发布对象总览:三条互不相同的路径

Rivet Actors 仓库的“发布”并非单一流程,而是按产物拆分为三条路径,各自部署源与触发方式都不同:

发布对象部署源触发方式
前端服务(dashboard.rivet.devinspect.rivet.dev等,不含官网)prod分支本地手动执行promote-prod.sh强推
官网(website)main分支main分支自动部署
引擎 + SDK(npm 包、crates.io 包、引擎二进制、Docker 镜像)Git tag + GitHub Actions本地just release切版后触发 workflow

其中最容易混淆的一点在原文档中被明确区分:官网走main而不是prod,也就是说promote-prod.sh推上去的提交只会影响前端服务(Dashboard / Inspector 等),不会影响官网页面。

前端生产发布:promote-prod.sh 与 prod 分支

前端服务的生产发布流程在 RELEASING.md 中定义得非常直接:

# 标准流程:校验后强推当前 main 到 prod 分支 ./scripts/frontend/promote-prod.sh # 跳过校验,直接把当前 ref 推到 prod ./scripts/frontend/promote-prod.sh --force

对照脚本实现 promote-prod.sh,可以看到校验逻辑只有三行核心判断:

git fetch origin main if [ "$(git branch --show-current)" != "main" ] || \ [ "$(git rev-parse HEAD)" != "$(git rev-parse origin/main)" ]; then echo "Error: Must be on main branch and up to date with remote (use --force to override)" exit 1 fi git push --force origin HEAD:prod

即:默认模式下必须先git fetch origin main,然后断言“当前分支是main”且“本地 HEAD 与远端origin/main完全一致”,校验通过后执行git push --force origin HEAD:prod--force参数会完全跳过上述校验,直接把当前 ref(注意是HEAD,不一定是main)强推到prod。这个设计意味着你可以临时把某个历史提交推上生产做回滚,但代价是完全绕过了分支与同步性检查,文档将其定位为紧急操作手段。

为什么用分支而不是 tag?

原文档用折叠块解释了这一决策:Railway 不支持基于 tag 部署服务,因此团队把prod分支当作“类 tag”来用——每次发布都是把main的完整历史强推到prod,而不是在prod上积累自己的提交。这解释了为什么脚本用的是--force推送而非普通推送:prod分支的语义就是“最近一次被晋升到生产的快照”。

引擎发布:just release 命令族

引擎(以及配套的 TypeScript / Rust SDK)发布统一入口是 justfile 中的release任务:

just release --patch # 补丁版本(如 1.0.0 -> 1.0.1) just release --minor # 次版本(如 1.0.0 -> 1.1.0) just release --major # 主版本(如 1.0.0 -> 2.0.0) # 发布指定版本 just release --version 1.2.3

justfile中该任务只有一行转发逻辑(justfile):

[group('release')] release *ARGS: pnpm --filter=publish release {{ ARGS }}

而 scripts/publish/package.json 中release脚本指向tsx src/local/cut-release.ts。也就是说,just release的所有参数最终都传给本地切版编排器 cut-release.ts,其文件头注释明确写着“Linear release cutter — called by humans, never by CI”(线性切版器——只由人调用,绝不被 CI 调用)。

文档记载的全部参数与源码中的实际选项

除文档中的三个 bump 参数外,cut-release.ts的 CLI 定义(cut-release.ts)还暴露了以下选项:

选项作用
--version <version>显式指定版本号(如2.5.0),跳过基于 git tag 的自动计算
--major/--minor/--patch基于最新稳定 tag 做 semver 递增
--latest/--no-latest显式控制是否标记为latest(默认由脚本自动判定)
--dry-run不 commit / push / 触发 workflow,但仍会修改源文件
-y, --yes跳过交互式确认
--skip-checks跳过本地构建 + 类型检查的快速失败环节

文档还记载了“复用上一次发布产物”的用法:

just release --patch --reuse-engine-version 1.0.0

用于跳过 Docker 镜像与引擎二进制的重新构建。需要注意的是,在当前仓库的cut-release.ts源码选项中并未检索到--reuse-engine-version参数的定义(该选项可能属于较早版本的发布脚本,或经由其他实现路径生效),因此实操时建议以just release --help的实际输出为准——这也正是原文档“Runjust release --helpfor all available options”这句提示的意义所在。

版本号如何被解析:resolveVersion 与 shouldTagAsLatest

版本号解析逻辑位于 version.ts:

  • resolveVersion(version.ts):若未给--version,则先git fetch --tags --force拉取全部远端 tag(拉取失败会直接报错“refusing to compute latest flag from stale local tags”,拒绝基于过期本地 tag 计算),过滤出合法 semver 的v*tag,取最高稳定版(无 prerelease 标识)作为基准,再按--major/--minor/--patch执行semver.inc。若仓库中还没有任何版本 tag,会提示改用--version显式指定。
  • shouldTagAsLatest(version.ts):自动判定latest标志的规则是——版本不带 prerelease 标识,且严格大于现有最高稳定 tag。这意味着2.5.0-rc.1这类候选版本绝不会自动抢占latest;发布 rc 版时latest默认保持指向已发布的稳定版。

cut-release 的十步流程:从修改源文件到触发 CI

cut-release.ts的头部注释(cut-release.ts)列出完整步骤,实际实现与之一一对应。把本地这一步读懂,就理解了整个引擎发布的“前半程”:

  1. 解析目标版本(flags → semver bump → 否则报错);
  2. 确认latest标志:显式参数 > 自动判定 > false;
  3. 校验 git 工作区干净validateClean);
  4. 打印发布计划:版本、latest 标志、当前分支、上一个版本、最近 10 个版本列表,然后交互确认(Proceed with release? (yes/no));
  5. 更新非 package.json 源文件updateSourceFiles):改写根 Cargo.toml 的[workspace.package]version,以及examples/**/package.json中对rivetkit/@rivetkit/*的依赖锁定为^<version>
  6. Cargo 工作区依赖钉版bumpCargoVersions):把[workspace.dependencies]中内部 crate 的version = "=X"精确钉版全部同步到新版本——源码注释指出若漏掉这一步,Rust/wasm 构建会因内部 crate pin 版本不一致而解析失败;
  7. 重写所有可发布 package.json 的 version 字段bumpPackageJsonsversionOnly: true模式):只改version,保留workspace:*依赖写法,因为 lockfile 依赖这些写法,直接提交字面量版本会破坏pnpm install --frozen-lockfile
  8. 执行./scripts/fern/gen.sh重新生成 Fern 文档产物;
  9. 本地类型检查快速失败:运行pnpm build(针对 rivetkit 与@rivetkit/*,排除 napi/wasm 等平台包)+cargo check --workspace --exclude rivetkit-wasm,把编译错误拦截在触发 CI 之前;
  10. 提交、推送并触发 CIgit add .后以chore(release): update version to <version>提交;若当前在main分支直接git push,否则优先尝试 Graphite 的gt submit --force --no-edit --publish,失败则回退git push -u origin <branch>;最后通过gh workflow run .github/workflows/publish.yaml -f version=<v> -f latest=<bool> --ref <branch>触发发布工作流。

一个值得注意的细节:--dry-run只跳过第 10 步的 commit/push/trigger,第 5~7 步对源文件的修改依然会发生(源码注释明确写道 “still mutates source files”),因此 dry-run 之后需要手动还原工作区改动或重新检查 diff。

发布后端:publish.yaml 工作流的“另一半”

cut-release.ts触发的是 publish.yaml,这条 workflow 同时承担预览发布(preview publish)与正式切版(release cut)两种模式,两者构建步骤完全一致,只有 npm dist-tag、retag、git tag 和 GitHub Release 的差异:

  • trigger=branch(不带 version 的手动派发):npm_tag 为清洗后的分支名,build_mode 为 debug,用于 PR 预览包;
  • trigger=release(带 version 派发):npm_tag 默认latest;若版本号含-rc.则为rc,若latest=false则为next

CI 侧的执行入口是 bin.ts,注释强调“每个 workflow step 恰好调用一个子命令,workflow 本身就是编排者”。子命令按职责划分:

子命令职责
context-output解析一次 PublishContext(trigger/version/npm_tag/sha/latest/targets),写入$GITHUB_OUTPUT供后续步骤复用
bump-versions发布时刻才执行完整版bumpPackageJsons:把workspace:*改写为字面量版本、向 meta 包注入optionalDependencies(按 os/cpu/libc 解析平台二进制),并校验没有workspace:/catalog:协议残留——源码注释提到曾因catalog:泄漏发布过不可安装的 rivetkit@2.3.14,所以现在会 fail loudly
publish-npm并行发布 npm 包(默认并发 16、每包重试 3 次)
publish-crates按依赖顺序发布 crates.io(默认每 crate 最多等 10 分钟索引),已存在则跳过,含 crates.io 限流重试
upload-r2/copy-r2制品先传rivet/{sha}/engine/,再复制到rivet/{version}/engine/(latest 时加rivet/latest/
docker-manifest/docker-retag为 commit sha 生成多架构 manifest,再 retag 到版本/latest
git-tag/gh-release强制创建并推送v{version}tag,创建/更新 GitHub Release
comment-pr在预览 PR 上 upsert 安装说明(npm install rivetkit@<tag>docker pull rivetdev/engine:slim-<sha>等)

crates.io 发布顺序在源码中被硬编码为依赖拓扑序(bin.ts 的RUST_CRATES列表),注释给出了两条关键约束:rivet-envoy-protocol必须先于精确 pin 它的rivet-depot-client发布,否则 cargo 无法解析;rivetkit-engine-process虽是rivetkit-core的可选依赖,但 cargo 在发布时仍要求它能在 crates.io 上被解析,所以也必须在rivetkit-core之前。

此外 justfile 还提供了一个不走just release的旁路:

just preview-publish <REF> # 等价于: gh workflow run .github/workflows/publish.yaml --ref "<REF>"

对任意 ref 手动派发 workflow(不带 version),即可产出该分支的预览包,供 PR 评审或灰度验证使用。

发布前自检清单

结合文档与源码,一次安全的引擎发布应满足:

  1. 本地工作区干净且 tag 已git fetch到最新(脚本会强制校验,但人工确认更稳);
  2. 明确本次是稳定版(可自动成为latest)还是 rc 版(latest默认不切换);
  3. 留意--dry-run仍会改写Cargo.toml与各package.json,dry-run 后需检查并还原 diff;
  4. 切版提交推送后,确认 workflow 触发成功,并跟踪 context → build → npm/crates/R2/docker → git tag → GitHub Release 各阶段;
  5. 前端生产变更走promote-prod.sh,且非必要不使用--force跳过 main 分支与远端同步校验。

小结

Rivet Actors 的发布体系体现了“本地编排 + CI 执行”的清晰分工:RELEASING.md 中简洁的三条路径背后,前端侧是prod分支强推这一最小可用机制(受限于 Railway 的部署能力),引擎侧则是 cut-release.ts 的十步线性切版流程与 publish.yaml 中高度子命令化的 CI 发布流水线。版本解析基于 git tag 的稳定版 semver 递增,latest标志由“无 prerelease 且严格高于现有稳定版”自动判定,npm 与 crates.io 双通道按依赖拓扑序幂等发布,制品(二进制、Docker 镜像、安装脚本)统一沉淀到 R2 的rivet/{sha} → rivet/{version}/latest晋升路径上。理解这套机制后,无论是排查一次失败的发布,还是为新版本选择合适的 bump 策略,都能直接定位到对应源码环节。

【免费下载链接】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 6:55:11

MySQL图书管理系统:数据库原生闭环设计实战

简介&#xff1a;本资源是一份面向高校计算机专业学生及数据库初学者的《图书管理系统数据库设计》完整方案文档&#xff0c;聚焦MySQL关系型数据库在图书馆业务场景中的落地实践。文档系统覆盖需求分析、E-R模型建模、6张核心数据表&#xff08;student/book/borrow/return_ta…

作者头像 李华
网站建设 2026/9/17 6:54:42

STM32F407上FreeRTOS与LwIP深度协同实战指南

1. 这不是“跑个例程”——STM32F407上跑通FreeRTOSLwIP的真实门槛在哪里&#xff1f;你搜“STM32F407 FreeRTOS LwIP移植”&#xff0c;首页全是Keil工程截图、几行初始化代码、一句“已验证可用”。但真正把FreeRTOS和LwIP在STM32F407上稳定跑起来&#xff0c;让HTTP服务器能…

作者头像 李华
网站建设 2026/9/17 6:54:30

RDMA无损网络中PFC配置的五大核心参数与实战技巧

1. 项目背景与核心挑战RDMA&#xff08;远程直接内存访问&#xff09;技术正在成为数据中心网络性能优化的关键利器&#xff0c;而PFC&#xff08;优先级流量控制&#xff09;作为保障RDMA无损网络的核心机制&#xff0c;其配置过程却暗藏玄机。三年前我第一次接触RoCEv2网络部…

作者头像 李华
网站建设 2026/9/17 6:54:29

DevOps时代测试工程师的转型与技能升级

1. 测试角色在DevOps时代的转型挑战十年前我刚入行测试时&#xff0c;手工执行用例、记录缺陷还是主流工作模式。如今在持续交付的浪潮下&#xff0c;测试团队经常面临这样的灵魂拷问&#xff1a;当开发自己就能通过流水线完成部署验证&#xff0c;传统测试工程师的价值该如何体…

作者头像 李华
网站建设 2026/9/17 6:53:39

银河麒麟V10 KVM虚拟化部署与桥接网络排障实战

1. 整体设计与方案选型1.1 为什么选择KVM而不是其他虚拟化方案银河麒麟高级服务器操作系统在国产化替代和信创项目中出镜率极高&#xff0c;尤其是V10版本&#xff0c;无论是党政机关还是金融、能源、教育行业&#xff0c;都能看到它的身影。而在服务器上跑虚拟机这件事&#x…

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

calibre:4步搞定电子书格式转换,顺带管完整个书库

calibre&#xff1a;4步搞定电子书格式转换&#xff0c;顺带管完整个书库 【免费下载链接】calibre The official source code repository for the calibre ebook manager 项目地址: https://gitcode.com/GitHub_Trending/ca/calibre 手里的EPUB传不进Kindle&#xff0c…

作者头像 李华