首页
/ Storybook 规范化 PR 实战:标题格式、Category/CI/QA 三类标签体系与 Draft PR 工作流

Storybook 规范化 PR 实战:标题格式、Category/CI/QA 三类标签体系与 Draft PR 工作流

2026-09-06 11:55:34作者:咎岭娴Homer

本文基于 Storybook 仓库中的 PR 创建技能文档(.claude/skills/pr/SKILL.md 指向 pr/SKILL.md)及其配套的 PR 模板(.github/PULL_REQUEST_TEMPLATE.md),完整拆解 Storybook 社区提交 Pull Request 的规范:[Area]: [Description] 标题约定、Category / CI / QA 三组标签的选择规则、必须"逐字复制"的 PR 正文模板与手工测试(Manual testing)要求,以及 gh pr create 的 Draft 提交命令。读完你可以按 Storybook 维护者的标准流程,写出一个能正确触发沙箱 CI、满足发版 QA 要求的规范 PR。

技能定位:为 Agent 与贡献者定义的 PR 规范

.claude/skills/pr/SKILL.md 本身只有一行指针内容:

@../../../.agents/skills/pr/SKILL.md

即 Claude 侧的技能文件直接引用了 pr/SKILL.md,其 Frontmatter 声明了技能的使用时机与允许的工具:

name: pr
description: Creates a pull request following Storybook conventions. Use when creating PRs, opening pull requests, or submitting changes for review.
allowed-tools: Bash, Read

从仓库结构看,这是一套面向 AI Agent 的"技能(skill)"体系,pr 技能定义了 PR 的核心规范,周围还有若干协作技能:

pr 技能是这一族技能中"规范本体"——例如 open-pr 技能明确写道:"Title: [Area]: [Description] — see the pr skill for format and examples."。下面按原技能文档的四个部分(Title format、Labels、PR body、Command)逐一展开。

PR 标题格式:[Area]: [Description]

技能文档对标题的约定非常严格:

[Area]: [Description]
  • Area 首字母大写,且不含空格(允许使用连字符)
  • 官方给出的示例:
    • CSFFactories: Fix type export
    • Nextjs-Vite: Add support
    • CLI: Fix automigrate issue

Area 对应的是仓库内的功能域(如 CSF Factories、Nextjs-Vite 框架适配器、CLI 等),Description 用一句话概括改动意图。这种格式的实战价值在于:标题前缀让维护者在 PR 列表里即可按模块过滤问题,也便于 changelog 聚合与检索。

标签体系:Category / CI / QA 三组标签各选其一

Storybook 要求每个 PR 必须打上三组标签,每组只选一个。这对应了模板中 "Checklist for Maintainers" 的要求:PR 必须包含其中一个类别标签,并通过 ci:* 标签声明要跑哪套沙箱,通过 qa:* 标签声明发版期是否需要人工 QA。

Category(必填,9 选 1)

标签 含义 是否进入 changelog
bug 修复错误行为
maintenance 面向用户的维护性改动
dependencies 升级/降级依赖
build 内部构建/测试工具更新
cleanup 小型代码清理
documentation 纯文档改动
feature request 新功能
BREAKING CHANGE 破坏兼容性
other 以上均不适用

其中 build / cleanup / documentation 三类的共同特征是"不出现在发布 changelog 中"——这一信息直接来自 PULL_REQUEST_TEMPLATE.md 的 Available labels 折叠区,技能文档与其逐字对应。

CI(必填,选 1)

标签 含义
ci:normal 标准沙箱集合,绝大多数代码改动的默认选择
ci:merged 合并后的更大沙箱集合
ci:daily 每日沙箱集合;当改动影响 prerelease 沙箱、或钉在较旧框架/React 版本的沙箱时使用
ci:docs 纯文档改动(配合 documentation 类别使用)

这组标签不是凭空设定的,它与仓库源码直接挂钩。PR 模板的 Maintainers 检查项写明:

make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

sandbox-templates.ts 中可以看到三套集合的真实定义:

export const normal: TemplateKey[] = [ ... ]        // L1251

export const merged: TemplateKey[] = [              // L1283
  ...normal, ...
]

export const daily: TemplateKey[] = [               // L1295
  ...merged, ...
]

export const templatesByCadence = { normal, merged, daily };  // L1320

从源码结构看,三套集合是逐层包含关系merged 展开 normaldaily 再展开 merged),因此"默认 ci:normal、影响面扩大到 prerelease/旧框架版本沙箱时升级到 ci:daily"的规则与源码中集合的嵌套设计完全吻合。

QA(必填,选 1):qa:needed / qa:skip

这两个标签告诉发版团队在下一个 minor 版本发布前是否需要针对该 PR 做人工 QA:

  • qa:needed — 发布前必须有人工验证;
  • qa:skip — 无需逐 PR 人工 QA。

技能文档给出了一套明确的启发式判断规则(这是该规范中最具经验价值的部分):

  • 用户明确要求发版前人工 QA → qa:needed
  • 属于一个整体 QA 的大项目的一部分(不按 PR 逐个验证)→ qa:skip
  • 触碰路径处理、文件系统、或任何在 Windows 上可能出问题的代码 → qa:needed
  • 横跨多个模块、必须协同工作的复杂改动 → qa:needed
  • 位于中心/共享代码、高副作用风险的小改动(例如共享 UI 的布局 CSS)→ qa:needed
  • 简单直接的小改动 → qa:skip
  • 拿不准 → 直接询问用户是否需要发版前人工 QA

PR 正文:逐字复制模板,保留全部 HTML 注释

技能文档对 PR body 的要求只有一句话,但执行细节很关键:

Read .github/PULL_REQUEST_TEMPLATE.md from the repository root. Copy that template EXACTLY, including all HTML comments (<!-- ... -->). Fill in the relevant sections based on the changes, but keep all comments intact.

也就是说,正文必须基于 .github/PULL_REQUEST_TEMPLATE.md 原样复制,包括所有 HTML 注释占位,然后只填写对应小节。该模板的完整骨架如下:

Closes #

<!-- If your PR is related to an issue, provide the number(s) above; ... -->

## What I did

<!-- Briefly describe what your PR does -->

## Checklist for Contributors

### Testing

#### The changes in this PR are covered in the following automated tests:

- [ ] stories
- [ ] unit tests
- [ ] integration tests
- [ ] end-to-end tests

#### Manual testing

> [!CAUTION]
> This section is mandatory for all contributions. ...

### Documentation

- [ ] Add or update documentation reflecting your changes
- [ ] If you are deprecating/removing a feature, make sure to update MIGRATION.MD

## Checklist for Maintainers

- [ ] ... add `ci:normal`, `ci:merged` or `ci:daily` GH label ...
- [ ] Declare whether manual QA will be needed ... through `qa:needed` or `qa:skip`
- [ ] Make sure this PR contains **one** of the labels below: ...

### 🦋 Canary release

<!-- CANARY_RELEASE_SECTION -->
...
<!-- CANARY_RELEASE_SECTION -->

<!-- BENCHMARK_SECTION -->
<!-- BENCHMARK_SECTION -->

几个填写要点:

  1. Closes # 开头:关联 issue 编号,多个 issue 用 "closes #1000, closes #1001" 分开写;
  2. 模板注明所有 PR 提交到 next 分支(除非仅针对当前发布分支)——维护者会在发版流程中把 bug 与文档修复 cherry-pick 进 main,贡献者不必操心;
  3. 自动测试勾选:在 stories / unit / integration / end-to-end 四个复选框上勾选实际覆盖的类型;
  4. Documentation 小节:若改动涉及文档更新、或废弃/移除功能需同步 MIGRATION.md,则勾选对应项;
  5. Maintainers 检查项保持不勾选ci:*qa:* 和类别标签是通过 PR 标签体现的,模板中的维护者检查框留给维护者操作(配套的 update-pr-description/SKILL.md 也要求"更新复选框状态时不要删除 canary release 小节")。

Manual testing:必填项,写给另一位维护者看

技能文档对 Manual testing 小节的要求最为具体:

  • 必填,绝不允许留空。模板中甚至用 > [!CAUTION] 强调:"This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly."
  • 写给另一位维护者看,而不是记录你自己是怎么测的。模板注释原文:"Do not describe how YOU tested the PR code, but how a separate maintainer should do so."
  • 每一步应当:
    • 清晰、易跟随;
    • 尽量给出可直接复制粘贴的 shell 命令;
    • 明确说明要检查的预期行为(而不是"check it works"这种空话);
    • UI 改动要链接到具体的 story;
    • 列出最可能回归、值得重点关注的区域。
  • 先自己跑一遍这些步骤("Verify your own steps first — run through them locally before opening the PR")。

模板注释中给的标准示例风格:

1. Run a sandbox for template, e.g. `yarn task --task sandbox --start-from auto --template react-vite/default-ts`
2. Open Storybook in your browser
3. Access X story

附:Chromatic 预览链接格式

需要展示 UI 效果时,可以在 CI 完成后链接已发布的 Chromatic Storybook(技能文档特别提示:CI 跑完之前链接不可用,PR 刚打开时不要急着贴)。两种常用入口的 URL 模板:

  • 内部 UI(Internal UI): https://<branch>--635781f3500dd2c49e189caf.chromatic.com/?path=/story/<story_id>
  • React Vite TS 沙箱: https://<branch>--630511d655df72125520f051.chromatic.com/?path=/story/<story_id>

其中 <branch> 要替换为 Chromatic 归一化后的 slug(特殊字符替换为连字符,如 feature/foofeature-foo),<story_id> 为 story 路径(如 example-button--primary)。

关于 635781f3500dd2c49e189caf 这个内部 UI 项目 ID,可以从仓库中印证:code/chromatic.config.json 里声明了 "projectId": "Project:635781f3500dd2c49e189caf",与技能文档中的链接前缀一致。

提交命令:始终以 Draft 模式创建 PR

规范的最后一步是命令本身——PR 必须始终以 draft 模式创建

gh pr create --draft --title "<Area>: <Description>" --body "<FILLED_TEMPLATE>" --label "<category>,<ci>,<qa>"

其中 <FILLED_TEMPLATE> 是上文"逐字复制并填写"后的模板内容,--label 的值是三组标签各选一项、以英文逗号拼接(如 bug,ci:normal,qa:skip)。配套的 open-pr/SKILL.md 给出了等价的完整工作流版本:先 git fetch origin 并运行 detect-base-branch.sh 探测 base 分支(支持栈式 PR,回退到 next),再用 heredoc 方式传多行 body、追加 --base--assignee @me

gh pr create \
  --draft \
  --base "<detected-base>" \
  --title "<Area>: <Description>" \
  --body "$(cat <<'EOF'
<FILLED_TEMPLATE>
EOF
)" \
  --assignee @me \
  --label "<type>,<ci>,<qa>"

PR 创建后,open-pr 技能还会询问是否需要触发 canary 发布;canary/SKILL.md 说明了触发方式(gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>)及 canary 版本号的预测格式 0.0.0-pr-<PR_NUMBER>-sha-<SHORT_SHA>——这与 PR 模板中 "🦋 Canary release" 小节的说明一致。

速查清单

  1. 标题[Area]: [Description],Area 首字母大写、无空格(连字符可用);
  2. 类别标签(9 选 1):bug / maintenance / dependencies / build / cleanup / documentation / feature request / BREAKING CHANGE / other,注意 buildcleanupdocumentation 不进 changelog;
  3. CI 标签(1 选 1):默认 ci:normal;影响 prerelease 或钉住旧框架/React 版本的沙箱用 ci:daily;纯文档用 ci:docs。对应沙箱集合定义见 sandbox-templates.ts
  4. QA 标签(1 选 1):按"路径/文件系统/Windows 风险、跨模块复杂改动、共享代码高副作用 → qa:needed;简单改动、整体 QA 的大项目 → qa:skip"判断,拿不准就问用户;
  5. 正文:从 .github/PULL_REQUEST_TEMPLATE.md 逐字复制(含 HTML 注释),勾选自动测试类型,Manual testing 必填且写给别的维护者,自己先跑通一遍;
  6. 命令gh pr create --draft --title ... --body ... --label "<category>,<ci>,<qa>",永远 draft 起步;
  7. 目标分支:提交到 next 分支(除非仅针对当前发布)。

这套规范的本质,是把"CI 触发策略、changelog 归类、发版 QA 排期"三个发版流程关注点前移到了 PR 创建时刻——贡献者打的三个标签,恰好就是后续 CI 选择沙箱集合、release 流程筛选 changelog 条目、QA 团队排定人工验证任务的直接输入。

登录后查看全文
热门项目推荐
相关项目推荐