首页
/ Gemini CLI 发布流程深度解析:从 nightly 到 stable 的渠道晋级、Patch 与双产物打包机制

Gemini CLI 发布流程深度解析:从 nightly 到 stable 的渠道晋级、Patch 与双产物打包机制

2026-09-06 13:18:05作者:魏侃纯Zoe

本文基于仓库官方文档 docs/releases.md 与配套脚本、CI 工作流源码,系统讲解 Gemini CLI 的发布体系:dev/prod 双环境与 NPM 命名空间、nightly/preview/stable 三渠道的晋级节奏、以 NPM 为唯一版本真相源的完整性校验、手动发布与回滚、/patch 热修复自动化流程,以及 NPM 包与 GitHub Release 单文件可执行体的双产物打包细节。读完后你能完整掌握如何安装指定渠道、触发发布工作流、执行 Patch 与回滚,并理解其底层校验与打包原理。

dev 与 prod 双发布环境

Gemini CLI 的发布流程同时支持 devprod 两个环境,两者的核心差异在于 NPM 仓库与包命名空间:

  • dev 环境:推送到私有、由 GitHub 托管的 NPM 仓库,包名以 @google-gemini/** 开头。
  • prod 环境:通过 Wombat Dressing Room 推送到公共全局 NPM 仓库,包名统一为 @google/**。Wombat Dressing Room 是 Google 用于管理 @google/** 命名空间 NPM 包的系统。

各包在两个环境下的命名对照如下:

Package prod(Wombat Dressing Room) dev(GitHub 私有 NPM 仓库)
CLI @google/gemini-cli @google-gemini/gemini-cli
Core @google/gemini-cli-core @google-gemini/gemini-cli-core
A2A Server @google/gemini-cli-a2a-server @google-gemini/gemini-cli-a2a-server

从源码结构看,这一命名差异由发布动作中的包名变量驱动:.github/actions/publish-release/action.yml 使用 wombat-token-corewombat-token-cliwombat-token-a2a-server 三个 Wombat token 以及 cli-package-namecore-package-namea2a-package-name 等仓库变量来区分发布目标,这与 docs/releases.md 中描述的双环境模型一致。更多包结构与职责说明可参见 NPM Package Overview

发布节奏与语义化版本标签

Gemini CLI 尽可能遵循 SemVer 规范,并在偏离时明确说明。其发布节奏为:每周发布对应 minor 版本,两次发布之间的 bug 修复或热修复则以 patch 版本形式发布到最近的 release 上。

晋级(promotion)流程如下:

  • 代码提交到 main 分支,并每晚推送到 nightly 渠道;
  • 代码在 main 上停留不超过一周后,被晋级到 preview 渠道;
  • 停留一周后,最近的 preview 渠道被晋级到 stable 渠道;
  • 补丁修复会按需同时作用于 previewstable,最终的 patch 版本号每次递增。

从当前仓库的根 package.json 可以看到,版本字符串遵循 major.minor.patch-nightly.日期.g提交号 的格式(例如 0.59.0-nightly.20260825.g812f7a2bc),这正是 nightly 渠道的命名产物,印证了上述节奏。

Preview 渠道

该渠道的发布尚未经过完整验证,可能包含回归或其他未决问题。安装方式:

npm install -g @google/gemini-cli@preview

Stable 渠道

Stable 是上周发布的完整晋级版本,外加所有 bug 修复与验证。使用 latest 标签:

npm install -g @google/gemini-cli@latest

Nightly 渠道

每天 UTC 00:00 发布一次,内容是发布时刻 main 分支的全部变更。应假定其存在待验证项与问题。使用 nightly 标签:

npm install -g @google/gemini-cli@nightly

每周发布晋级(Weekly Release Promotion)

每周二,值班工程师触发 "Promote Release" 工作流,这一单一动作自动化了整个每周发布过程:

  1. 将 preview 晋级为 stable:工作流识别最新的 preview 发布并晋级为 stable,成为 npm 上新的 latest 版本。
  2. 将 nightly 晋级为 preview:最新的 nightly 发布被晋级为新的 preview 版本。
  3. 为下一个 nightly 做准备:自动创建并合并一个 PR,用于提升 main 上的版本号,为下一次 nightly 发布做准备。

该流程以极少的干预保证了稳定可靠的发布节奏。

版本号的唯一真相源(Source of Truth)

为确保最高可靠性,发布晋级过程以 NPM 仓库作为每个发布渠道(stablepreviewnightly)当前版本的唯一真相源

  1. 从 NPM 获取:工作流先查询 NPM 的 dist-tagslatestpreviewnightly),获取用户当前可安装的精确版本字符串。
  2. 完整性交叉校验:对 NPM 检索到的每个版本,工作流执行关键的完整性检查——验证仓库中是否存在对应的 git tag,以及是否已创建对应的 GitHub release
  3. 差异即中止:若 NPM 上列出的某个版本缺少 git tag 或 GitHub Release,工作流立即失败。这一严格检查可阻止从损坏或不完整的上一发布进行晋级,并提醒值班工程师存在需要手动解决的发布状态不一致。
  4. 计算下一版本:只有上述检查全部通过,工作流才基于从 NPM 获取的可信版本号计算下一个语义化版本。

这种「NPM 优先 + 完整性校验」的方法使发布流程高度健壮,避免了单纯依赖 git 历史或 API 输出可能导致的版本不一致。

手动发布(Manual Release)

对于需要脱离常规 nightly 与每周晋级节奏、且不在 patch 流程覆盖范围内的发布场景,可以使用 Release: Manual 工作流。它提供了从任意分支、tag 或提交 SHA 直接发布特定版本的途径。对应工作流文件为 release-manual.yml

手动发布的创建步骤

  1. 进入仓库的 Actions 选项卡
  2. 从列表中选中 Release: Manual 工作流。
  3. 点击 Run workflow 下拉按钮。
  4. 填写所需输入参数:
    • Version:要发布的精确版本(例如 v0.6.1),必须是带 v 前缀的合法语义化版本。
    • Ref:要从中发布的分支、tag 或完整提交 SHA。
    • NPM Channel:要发布的 npm 渠道,可选 previewnightlylatest(stable 发布)、dev
    • Dry Run:保持 true 可执行所有步骤但不实际发布;设为 false 执行真实发布。
    • Force Skip Tests:设为 true 跳过测试套件,生产发布不建议这样做。
    • Skip GitHub Release:设为 true 时跳过创建 GitHub release,仅创建 npm release。
    • Environment:选择合适的环境。dev 用于测试,prod 用于生产发布;prod 为默认值,且需要发布管理员授权。
  5. 点击 Run workflow

随后工作流将进行(若未跳过的)测试、构建与发布。若工作流在非 dry run 过程中失败,会自动创建一个包含失败详情的 GitHub issue。

从源码看,release-manual.ymlworkflow_dispatch.inputs 与上述参数一一对应(versionrefnpm_channeldry_runforce_skip_testsskip_github_releaseenvironment),并在失败时以 release-failure,priority/p0 标签自动开 issue,与文档描述的失败通知机制吻合。

回滚 / 前滚(Rollback / Rollforward)

当某个发布出现严重回归时,可通过修改 npm dist-tag 快速回滚到之前的 stable 版本,或前滚到一个新补丁。Release: Change Tags 工作流提供了安全可控的方式来执行这一操作,是回滚与前滚的首选方法——因为它无需走完整发布周期。对应工作流为 release-change-tags.yml

如何修改发布标签

  1. 进入仓库 Actions 选项卡
  2. 选中 Release: Change Tags 工作流。
  3. 点击 Run workflow 下拉按钮。
  4. 填写所需输入:
    • Version:希望标签指向的已存在包版本(例如 0.5.0-preview-2),该版本必须已发布到 npm 仓库。
    • Channel:要应用的 npm dist-tag(例如 previewstable)。
    • Dry Run:保持 true 仅记录操作不做变更;设为 false 执行真实的标签变更。
    • Environment:选择合适的环境,dev 用于测试,prod 用于生产发布;prod 为默认且需发布管理员授权。
  5. 点击 Run workflow

随后工作流会为 gemini-cligemini-cli-coregemini-cli-a2a-server 三个包执行 npm dist-tag add,将指定渠道指向指定版本。

从源码看,tag-npm-release 复合动作会对 core、cli、a2a-server 三个包分别调用 npm dist-tag add <包名>@<版本> <渠道>,这正是文档所述「为三个包改标签」的落地实现。

补丁(Patching)

当一个已在 main 上修复的严重 bug 需要回补到 stablepreview 发布时,该过程已高度自动化。相关链路涉及 release-patch-0-from-comment.ymlrelease-patch-1-create-pr.ymlrelease-patch-2-trigger.ymlrelease-patch-3-release.yml

如何打补丁

1. 创建补丁 PR

有两种方式:

方式 A:从 GitHub 评论触发(推荐)

包含修复的 PR 合并后,维护者可以在同一 PR 下按以下格式添加评论:

/patch [channel]
  • channel(可选):
    • 不带 channel —— 同时打 stable 与 preview 渠道(默认,大多数修复推荐)。
    • both —— 同时打 stable 与 preview(与默认相同)。
    • stable —— 只打 stable 渠道。
    • preview —— 只打 preview 渠道。

示例:

  • /patch(默认,打 stable 与 preview)
  • /patch both(显式打 stable 与 preview)
  • /patch stable(只打 stable)
  • /patch preview(只打 preview)

Release: Patch from Comment 工作流会自动找到 merge commit SHA 并触发 Release: Patch (1) Create PR 工作流。若 PR 尚未合并,则发布一条表示失败的评论。

方式 B:手动触发工作流

进入 Actions 选项卡,运行 Release: Patch (1) Create PR 工作流:

  • Commit:要在 main 上 cherry-pick 的提交完整 SHA。
  • Channel:要打补丁的渠道(stablepreview)。

该工作流会自动:

  1. 找到该渠道最新的 release tag;
  2. 若不存在,从该 tag 创建 release 分支(例如 release/v0.5.1-pr-12345);
  3. 从 release 分支创建新的 hotfix 分支;
  4. 将指定 commit cherry-pick 到 hotfix 分支;
  5. 从 hotfix 分支向 release 分支创建 PR。

2. 审阅与合并

审阅自动创建的 PR,确认 cherry-pick 成功且改动正确,批准后合并。

警告release/* 分支受分支保护规则约束。针对这些分支的 PR 至少需要一名 code owner 的评审才能合并,以确保不发布未经授权代码。

2.5. 向 hotfix 追加多个提交(进阶)

若需要在单个补丁发布中包含多个修复,可在初始 patch PR 创建后向 hotfix 分支追加更多提交:

  1. 从主修复开始:在最关键的 PR 上使用 /patch(或 /patch both)创建初始 hotfix 分支与 PR。

  2. 本地签出 hotfix 分支

    git fetch origin
    git checkout hotfix/v0.5.1/stable/cherry-pick-abc1234  # 使用 PR 中的实际分支名
    
  3. Cherry-pick 其他提交

    git cherry-pick <commit-sha-1>
    git cherry-pick <commit-sha-2>
    # 按需添加任意多个提交
    
  4. 推送更新后的分支

    git push origin hotfix/v0.5.1/stable/cherry-pick-abc1234
    
  5. 测试与审阅:现有 patch PR 会自动更新,纳入你追加的提交。由于现在将一起发布多个变更,务必充分测试。

  6. 更新 PR 描述:建议更新 PR 标题与描述,以反映其包含多个修复。

这种做法可将相关修复归组到单个补丁发布中,同时保持对包含内容与冲突解决的完全控制。

3. 自动发布

合并 PR 后,Release: Patch (2) Trigger 工作流被自动触发,它继而启动 Release: Patch (3) Release 工作流,该工作流会:

  1. 构建并测试打了补丁的代码;
  2. 将新的 patch 版本发布到 npm;
  3. 创建包含补丁说明的新 GitHub release。

这一全自动化流程确保补丁以一致、可靠的方式被创建与发布。

故障排查:旧分支工作流

问题:若 patch 触发工作流出现诸如 "Resource not accessible by integration" 或引用不存在的工作流文件(例如 patch-release.yml)的错误,说明 hotfix 分支包含了过期版本的工作流文件。

根因:当 PR 合并时,GitHub Actions 会从 源分支(hotfix 分支)而非目标分支(release 分支)读取工作流定义。若 hotfix 分支由一个早于工作流改进的旧 release 分支创建,它便会使用旧的工作流逻辑。

解决方案

方案 1:手动触发(快速修复) —— 手动从拥有最新工作流代码的分支触发更新后的工作流:

# preview 渠道补丁(跳过测试)
gh workflow run release-patch-2-trigger.yml --ref <branch-with-updated-workflow> \
  --field ref="hotfix/v0.6.0-preview.2/preview/cherry-pick-abc1234" \
  --field workflow_ref=<branch-with-updated-workflow> \
  --field dry_run=false \
  --field force_skip_tests=true

# stable 渠道补丁
gh workflow run release-patch-2-trigger.yml --ref <branch-with-updated-workflow> \
  --field ref="hotfix/v0.5.1/stable/cherry-pick-abc1234" \
  --field workflow_ref=<branch-with-updated-workflow> \
  --field dry_run=false \
  --field force_skip_tests=false

# 使用 main 分支的示例(最常见情形)
gh workflow run release-patch-2-trigger.yml --ref main \
  --field ref="hotfix/v0.6.0-preview.2/preview/cherry-pick-abc1234" \
  --field workflow_ref=main \
  --field dry_run=false \
  --field force_skip_tests=true

注意:将 <branch-with-updated-workflow> 替换为包含最新工作流改进的分支(通常是 main,若正在测试更新则可能是某个特性分支)。

方案 2:更新 hotfix 分支 —— 将最新 main 合并进 hotfix 分支以获取更新后的工作流:

git checkout hotfix/v0.6.0-preview.2/preview/cherry-pick-abc1234
git merge main
git push

然后关闭并重开 PR,以使用更新后的版本重新触发工作流。

方案 3:直接触发发布 —— 完全跳过触发工作流,直接运行发布工作流:

# 将 channel 与 release_ref 替换为合适值
gh workflow run release-patch-3-release.yml --ref main \
  --field type="preview" \
  --field dry_run=false \
  --field force_skip_tests=true \
  --field release_ref="release/v0.6.0-preview.2"

Docker 发布

此外还有一个 Google Cloud Build,名为 release-docker.yml,用于发布与你的发布版本匹配的 sandbox Docker 镜像。待服务账号权限问题解决后,它也会迁移到 GitHub 并与主发布文件合并。

发布验证(Release Validation)

推送新发布后应执行冒烟测试,以确保包按预期工作:安装包到本地并运行一组测试。

  • npx -y @google/gemini-cli@latest --version:若非 rc 或 dev 标签发布,用于验证推送是否符合预期。
  • npx -y @google/gemini-cli@<release tag> --version:用于验证标签是否正确推送。
  • 此操作在本地具有破坏性npm uninstall @google/gemini-cli && npm uninstall -g @google/gemini-cli && npm cache clean --force && npm install @google/gemini-cli@<version>
  • 建议通过一次基本的 LLM 命令与工具演练做冒烟测试,以确保包按预期工作。

本地测试与验证:打包发布流程变更

若需要在不真正发布到 NPM 或创建公开 GitHub release 的情况下测试发布流程,可从 GitHub UI 手动触发工作流:

  1. 进入仓库的 Actions 选项卡(release-manual.yml)。
  2. 点击 "Run workflow" 下拉。
  3. 保持 dry_run 选项勾选(true)。
  4. 点击 "Run workflow" 按钮。

这将运行整个发布流程,但会跳过 npm publishgh release create 步骤。可检查 workflow 日志确认一切符合预期。

在提交前于本地测试任何对打包与发布流程的变更至关重要,可确保包被正确发布并在用户安装后正常工作。文档中给出了用于验证变更的 dry run 命令:

npm_package_version=9.9.9 SANDBOX_IMAGE_REGISTRY="registry" SANDBOX_IMAGE_NAME="thename" npm run publish:npm --dry-run

该命令会:

  1. 构建所有包;
  2. 运行所有 prepublish 脚本;
  3. 创建将要发布到 npm 的包 tarball;
  4. 打印将要发布的包摘要。

随后可检查生成的 tarball,确认其包含正确的文件,且 package.json 已被正确更新。tarball 会创建在每个包目录的根(例如 packages/cli/google-gemini-cli-0.1.6.tgz)。

从源码结构看,打包产物的组装由若干脚本支撑:scripts/prepare-npm-release.js 会把项目根目录的 bundle/ 复制到 packages/cli/bundle/,并将 @google/gemini-clipackage.json 改写为 files: ['bundle/']bin: { gemini: 'bundle/gemini.js' },同时移除 dependenciesdevDependenciesscripts 等字段并继承根包的 optionalDependencies(剔除 gemini-cli-devtools)。这与根 package.jsonbin.gemini -> bundle/gemini.jsfiles: ["bundle/", "README.md", "LICENSE"] 的配置一致,说明 npm 包最终也是以单文件可执行体形式分发。而 scripts/version.js 则负责统一提升根包与所有 workspace 包的版本,并同步更新根包与 cli 包中的 sandboxImageUri 镜像 tag,保证 Docker 镜像与发布版本对齐。

发布深度解析(Release Deep Dive)

发布过程为不同分发渠道生成两类不同产物:面向 NPM 仓库的标准包,以及面向 GitHub Releases 的单个自包含可执行文件。关键阶段如下:

阶段 1:发布前健全性检查与版本化

在移动任何文件之前,流程确保项目处于良好状态:运行测试、lint 与类型检查(对应根 package.json 中的 preflight 脚本,其串联了 cleanciformatbuildlint:citypechecktest:ci)。随后把根 package.jsonpackages/cli/package.json 的版本号更新为新发布版本。

阶段 2:为 NPM 构建源码

packages/core/srcpackages/cli/src 中的 TypeScript 源码编译为标准 JavaScript:

  • packages/core/src/**/*.ts -> 编译为 -> packages/core/dist/
  • packages/cli/src/**/*.ts -> 编译为 -> packages/cli/dist/

原因:开发期编写的 TypeScript 需转换为 Node.js 可运行的纯 JavaScript。由于 cli 包依赖 core,故先构建 core

阶段 3:向 NPM 发布标准包

@google/gemini-cli-core@google/gemini-cli 执行 npm publish,以标准 Node.js 包形式发布。用户通过 npm install -g @google/gemini-cli 安装时会下载这些包,npm 会自动处理 @google/gemini-cli-core 依赖的安装。这些包中的代码并非被打包成单文件。

阶段 4:组装并创建 GitHub release 资产

该阶段发生在 NPM 发布之后,生成支持直接从 GitHub 仓库使用 npx 的单文件可执行体。

  1. 创建 JavaScript 打包文件:由 esbuildpackages/core/distpackages/cli/dist 构建出的 JS,连同所有第三方 JS 依赖,打包成单个可执行 JS 文件(例如 gemini.js)。由于 node-pty 库包含原生二进制,故被排除在该打包之外。这为不想做完整 npm install 的用户提供了单文件、内联所有依赖的简化执行方式。
  2. 组装 bundle 目录:在项目根创建临时 bundle 文件夹,放入 gemini.js 可执行体及其他必要文件:
    • gemini.js(来自 esbuild)-> bundle/gemini.js
    • README.md -> bundle/README.md
    • LICENSE -> bundle/LICENSE
    • packages/cli/src/utils/*.sb(sandbox 配置文件)-> bundle/
  3. 创建 GitHub release:将 bundle 目录内容(含 gemini.js 可执行体)作为资产附加到新的 GitHub Release,使单文件版 CLI 可直接下载,并支持 npx 拉取该特定打包资产运行。

产物小结

  • NPM:发布标准的、未打包的 Node.js 包,主要产物是 packages/cli/dist 中的代码,它依赖 @google/gemini-cli-core
  • GitHub release:发布单文件、已打包的 gemini.js,包含所有依赖,便于通过 npx 执行。

这一双产物流程确保传统 npm 用户与偏好 npx 便捷性的用户都能获得优化体验。

发布失败通知(Notifications)

失败的发布工作流会自动创建带 release-failure 标签的 issue。当创建此类 issue 时,会向维护者的聊天频道发送通知。

修改聊天通知

通知使用 GitHub for Google Chat 应用。如需修改通知,可在聊天空间内使用 /github-settings

警告:以下说明描述了一个脆弱的变通方案,依赖聊天应用 UI 的内部结构,很可能在未来更新中失效。

可用标签列表当前未被正确填充。若要添加一个未出现在仓库前 30 个字母序标签中的标签,必须使用浏览器开发者工具手动修改 UI:

  1. 打开浏览器开发者工具(例如 Chrome DevTools)。
  2. /github-settings 对话框中,检查标签列表。
  3. 定位到代表某个标签的 <li> 元素之一。
  4. 在 HTML 中,将该 <li> 元素的 data-option-value 属性修改为所需标签名(例如 release-failure)。
  5. 在 UI 上点击修改后的标签以选中,然后保存设置。
登录后查看全文
热门项目推荐
相关项目推荐