Polaris React 仓库发布全流程指南:Snapshot 快照、Changesets 版本发布与 Style Guide 部署
Polaris React 仓库发布全流程指南:Snapshot 快照、Changesets 版本发布与 Style Guide 部署
本文以 Polaris React 仓库的 Releasing 文档 为核心,系统讲解该 monorepo 的两条发布主线:面向「测试中的功能分支」的 Snapshot 快照发布(/snapit 命令),以及面向正式版本的 Changesets 版本发布(含 beta 预发布分支);同时覆盖 polaris-for-vscode 扩展与 polaris.shopify.com 风格指南站点的自动部署机制。读完本文,你将掌握从"提交一个 changeset"到"把新版本发布到 npm、并完成下游 Shopify/web 升级"的完整链路,以及如何在发布前用快照包在真实项目中做验证(tophatting)。
一、发布体系总览
Polaris 是一个由 npm 包、VS Code 扩展和站点组成的 monorepo,其根目录 package.json 中以 pnpm + turbo 管理全部工作区。整个发布体系可以归纳为三条自动化流水线:
| 流水线 | 触发方式 | 产物 | 对应工作流 |
|---|---|---|---|
| Snapshot 发布 | PR 评论 /snapit |
0.0.0-snapshot-release-<时间戳> 形式的临时 npm 包 |
.github/workflows/snapit.yml |
| 正式版本发布 | main / next 分支 push |
常规 semver 版本(含 beta dist tag) |
.github/workflows/release.yml |
| VS Code 扩展发布 | polaris-for-vscode CHANGELOG 变更 |
Visual Studio Marketplace 扩展 | .github/workflows/release-vscode.yml |
| 风格指南站点部署 | polaris.shopify.com/** 合入 main |
polaris.shopify.com 站点 | .github/workflows/deploy-polaris.shopify.com.yml |
三条流水线共享同一套前置设施:changeset 变更集 是版本发布的"货币",任何需要版本 bump 的改动都必须先通过 pnpm changeset 记录。下文先从最轻量的 Snapshot 发布讲起。
二、Snapshot 快照发布:无需发版即可在消费方项目中验证改动
2.1 什么是 Snapshot 发布
Snapshot release 是一种在不发布新正式版本的前提下,把分支上的改动打包发布到 npm、供消费方项目安装验证的机制。它非常适合发布前的 tophat 验证:例如在发布新 @shopify/polaris 版本前,先在 Shopify/web 的升级分支里安装快照包,确认 UI 表现符合预期。
从仓库文档与源码看,发起 Snapshot 需要满足两个前提条件:
- CI 在功能分支上通过——保证快照包构建自一个可用的代码状态;
- 功能分支上至少有一个待处理的 changeset——changeset 用于声明哪些包需要被打包进快照(对应 CONTRIBUTING.md 的 adding-a-changeset 章节)。
2.2 使用方法:/snapit 斜杠命令
在满足上述条件的功能分支 PR 中,直接添加一条评论:
/snapit
其后的执行链路由 .github/workflows/snapit.yml 驱动,该工作流监听 issue_comment 的 created 事件,核心步骤是:
- name: Create snapshot
uses: Shopify/snapit@v0.0.14
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
with:
build_script: pnpm build:release
可以看到,SnapIt action 会先执行根目录脚本 pnpm build:release(即 turbo run build --filter='!polaris.shopify.com',构建除站点外的全部包),再基于当前 PR 的 changeset 生成快照版本并发布到 npm。整个流程中:
github-actionsbot 会在工作流开始运行时对你的评论回复 👀;- 构建完成后回复 🚀,并贴出下一次正式版本发布中会包含的每个 npm 包的快照安装命令(如
pnpm add @shopify/polaris@0.0.0-snapshot-release-20220525184558,该格式示例见 CONTRIBUTING.md 的 Testing 章节)。
快照版本号通常形如 0.0.0-snapshot-release-<时间戳>,与正式 semver 完全隔离,不会污染正式版本序列。
2.3 polaris-for-vscode 的快照
polaris-for-vscode 扩展本身发布到 Visual Studio Marketplace,它的发布不依赖 /snapit,而是由 .github/workflows/release-vscode.yml 在 polaris-for-vscode/CHANGELOG.md 或 polaris-tokens/CHANGELOG.md 发生变更并合入 main 时自动触发:
on:
push:
paths:
- 'polaris-for-vscode/CHANGELOG.md'
- 'polaris-tokens/CHANGELOG.md'
branches:
- main
工作流依次执行 pnpm install --frozen-lockfile、pnpm build --filter=polaris-for-vscode 构建扩展,最后以 pnpm --filter=polaris-for-vscode vsce publish 配合 VSCE_PAT 密钥发布到 Marketplace。这意味着:只要在发布流程中为扩展生成了 CHANGELOG 条目,其发布就是全自动的,无需人工干预。
三、Version Releases:基于 Changesets 的正式版本发布
3.1 Changesets 机制与 GitHub Action 的职责
Polaris 使用 Changesets 处理仓库内各包的版本发布。整体编排由官方 changesets/action 完成,其职责在 Releasing 文档 中被明确为四件事:
- 创建
changeset-release/main分支,并打开一个标题为 "[Version Packages]" 的 PR,该 PR 始终保持changeset version的一次最新运行结果; - 每当有 PR 合入
main,就把changeset-release/main分支更新到最新; - 当
changeset-release/main分支合入main时执行正式发布; - 发布完成后重建
changeset-release/main分支,并再次打开新的 "[Version Packages]" PR,为下一轮发布做准备。
这个"发布即重建"的设计保证了 main 分支随时处于可发布状态——每次发布结束,新的版本 PR 已经就位,只等下一批 changeset 积累。
3.2 工作流源码佐证:release.yml 与根脚本
正式发布由 .github/workflows/release.yml 承载。其关键配置如下:
on:
push:
branches:
- main
workflow_dispatch:
inputs:
branch:
description: 'Branch to release from'
required: true
default: 'main'
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
id-token: write
steps:
# ... checkout / pnpm 安装 / 构建 ...
- name: Build
run: pnpm build:release
- name: Create release Pull Request or publish to NPM
id: changesets
uses: changesets/action@v1.5.3
with:
version: pnpm version-packages
publish: pnpm release-packages
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_CONFIG_PROVENANCE: true
该工作流把两个关键命令委托给根 package.json 中的脚本:
| 脚本 | 实际执行内容 | 作用 |
|---|---|---|
version-packages |
changeset version && pnpm install --lockfile-only |
依据 changeset 提升各包版本号、生成 CHANGELOG,并同步 lockfile |
release-packages |
pnpm build:release && changeset publish |
重新构建全部发布包后,将新版本发布到 npm |
其中 NPM_CONFIG_PROVENANCE: true 启用了 npm 的 provenance 签名(配合 id-token: write 权限),用于在 npm 上记录包的构建来源;workflow_dispatch 输入项 branch 允许手动指定从哪个分支发起发布,默认 main。
另外,.changeset/config.json 中的关键配置也值得关注:
{
"changelog": ["@changesets/changelog-github", {"repo": "Shopify/polaris"}],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
"updateInternalDependents": "always"
}
}
access: public:包以公共可见方式发布到 npm;changelog使用@changesets/changelog-github,自动把 PR 链接与贡献者写进 CHANGELOG;updateInternalDependents: always:仓库内部包相互依赖时,发布后依赖方也总会得到更新,避免出现"新包配旧依赖"的版本错位。
3.3 创建 changeset:版本发布的起点
任何需要发布的功能分支都必须携带 changeset。在 .changeset/README.md 中给出了交互式创建流程,从功能分支运行:
pnpm changeset
依次回答 CLI 的三个问题:
🦋 Which packages would you like to include?——用Space键选中发生变更的包,Enter进入下一题;🦋 Which packages should have a major bump?——如有破坏性变更则用方向键与Space选中这些包,否则直接Enter;🦋 Which packages should have a minor bump?——同理选择 minor 包,不选择则默认按 patch 处理。
最后为这次变更填写 changelog 摘要。写 changelog 时遵循 CONTRIBUTING.md 的写作建议:使用积极、对话式的语气,避免冗余,使用 sentence case 与平实的语言;polaris.shopify.com、开发依赖升级、基础设施类 chore 通常可以省略。
仓库还在 CI 层面强制校验 changeset:.github/workflows/changelog.yml 会在每个 PR 上执行 npx @changesets/cli status --since="origin/main",只要 PR 中缺少 changeset 就会检查失败(dependabot 机器人、changeset-release 分支以及带有 🤖Skip Changelog 标签的 PR 除外)。
3.4 语义化版本:什么改动 bump 什么版本
CONTRIBUTING.md 的 Semantic versioning 章节 明确了 Polaris 包的版本规则,发布与 changeset 的 bump 选择均以此为准:
- Major(破坏性):移除组件、移除组件 prop、改变 prop 接受的类型、对依赖最低版本做破坏性升级、对公开 Sass 变量/函数/mixin 做破坏性变更;
- Minor(新功能):新增组件、新增 prop、prop 增加可接受类型、对组件/公开 Sass API 引入弃用警告(为下一个 major 版本铺路);
- Patch(修复):改变组件生成的 HTML(含类名增删改)这类表面变更、不触及公开 API 的改动、非破坏性的依赖最低版本升级、私有 Sass API 的破坏性变更。
这也是为什么破坏性改动应当走 next 分支、而 main 分支只接受非破坏性改动(详见 CONTRIBUTING.md 的 Breaking changes 章节)。
四、Prerelease(beta):为下一个大版本准备的预发布分支
正式发布之外,Polaris 通过 next 分支承载下一个大版本的预发布(prerelease)。机制上与常规 Changesets 发布一致:合并到 next 分支的含 changeset 的工作,会自动生成标题为 "[Version Packages (beta)]" 的预发布 PR,其中包含将进入下一个大版本的全部改动;将该 PR 合入 next 后,会以 beta dist tag 创建一个新的预发布版本。
如果当前仓库中还不存在 next 分支,按如下步骤建立预发布分支(源自 Releasing 文档 的 Prerelease 章节):
-
创建新的
next分支用于预发布开发; -
运行
pnpm changeset pre enter beta,让 changeset 进入 beta 预发布模式; -
调整发布工作流 .github/workflows/release.yml,使其同时监听
main与next两个分支:on: push: branches: - main - next -
后续功能开发从
next分支拉取分支进行; -
在
next分支上正常创建 changeset 并合并; -
此时发布 PR 就会自动为预发布分支生成,预发布流水线即告就绪。
值得注意的细节:正式发布的 release.yml 默认只监听 main;预发布流程要求你手动把 next 加进 on.push.branches 列表,这正是文档示例中给出的配置片段。而 pnpm changeset pre enter beta 会在 .changeset 目录中写入预发布状态文件,使后续合并的 changeset 统一按 beta 预发布处理。
五、执行一次正式版本发布的完整步骤
5.1 谁可以发布
按仓库文档说明,任何 Shopify 成员都可以执行版本发布;需要支持时可联系 GitHub 上的 @Shopify/polaris-team 或 Slack 频道 #polaris 中的 @polaris-developers 团队。
5.2 步骤 1:🧪 测试 "[Version Packages]" PR
正式发布前的第一道闸门是用快照验证待发布内容:
- 对当前打开的 "Version Packages]" PR 创建一次 [Snapshot 发布(即在其中评论
/snapit,前提是该 PR 已包含至少一个 changeset); - 在
Shopify/web的 Spinstance 中新建分支,将@shopify/polaris升级到对应的快照版本(形如pnpm add @shopify/polaris@0.0.0-snapshot-release-<时间戳>),用于人工 tophat 验证。
这一步把"即将发布的代码"与"正式发布"解耦:快照包验证通过后,才进入正式发布环节。
5.3 步骤 2:🚢 发布新版本
- 确认
Shopify/web升级分支 CI 通过后,批准并合并 "[Version Packages]" PR; - 合并动作会触发 release.yml 工作流,执行
changeset publish把各包发布到 npm。
5.4 步骤 3:🕸️ 在 Shopify/web 中升级 @shopify/polaris
为 Shopify/web 的升级分支起草 PR,PR 中需要包含:
- "[Version Packages]" PR 的链接;
- 需要 tophat 的关键事项的简要说明(Tl;dr);
- Spinstance URL;
Key dependencies与Polaris两个标签;- 将 "[Version Packages]" PR 描述中列出的贡献者添加为 reviewers。
随后,等新版本在 npm 上可用后,在 Shopify/web 升级 PR 中安装新版本 @shopify/polaris;最后把升级 PR 链接发到群 Slack DM,请贡献者在 Spinstance 中 tophat 各自的改动、标记回归问题或直接批准 PR。
5.5 步骤 4:🚀 升级 Shopify/shopify-frontend-template-react
在 Shopify/web 升级确认无误后,同步把 @shopify/polaris 升级到 shopify-frontend-template-react 模板仓库,保证新建的 Shopify 应用开箱即可使用最新版 Polaris。
5.6 步骤 5 与 6:🦄 致谢贡献者并公告
- 为本次发布的贡献者送出 Unicorn(内部致谢文化);
- 在 #polaris Slack 频道以及 Workplace 的 Polaris Updates / Engineering 群组中公告新版本,并分享 Unicorn。
整个发布流程体现了"自动化产出、人工把关验证、全链路追踪"的工程实践:Changesets 负责自动生成版本与 CHANGELOG,Shopify/web 的升级验证把发布风险拦截在上游消费方。
六、Style Guide 自动部署
风格指南站点 polaris.shopify.com 采用"改动即部署"的策略:当 /polaris.shopify.com 目录下的新改动合入 main 分支时,站点会自动部署。
底层由 .github/workflows/deploy-polaris.shopify.com.yml 实现。该工作流监听 main 分支且路径过滤为 polaris.shopify.com/**,并在部署前用 GitHub Actions 的 workflow_dispatch API 调用另一个仓库 polaris-site-prod-kit 中的 build-and-deploy.yml 工作流:
on:
push:
branches:
- main
paths:
- 'polaris.shopify.com/**'
# ...
script: |
await github.rest.actions.createWorkflowDispatch({
owner: "shopify",
repo: "polaris-site-prod-kit",
workflow_id: "build-and-deploy.yml",
ref: "${{ inputs.branch || 'main' }}",
});
即:本仓库负责"感知变更并下发指令",站点构建与上线则由独立的 polaris-site-prod-kit 仓库执行。这样的解耦让文档站点发布与 npm 包发布完全互不阻塞——修改 polaris.shopify.com 下的内容(如 content 目录 中的 MDX 文档、pages 目录 中的示例页面)不会触碰任何 npm 包版本。
七、常见问题与排查要点
/snapit评论发出后没有反应? 检查功能分支 CI 是否通过、是否存在至少一个 pending changeset(changelog.yml 的 CI 检查会直接给出缺失提示);SnapIt action 需要仓库配置NPM_TOKEN与GITHUB_TOKEN密钥。- 快照包安装后不是最新代码? 快照基于 PR 当前 head 构建,推送新提交后需重新评论
/snapit生成新快照(参考 CONTRIBUTING.md 的 Testing 章节)。 - 发布后 npm 上找不到新版本? 确认 "[Version Packages]" PR 已合入
main,且 release.yml 中的NPM_TOKEN有效;若从next分支发布,还需确认该分支已加入工作流的branches列表且执行过pnpm changeset pre enter beta。 - 破坏了 CHANGELOG 检查? 任何改动包版本的 PR 都要运行
pnpm changeset并遵循 changelog 写作规范;纯站点改动(polaris.shopify.com)可省略。
结语
从 pnpm changeset 记录一次变更,到 /snapit 生成可验证的快照,再到 Changesets 自动产出 "[Version Packages]" PR、合并即触发 npm 发布,最后在 Shopify/web 与模板仓库中完成下游升级——Polaris 的发布体系把"人类判断"集中在最有价值的两个节点:快照验证(tophat) 与 合并发布 PR,其余环节全部交给 release.yml、snapit.yml 等自动化工作流。这套基于 Changesets + GitHub Actions 的发布模式,配合语义化版本规则与 beta 预发布分支,为多包 monorepo 的持续发布提供了一套完整可复用的工程范式。