Pre-commit Hook 完整流水线 · .husky/pre-commit · 更新于 2026-02-08
每次 git commit 时,Husky pre-commit hook 会依次执行以下 6 个检查步骤。任一步骤失败(exit 1)将阻断 commit。
shared/errors/ 有变更时触发。验证错误码唯一性、HTTP 状态码映射正确性,并自动更新错误码文档。git diff --cached --name-only | grep "shared/errors/".ts/.tsx/.js 文件变更时触发。扫描硬编码的中文字符串,要求使用 next-intl 的 useTranslations()。支持白名单豁免。git diff --cached --name-only | grep "^frontend/.*\.(ts|tsx|js)$"scripts/i18n-whitelist.json
.js 文件变更时触发。扫描 throw new Error()、硬编码 res.status(4xx/5xx) 等应迁移到统一错误码系统的模式。CI 模式忽略注释中的代码。git diff --cached --name-only | grep "^backend/.*\.js$"backend/api/, backend/services/, backend/auth/, backend/jobs/
阈值由各子项目的 jest.config.js 中 coverageThreshold 字段控制。Jest 内置机制:低于阈值时进程以非零码退出。
| 项目 | 配置文件 | Branches | Functions | Lines | Statements |
|---|---|---|---|---|---|
| 后端 (Backend) | backend/jest.config.js |
60% | 60% | 60% | 60% |
| 前端 (Frontend) | frontend/web_app/jest.config.js |
70% | 70% | 70% | 70% |
| 项目 | 包含 | 排除 |
|---|---|---|
| 后端 | api/**/*.js, auth/**/*.js, services/**/*.js, database/**/*.js |
database/migrations/**, node_modules, logs, uploads |
| 前端 | src/**/*.{js,jsx,ts,tsx} |
*.d.ts, types/**, layout.tsx, loading.tsx, error.tsx, not-found.tsx |
SKIP_COVERAGE=1 git commit -m "wip: work in progress"
只跳过第 6 步覆盖率检查,前 5 步(语法、错误码、i18n、审计、lint)仍然执行。适合开发中的 WIP commit。
git commit --no-verify -m "hotfix: emergency"
跳过整个 pre-commit hook。仅限紧急情况使用。
覆盖率门禁的目的是确保每次提交不会引入未测试的代码。频繁使用 SKIP_COVERAGE=1 会导致技术债积累。如果发现经常需要跳过,应该反思是否需要补充测试。
| 用途 | 文件路径 |
|---|---|
| Pre-commit Hook 主文件 | .husky/pre-commit |
| Husky 配置 | .husky/_/husky.sh |
| 语法检查脚本 | scripts/tools/check-syntax.js |
| 错误码验证 | scripts/validate-error-codes.js |
| 错误码文档生成 | scripts/generate-error-docs.js |
| i18n 检查脚本 | scripts/check-i18n.js |
| i18n 白名单 | scripts/i18n-whitelist.json |
| 错误使用审计 | scripts/audit-error-usage.js |
| lint-staged 配置 | package.json (lint-staged 字段) |
| 后端 Jest 配置 | backend/jest.config.js |
| 前端 Jest 配置 | frontend/web_app/jest.config.js |
每一步都有对应的 emoji 前缀输出。查看终端输出中最后一个 emoji 标记即可定位:
🔍 → 语法错误🔢 → 错误码定义问题🌐 → 国际化硬编码🔴 → 错误码使用不规范📝 → ESLint / Prettier 格式问题📊 → 覆盖率不达标完整覆盖率检查需要 2-5 分钟。如果觉得开发节奏受影响:
SKIP_COVERAGE=1 做 WIP commitgit commit --amend 合并 WIP 提交修改对应的 jest.config.js 中 coverageThreshold.global 字段即可。Hook 本身不做数值判断,完全依赖 Jest 内置机制。
SKIP_COVERAGE=1 精确跳过覆盖率,不影响其他检查