代码质量门禁与 CI 集成:把 Lint/TypeCheck/Test 变成“可执行的合并规则”
“代码质量”如果只靠口头约定,最终会变成:
- 高手自律、普通人随缘
- 临近发版集中修,成本爆炸
- 代码风格争论消耗协作时间
真正有效的做法是:把质量标准写成可执行的门禁,并且让门禁:
- 对业务有价值(能拦住真实问题)
- 对开发友好(失败原因清晰、能快速修复)
- 对协作友好(噪音低、不折磨人)
本文给你一套可复用的“门禁体系 + CI 工作流”方案,重点放在落地细节。
1. 什么是“门禁”(Quality Gates),它和“规范”有什么区别
- 规范:建议你怎么写
- 门禁:不满足就不能合并
门禁的关键不是“更严格”,而是:
- 把团队的最低质量底线固化下来
- 把问题尽可能前置(PR 阶段解决,而不是上线后)
一个成熟团队通常会有三道核心门禁:
- 静态检查(Lint):拦住明显 bug 与坏味道
- 类型检查(TypeCheck):拦住 TS 类型层面的错误
- 自动化测试(Test):拦住行为回归
2. 门禁标准怎么定:先从“最小可行”开始
门禁失败会影响开发节奏,所以第一版标准必须“可持续”。
2.1 推荐的最小可行门禁(MVP)
- Lint:必须通过(允许少量 legacy 目录豁免)
- TypeCheck:必须通过
- Unit Test:必须通过(先覆盖核心模块/关键流程)
如果你还没有测试体系,建议先把 Lint + TypeCheck 立起来,再逐步补测试。
2.2 让门禁“可维护”的 3 条原则
- 失败信息要可读:一眼知道怎么修
- 修复路径要清晰:本地一条命令能复现
- 噪音要可控:不要因为格式/低价值规则导致频繁失败
3. 本地脚本设计:让开发者“跑得起、修得动”
门禁要成功,必须先把本地体验做好。
建议把脚本按“检查/修复”拆开:
lint:只检查lint:fix:自动修复typecheck:类型检查test:单测
示例(思路为主,按你项目实际替换命令):
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"typecheck": "tsc -p tsconfig.json --noEmit",
"test": "vitest run"
}
}
团队约定:
- 本地提交前优先跑
lint:fix - PR 门禁永远跑
lint(只检查,不改代码)
4. CI 工作流:把门禁做成可重复、可定位的流水线
4.1 GitHub Actions 示例(最小可用)
name: quality
on:
pull_request:
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm typecheck
- run: pnpm test
关键点:
--frozen-lockfile:确保依赖解析可重复- 每一步独立输出:失败更容易定位
4.2 并行化:让 CI 更快
当项目变大后,可以拆成多个 job 并行跑:
- lint job
- typecheck job
- test job
这样单步失败不阻塞其他步骤,也更容易看出瓶颈。
5. Monorepo 的门禁策略:从“全量”走向“按影响范围”
在 monorepo 中,如果每次 PR 都全量跑,很快就会遇到:
- CI 太慢,大家开始绕开门禁
- 失败太多,大家对门禁失去信任
推荐分两阶段:
5.1 第一阶段:先跑通全量(建立基线)
pnpm -r lintpnpm -r typecheckpnpm -r test
先让流程稳定。
5.2 第二阶段:按包过滤(增量门禁)
用 pnpm 的 --filter 精准执行:
- 只跑当前 app:
pnpm --filter landing lint - 修改了共享包时,再跑依赖它的 app
如果仓库规模更大,可以引入任务编排与缓存(例如 Turborepo/Nx),但这属于“增量优化”,不是起步必需。
6. 降噪:门禁失败的“真实成本”来自误报
门禁最容易失败的原因不是 bug,而是:
- 规则过度严格
- 历史债务太多
- 失败信息太难读
实战策略:
6.1 对 legacy 目录做“隔离与渐进收敛”
- 先对新增代码严格
- 旧代码允许临时豁免
- 用“每周清债”逐步降低豁免范围
6.2 把格式化从争论变成自动化
- 本地保存/提交自动格式化
- CI 只检查
这样既统一风格,又避免 CI 改代码。
7. 让门禁真正有效:从“拦住问题”到“推动改进”
成熟的门禁体系会进一步做到:
- 对关键指标做趋势(失败率、平均修复时间)
- 对常见失败原因沉淀 FAQ
- 对质量薄弱模块增加专项测试
当门禁成为团队的“反馈系统”,它就不再是负担。


