首页
/ Storybook PR 维护实战:修复 Lint 与 TypeScript 错误的完整工作流(fix-linting-types-on-pr 技能解析)

Storybook PR 维护实战:修复 Lint 与 TypeScript 错误的完整工作流(fix-linting-types-on-pr 技能解析)

2026-09-05 16:33:41作者:平淮齐Percy

本文以 Storybook 仓库中的 Agent 技能文档 SKILL.md 为主体,完整讲解“在 Pull Request 上检出代码、修复全部 linting 与 TypeScript 错误、再推回远端”的八步标准流程。结合仓库中真实的 npm scripts、Nx 任务定义与类型检查脚本源码,你可以掌握该流程每一步背后的底层机制:为什么必须先编译再检查、yarn lint 实际执行的是什么、yarn nx run-many -t check 如何按包过滤类型诊断。

1. 技能定位:这个 SKILL 解决什么问题

.agents/skills/fix-linting-types-on-pr/SKILL.md 是 Storybook 仓库为 AI Agent 定义的一组可复用工作流之一(同级目录还有 canarydocs-reviewgithub-qa-labelshandle-pr-commentsopen-pr 等技能)。该技能的 frontmatter 明确界定了触发场景:

---
name: fix-linting-types-on-pr
description: Checks out a PR (including fork PRs), fixes all linting and
  TypeScript errors, then pushes the changes back. Use when asked to fix
  lint, types, or TS errors on a PR.
---

一句话概括:检出 PR(包括来自 fork 的 PR)→ 自动修复 linting 和类型问题 → 将修复推回。文档将整个过程拆成 8 个步骤加一组边界性 Notes,本文按原步骤顺序展开,并用仓库源码印证每一步的必要性。

2. Step 1–2:获取 PR 号并检出 PR

  • Step 1:如果用户已经给出 PR 号则直接使用,否则先询问。
  • Step 2:使用 gh pr checkout 检出 PR:
gh pr checkout <PR_NUMBER>

选择 gh pr checkout 而非手动 git fetch + 分支切换的关键原因,是它对 fork 来源的 PR 同样有效:文档明确指出,该命令会自动建立正确的远端跟踪关系并切换到 PR 分支——即使 PR 来自外部贡献者的 fork,后续步骤(尤其是最后一步 git push)才能正确推送回贡献者的源分支,而不是误推到本仓库。

这一点在 Step 8 会得到呼应:正因为 gh pr checkout 设置了正确的 upstream 跟踪,最后才能“直接 git push”。

3. Step 3:安装依赖

yarn

Storybook 是一个大型 Yarn Workspaces 单仓。从根目录 package.json 可以看到:

  • packageManager 固定为 yarn@4.18.0,即必须使用 Yarn 4(Berry);
  • workspaces.packages 覆盖了 code/addons/*code/builders/*code/corecode/frameworks/*code/lib/*code/presets/*code/renderers/*agent-evalscripts 等几十个内部包;
  • postinstall 脚本会执行 husky,在检出分支后重新挂载 Git hooks。

在一个几十个 workspace 包、且 resolutions 中锁定大量版本(如 typescriptreactplaywright)的仓库里,跳过安装直接跑 lint/check 会因缺少内部包产物与类型声明而产生大量假性错误——这正是文档把“安装依赖”放在“修复错误”之前单独一步的原因。

4. Step 4:先编译仓库,再谈检查

yarn nx run-many -t compile

文档给出了一行解释:先编译可以确保 linter 所引用的 TS 声明文件已经存在。这一行在本仓库里有非常具体的对应实现,定义在 nx.jsontargetDefaults.compile 中:

"compile": {
  "dependsOn": ["^compile"],
  "command": "node --disable-warning=MODULE_TYPELESS_PACKAGE_JSON ./scripts/build/build-package.ts --cwd {projectRoot}",
  "cache": true,
  "inputs": ["production", "^production"],
  "outputs": [
    "{projectRoot}/dist",
    "{workspaceRoot}/code/bench/esbuild-metafiles/{projectName}"
  ]
}

从源码结构看有三个要点:

  1. 依赖拓扑先行dependsOn: ["^compile"] 表示每个包会先编译它依赖的其他 workspace 包(^ 表示“被依赖项目”),从而保证跨包引用链上的 dist 产物完整;
  2. 产物落在 {projectRoot}/dist:Storybook 的包之间通过 workspace 互相引用,被引用包的类型入口指向 dist 下编译出的声明文件。若未编译,下游包的类型检查会因找不到声明而报“模块不存在/隐式 any”等假错;
  3. cache: true:compile 结果可被 Nx 缓存,在修复循环中重跑时命中缓存、显著提速。

5. Step 5:修复 linting 错误

yarn lint

这一步对应根目录 package.json 中的 "lint": "cd code; yarn lint",即进入 code/ 目录执行 code/package.json 的 lint 脚本链:

"lint": "yarn lint:js",
"lint:js": "yarn lint:js:cmd . --quiet",
"lint:js:cmd": "oxlint --report-unused-disable-directives-severity=error"

也就是说,Storybook 的 JS/TS linting 由 oxlint(Rust 实现的高速 linter,仓库锁定版本 1.72.0)驱动。其中 --report-unused-disable-directives-severity=error 值得注意:代码中残留的、已经不起作用的 eslint-disable / oxlint-disable 注释本身会被当作错误报出——修复 PR 时如果顺手删掉了触发规则的代码,必须同时清掉失效的 disable 注释,否则 yarn lint 依然不过。

lint 行为的具体规则定义在 code/.oxlintrc.json,它 extends 根目录 .oxlintrc.json,并加载了 local-ruleseslint-plugin-storybookeslint-plugin-playwrighteslint-plugin-compat 等插件。其中的规则对“修 lint 不修逻辑”原则有直接约束,例如:

  • no-restricted-imports 禁止从 react-ariareact-statelyes-toolkit 等包的根入口导入,要求使用具名子模块入口;
  • compat/compat 按 browserslist 目标(chrome ≥ 131、safari ≥ 18.3、node ≥ 20 等,见 code/package.json)检查浏览器 API 兼容性;
  • ignorePatterns 排除了 **/*.vue**/*.sveltestorybook-staticsandbox 等目录。

修复时只处理这些由 linter 报出的问题(错误级别必须清零,warn 级规则如 import/no-named-as-default 可作为参考),不要做超出 lint 范围的重构

6. Step 6:手动修复 TypeScript 错误并循环验证

yarn nx run-many -t check

check 目标同样定义在 nx.json

"check": {
  "dependsOn": [{ "projects": ["*"], "target": "compile" }],
  "command": "yarn exec jiti ./scripts/check/check-package.ts --cwd {projectRoot}",
  "cache": true,
  "inputs": ["default", "^production"],
  "configurations": { "production": {} }
}

两个细节印证了“先 compile 再 check”的必然性:dependsOn 声明了所有项目的 compile 都先于 check 执行cache: true 使类型检查结果可缓存。

真正执行检查的脚本是 scripts/check/check-package.ts,阅读源码可以看到它的完整行为契约:

  • 对每个含 tsconfig.json 的包,以 原生 tsctypescript-native)执行 tsc --project tsconfig.json --noEmit --pretty falsecheck-package.ts#L34-L44);
  • 设置了 10 分钟超时与 64MB 输出缓冲,超时/被信号终止时明确区分“编译器挂死或崩溃”与“类型错误”,避免把环境问题误当类型问题去修(check-package.ts#L46-L63);
  • 最关键的是按包过滤诊断:通过 scripts/check/utils/typescript.ts 中的 filterToPackageDiagnostics,只有落在被检查包自身目录内的诊断才会使其 check 失败,其他 workspace 包引入的诊断被忽略——因此 run-many 并发跑全部包时,每个包的报错都可以精确归因到具体目录,修复时可以直接定位文件。

文档列出的常见类型错误修复手法(逐条人工编辑、而非盲改):

  • 添加或修正类型标注(type annotations);
  • 修正错误的泛型(generics)用法;
  • 解决违反 strict mode 的 any 赋值;
  • 补齐缺失的 import 或 re-export。

每修完一批编辑就重跑一次 yarn nx run-many -t check,确认错误确实消除再继续。由于 check 有缓存且按包并发,这个“小批量—重跑”的循环在几十个包的仓库里是控制错误面、避免引入新类型错误的实用策略。

7. Step 7–8:只提交改动的文件并推回

git add <files-you-modified>
git commit -m "Maintenance: Fix linting and TypeScript errors"
  • 严禁 git add -A:PR 分支上可能残留无关的未跟踪文件,全量暂存会把它们误提交进贡献者的 PR;
  • 提交信息统一使用 Maintenance: Fix linting and TypeScript errors 这类维护型文案,与 PR 的功能变更在 changelog 语义上区分开(仓库的 pr-log 配置将 maintenance 标签映射为 “Maintenance” 分区,见 code/package.jsonpr-log.validLabels)。
git push

对 fork PR,gh pr checkout 已设置好指向贡献者远端分支的 upstream,直接 git push 即可把修复叠加到 PR 分支上,维护者无需在本地重新发起 PR。

8. Notes:边界条件与升级人工确认的时机

文档末尾 Notes 定义了这套流程的安全边界,全部是“什么情况下不该继续自动修”的判断准则:

  1. 只修明确的 linting / TypeScript 问题,不重构逻辑——保持 diff 最小、可审查;
  2. 若某个类型错误需要非平凡的代码改动(例如要改公共 API 签名),必须先向用户(维护者)说明并请求确认,而不是擅自改;
  3. gh pr checkout 因 fork 权限失败,应告知用户:可能需要贡献者授予 fork 写权限,或由维护者直接向其分支推送;
  4. 推送后需与维护者确认 CI 已变绿,流程才算闭环。

这条 CI 闭环与仓库的 CI 检查链是一一对应的:code/package.jsonci-tests 脚本为

yarn task --task check --no-link --start-from=install && yarn lint && cd .. && yarn test

即“check(含全量 compile 依赖)→ lint → 单测”三段式。本技能在 PR 分支上把前两段(check 依赖的 compile、lint)完整重放了一遍,再推回触发 CI 验证,因此推送后 CI 的主要风险只剩下第三方 flaky 用例——这也是第 4 条 Notes 要求人工确认的原因。

9. 流程小结:可复制的八步检查单

步骤 命令 / 动作 仓库内对应实现
1 确认 PR 号(用户给出或询问)
2 gh pr checkout <PR_NUMBER> 兼容 fork PR,建立正确 upstream
3 yarn Yarn 4.18.0 workspaces,postinstall: husky
4 yarn nx run-many -t compile nx.json compile 目标:dependsOn: ["^compile"],产物 {projectRoot}/dist
5 yarn lint code/ 下 oxlint 1.72.0,规则见 code/.oxlintrc.json
6 yarn nx run-many -t check + 人工修类型 + 循环重跑 scripts/check/check-package.ts:原生 tsc --noEmit,按包过滤诊断
7 git add <files-you-modified> + git commit 禁用 git add -A
8 git push,并确认 CI 变绿 对应 ci-tests:check → lint → test

这套流程的价值在于:它把“修 PR 上的 lint/类型问题”这件高频维护工作压缩成了可预测、可缓存、可归因的机械步骤——编译保证声明产物存在,oxlint 与按包过滤的 tsc 保证错误精确定位,最小化暂存与 fork 权限处理保证了操作不会伤及 PR 分支上的他人改动。

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

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384