Sentry JavaScript SDK 版本发布全流程指南:从 Changelog 到 CI 自动发布与 Gitflow 分支同步

原创2026-09-25 10:57:391,753 阅读
文章标签:可观测性

Sentry JavaScript SDK 版本发布全流程指南:从 Changelog 到 CI 自动发布与 Gitflow 分支同步

本文以 Sentry JavaScript SDK(sentry-javascript)官方发布流程文档为骨架,系统讲解该仓库从日常开发到正式发布一个 SDK 版本的完整操作路径:如何在 develop 分支上生成并整理 Changelog、如何以 prepare-release/VERSION 分支触发自动发布、如何针对历史大版本与 alpha/beta 预发布版本手动执行 Release 工作流,以及发布后 master 回同步 develop 的 Gitflow 机制。读完本文,你将掌握该仓库(以及采用了类似 Craft 发布体系的 Sentry 系列仓库)的版本号决策、Changelog 撰写规范、CI 自动发布触发条件与手动发布兜底方案,能够独立完成一次标准的 SDK 版本发布。

背景:sentry-javascript 的发布体系概览

sentry-javascript 是一个包含 @sentry/browser、@sentry/node、@sentry/nextjs 等数十个 npm 包与 CDN 产物的大型 monorepo(仓库根目录下的 package.json 声明了所有工作区脚本)。版本发布并非手工逐包打包上传,而是围绕 Craft(Sentry 自研的开源发布工具链)与 GitHub Actions 构建的一套半自动流水线:

本文主体依据官方文档 docs/publishing-a-release.md 展开,并补充了仓库内工作流文件、scripts/generate-changelog.ts、.craft.yml 等源码证据,帮助你理解每一步背后的实现原理。

注意:文档开篇明确说明,这些步骤仅对 Sentry 员工在准备和发布新 SDK 版本时适用("These steps are only relevant to Sentry employees")。因此本文面向的是该仓库的维护者/发布者角色;外部贡献者只需了解流程,无权触发发布。

发布前的准备:理解 Gitflow 分支模型

要正确执行发布流程,必须先理解仓库采用的 Gitflow 分支模型,详见 docs/gitflow.md:

  • 所有日常工作发生在 develop 分支上,功能、修复类 PR 都合入 develop;
  • 准备发布时,将 develop 合并进 master,在 master 上发布,随后再把 master 合并回 develop;
  • master 上的内容可视为 SDK 的上一次已发布状态;禁止直接向 master 合入(紧急 Bugfix 发布除外)。

一个关键约束是:在发布进行期间,可以往 develop 合入任何内容,唯独不能修改 package.json 文件。因为发布过程中 Craft 会在 master 上更新各包的 package.json(版本号),如果 develop 也改了这些文件,master -> develop 的 Gitflow 同步 PR 就会产生合并冲突。

如果发布后同步 PR 仍然出现合并冲突,docs/gitflow.md 给出的解决方案是:关闭自动化 PR → 在 master 之上新建分支(如 manual-develop-sync)→ 用 merge commit 把 develop 合并进来并解决冲突 → 再向 develop 提 PR 并同样以 merge commit 合并。

主线发布流程:prepare-release 自动发布(8 步)

以下是从 docs/publishing-a-release.md 第一节整理出的主线发布步骤,适用于在 develop 上发布的当前大版本:

Step 1:在 develop 分支运行 yarn changelog,确定要发布的版本号

yarn changelog

该命令实际执行的是 tsx ./scripts/get-commit-list.ts(见根目录 package.json)。脚本通过 git log --format="- %s" 拉取提交列表,定位到最近一条 meta(changelog) 提交作为上一次发布点,取出其后的所有新提交;过滤掉 Merge pull request、Merge branch 与 release: 类提交后按字母序排序,并把 PR 编号 #123 自动替换为指向对应 PR 的链接(见 scripts/get-commit-list.ts)。

版本号遵循 semver 语义化版本规范,决策原则是:

  • 包含新功能(feature)→ 递增 minor 版本,例如 8.2.0;
  • 仅包含 Bug 修复 → 递增 patch 版本,例如 8.1.1;
  • 含破坏性变更 → 递增 major 版本。

Step 2:基于 develop 创建发布准备分支

git checkout develop
git checkout -b prepare-release/VERSION
# 例如:git checkout -b prepare-release/8.1.0

分支名必须严格遵循 prepare-release/<版本号> 的格式,因为自动发布工作流正是靠解析这个分支名来提取版本号的(见下文 Step 6 的源码解析)。

Step 3:更新 CHANGELOG.md,为下一个版本号新增条目

在 Changelog 中为将要发布的版本添加一个章节,并列出自上次发布以来的所有变更(详细规范见本文"Changelog 撰写规范"一节)。

Step 4:提交 PR

PR 标题固定为:

meta(changelog): Update changelog for VERSION

(例如 meta(changelog): Update changelog for 8.1.0),目标分支为 master。

Step 5:⚠️ 谨慎操作 —— 合入方式必须是 "Merge Commit"

合并 prepare-release 分支到 master 的 PR 必须使用 Merge Commit(合并提交)方式合入,而不是 Squash and Merge。这是为了让 prepare-release/8.1.0 分支上的所有提交(含 changelog 提交本身)都原样保留在 master 的历史中,从而被 auto-release 工作流正确识别。

Step 6:PR 合并后自动触发 Auto Prepare Release

PR 合入 master 后,.github/workflows/auto-release.yml 随即被触发。该工作流在 pull_request 事件类型为 closed 且分支为 master 时启动,核心逻辑如下:

  1. 使用 Sentry Release Bot 的 GitHub App token 检出代码(fetch-depth: 0);
  2. 用正则 ^prepare-release\/(\d+\.\d+\.\d+)(?:-(alpha|beta|rc)\.\d+)?$ 匹配 head 分支名,从中提取版本号(该正则可以识别 prepare-release/8.1.0,也能识别带 -alpha.1、-beta.1、-rc.1 后缀的预发布版本号);
  3. 在 github.event.pull_request.merged == true 且版本号非空的前提下,调用 getsentry/craft action(v2.30.1)执行发布准备,参数为 version: <提取的版本号>、merge_target: master、craft_config_from_merge_target: true。

换言之,只要合入 master 的分支名符合 prepare-release/<版本> 模式,版本号就会被自动解析并交给 Craft 准备发布。

Step 7:在 Sentry 的发布跟踪仓库出现新 issue

发布准备开始后,会自动在 getsentry/publish 仓库中创建一个新 issue,用于跟踪本次发布的 CI 状态与审批进度(issue 中会附带 CI 检查运行的链接)。这属于 Sentry 内部基础设施,外部贡献者无法访问。

Step 8:等待 CI 通过并打上 accepted 标签

  • 等待 issue 中链接的 CI 检查全部运行成功(包括各包的构建、测试与 tarball 产物检查);
  • 在 issue 上设置 accepted 标签,批准本次发布;
  • 发布完成后,master -> develop 的自动同步会被触发(详见本文"发布后的 Gitflow 同步"一节)。

历史大版本与预发布(alpha / beta)版本的发布流程

主线流程只覆盖在 develop 上发布当前大版本。如果需要为上一个主版本分支(例如 v8)或预发布版本分支(例如 9.7.0-alpha)发布补丁或快照版本,则走手动流程:

Step 1:在对应分支上运行 yarn changelog 确定版本

在旧分支(如 v8)或预发布分支(如 9.7.0-alpha)上运行 yarn changelog,依据 semver 确定要发布的版本(例如补丁 8.45.1,或预发布 9.7.0-alpha.1)。

Step 2:从该分支创建 changelog 分支

# 从 v8 分支创建
git checkout v8
git checkout -b changelog-8.45.1

# 或从预发布分支创建
git checkout 9.7.0-alpha
git checkout -b changelog-9.7.0-alpha.1

Step 3:更新 CHANGELOG.md,新增对应版本条目(规范同主线流程)。

Step 4:提交 PR

PR 标题仍为 meta(changelog): Update changelog for VERSION,但目标分支是对应的旧大版本分支或预发布分支(如 v8、9.7.0-alpha),而非 master。

Step 5:⚠️ 合入方式不同 —— "Squash and Merge"

与主线流程相反,针对旧分支的 changelog PR 应使用 Squash and Merge,因为该分支上的提交已存在于历史中,无需保留合并提交。

Step 6:手动触发 Prepare Release 工作流

PR 合入后,打开 .github/workflows/release.yml(名为 "Action: Prepare Release")的 workflow_dispatch 界面,填写三个输入项:

输入项 含义 示例
version 要发布的版本号(或填 auto) 8.45.1、9.7.0-alpha.1
force 即使存在 release-blocker 也强制发布(可选) 留空
merge_target 要合入的目标分支,默认 master v8、9.7.0-alpha

工作流声明了 workflow_dispatch 手动触发事件,三个输入均非必填,其中 merge_target 默认值为 master。该工作流同样通过 getsentry/craft action 执行发布,并把 version、force、merge_target 原样传给 Craft(见 .github/workflows/release.yml)。Craft 会根据 .craft.yml 中声明的 targets 逐个发布(详见下文)。

Step 7:运行发布工作流

点击 "Run workflow" 后,由 Craft 完成版本 bump、打包、发布 npm 包、上传 CDN bundle、创建 GitHub Release 与更新 Release Registry 等全部动作。

图片 docs/assets/run-release-workflow.png 展示了 Release 工作流界面中填写 major branch、version、major branch to merge into 三个字段的示例截图,可在仓库中查看:docs/assets/run-release-workflow.png。图示对应手动工作流中的三个输入:要发布的大版本分支、要发布的版本号、要合并回的大版本分支。

Changelog 撰写规范

Changelog 是发布流程的"输入原料",其格式直接决定发布说明的呈现质量。官方文档的规范如下。

生成与搬运

# 基础生成(git 提交列表)
yarn changelog

# 最佳实践:格式化生成(推荐)
yarn generate-changelog

yarn generate-changelog 执行 scripts/generate-changelog.ts,它解析 CHANGELOG.md 中的 ## Unreleased 章节,将其中的已有条目与新提交合并、去重(按 PR 编号)、自动分类并排序,最后输出格式化后的 changelog 文本,可直接复制粘贴进新版本章节。脚本的分类逻辑(determineEntryType)如下:

  • 条目首行包含 **feat 或 **fix → 归入 Important Changes;
  • 以 chore、ref、test、meta 开头的提交 → 归入 Internal Changes;
  • 其余 → 归入 Other Changes。

在 Changelog 中新增版本章节

  1. 运行上述任一命令并复制全部输出;
  2. 在 Changelog 中创建以版本号命名的章节(## <版本号>,例如 ## 9.28.0);
  3. 粘贴复制的日志内容。

章节组织规则

  • Important Changes(重要变更):如果存在重要功能或修复,在 ### Important Changes 小标题下列出,并附上简要说明段落。例如文档示例中 feat(node) 条目解释了为何更新 span 名称与 op 以匹配 OpenTelemetry 约定。
  • Other Changes(其他变更):使用 ### Other Changes 小标题收纳其余面向用户的变更。
  • Internal Changes(内部变更):纯内部改动(如无用户可见影响的 ref 重构、测试、chore 等)放入 <details> 折叠块中,<summary> 文本为 "Internal Changes"。
    • 例外:如果 ref、chore 等标记的提交实际包含面向用户的变更,则应放在主 changelog 正文,而非内部变更区。
  • 条目排序:所有条目按字母序排列。
  • 外部贡献者致谢:如果本次发布包含外部贡献者的 PR,在提交列表下方加入一行:
Work in this release contributed by <外部贡献者GitHub用户名列表>. Thank you for your contributions!

注意语法细节:只有一个外部 PR 时用单数 contribution(去掉末尾的 s);三个及以上时使用牛津逗号(Oxford comma),例如 @alice, @bob, and @carol。

外部贡献者行的自动化来源

仓库内置了 .github/workflows/external-contributors.yml(名为 "CI: Mention external contributors"):每当非 COLLABORATOR/MEMBER/OWNER 的外部贡献者 PR 合入 develop 后,该工作流会调用 dev-packages/external-contributor-gh-action 自动把贡献者用户名追加到 CHANGELOG.md 的 ## Unreleased 章节,并创建一个标题为 chore: Add external contributor to CHANGELOG.md 的 PR。发布者在整理 changelog 时可以安全地把这行内容剪切到新版本章节中(不过官方文档也提醒:做一次人工 sanity check 永远不嫌多)。

Changelog 条目示例(来自官方文档)

## 9.28.0

### Important Changes

- **feat(nestjs): Stop creating spans for `TracingInterceptor` ([#16501](https://github.com/getsentry/sentry-javascript/pull/16501))**

With this change we stop creating spans for `TracingInterceptor` as this interceptor only serves as an internal helper and adds noise for the user.

- **feat(node): Update vercel ai spans as per new conventions ([#16497](https://github.com/getsentry/sentry-javascript/pull/16497))**

This feature ships updates to the span names and ops to better match OpenTelemetry. This should make them more easily accessible to the new agents module view we are building.

### Other Changes

- fix(sveltekit): Export `vercelAIIntegration` from `@sentry/node` ([#16496](https://github.com/getsentry/sentry-javascript/pull/16496))

<details>
  <summary> <strong>Internal Changes</strong> </summary>

- ref(node): Split up incoming & outgoing http handling ([#17358](https://github.com/getsentry/sentry-javascript/pull/17358))
- test(node): Enable additionalDependencies in integration runner ([#17361](https://github.com/getsentry/sentry-javascript/pull/17361))

</details>

Work in this release was contributed by @agrattan0820. Thank you for your contribution!

当前仓库的 CHANGELOG.md 顶部即维护着一个 ## Unreleased 章节,其中已经包含 Work in this release was contributed by ... 的致谢行,这正是上述自动化机制的实时产物。

发布背后的 Craft 流水线:.craft.yml 解读

无论是自动发布还是手动发布,真正的发布动作都由 Craft 执行,其配置位于仓库根目录的 .craft.yml。理解这个文件就能知道一次发布会产出什么。关键字段:

  • minVersion: '0.23.1':要求最低 Craft 版本;
  • changelog.policy: simple:changelog 策略为 simple;
  • preReleaseCommand: bash scripts/craft-pre-release.sh:在发布前执行 scripts/craft-pre-release.sh,该脚本调用 yarn install --frozen-lockfile 并通过 scripts/bump-version.js 在所有工作区包中统一 bump 版本号(不创建 git tag 或 commit);
  • targets:发布目标列表,按依赖顺序排列,例如:
    • npm 目标:按依赖层级依次发布 @sentry/core → @sentry/browser-utils → @sentry/browser/@sentry/node → 框架包(@sentry/nextjs、@sentry/nuxt 等),每个目标通过 includeNames 正则匹配 tarball 产物(如 /^sentry-core-\d.*\.tgz$/),确保 @sentry/core 先于依赖它的包发布;
    • aws-lambda-layer:构建并发布 AWS Lambda Layer;
    • gcs:把浏览器 CDN bundle 上传到 GCS bucket sentry-js-sdk 的 /{{version}}/ 路径,并设置一年缓存(cacheControl: 'public, max-age=31536000');
    • github:创建 GitHub Release;
    • registry:更新 Sentry Release Registry 中各 SDK 的版本与(浏览器包的)sha384 checksum。

这也是 docs/new-sdk-release-checklist.md 中所说的"首次发布新 SDK 需在 craft.yml 中为 npm 与 registry 添加新目标"的落点。

发布后的 Gitflow 同步机制

发布完成并不代表流程结束。文档 Step 9 提到"发布完成后会自动触发 master -> develop 的同步"。该行为由 .github/workflows/gitflow-sync-develop.yml 实现:

  • 触发条件:push 到 master 分支,且路径变更涉及 .version.json(Craft 发布时会由 scripts/bump-version.js 更新该文件);也支持手动 workflow_dispatch;
  • 动作:自动创建标题为 [Gitflow] Merge master into develop 的 PR,打上 Dev: Gitflow 标签,然后自动审批(auto-approve)并启用 automerge 以 merge commit 方式合并。

这保证了 develop 能尽快拿到 master 上的版本号更新,避免下一次 prepare-release 分支合入 master 时出现版本文件冲突。如果该同步 PR 因 package.json 冲突而失败,按 docs/gitflow.md 的手动合并方案处理即可。

首次发布新 SDK 的补充检查清单

官方文档在发布流程入口处明确要求:如果这是某个新 SDK 的首次发布,必须先阅读 docs/new-sdk-release-checklist.md。该清单覆盖了发布前的工程准备(包导出模块、单元测试、构建产物、tarball 内容、README.md 与 LICENSE、CI 配置)、发布中的 craft.yml 配置(移除 private: true、设置 publishConfig.access: public、添加 npm 与 registry target),以及发布后的 NPM 与 Release Registry 核验。首次发布者应将其作为发布流程的前置检查项。

常见注意事项与最佳实践小结

  1. 分支名决定自动发布的版本号:prepare-release/<VERSION> 必须严格匹配 .github/workflows/auto-release.yml 中的正则(支持 alpha/beta/rc 预发布后缀),否则版本解析失败、不会触发 Craft。
  2. 合入方式因场景而异:面向 master 的 prepare-release PR 用 Merge Commit;面向旧大版本分支/预发布分支的 changelog PR 用 Squash and Merge,切勿混淆。
  3. 发布期间冻结 package.json 变更:发布窗口内不要向 develop 合入任何 package.json 改动,否则会破坏 master -> develop 的自动同步。
  4. Changelog 保持规范:重要变更进 ### Important Changes、其余用户可见变更进 ### Other Changes、纯内部改动进 <details> 折叠块、条目按字母序排列、外部贡献者行注意单复数与牛津逗号。
  5. 预发布版本:alpha/beta/rc 快照可通过 prepare-release/<VERSION>(自动)或 Release 工作流手动指定 9.7.0-alpha.1 这类带预发布后缀的版本号发布,最终发布的 npm 版本、CDN 路径与 GitHub Release 均由 .craft.yml 中声明的 targets 决定。

以上流程在仓库中的实现载体(.github/workflows/auto-release.yml、.github/workflows/release.yml、.github/workflows/gitflow-sync-develop.yml、.craft.yml、scripts/generate-changelog.ts)均为开源可见,维护者可以据此排查问题或扩展新的发布目标。官方文档同时指出,该流程已被封装为 Claude Code / Cursor 中的 /release skill,可自动化执行上述步骤,但本文所述的手动步骤依然是理解与排查发布问题的基础。

登录后查看全文
sentry-javascript