MonkeyCode 代码质量门禁设置实践:从零构建企业级质量防线
引言
在软件开发过程中,代码质量门禁(Quality Gates) 是保证交付质量的核心机制。作为一款支持私有化部署的 AI 编程工具,MonkeyCode 在代码质量管理方面积累了丰富的实践经验。本文将全面分享 MonkeyCode 的质量门禁体系建设方法,帮助团队建立可靠的代码质量保障机制。
GitHub Issue 邀请:如果您在代码质量门禁配置、静态分析工具集成或质量度量方面有任何问题或建议,欢迎前往 MonkeyCode GitHub 仓库 提交 Issue 或参与讨论!
一、为什么需要代码质量门禁?
1.1 传统开发模式的痛点
┌─────────────────────────────────────────────────────────────┐
│ ❌ 没有质量门禁的开发模式 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 开发者 A 写完代码 → 直接提交 → 合并到主分支 │
│ ↓ │
│ 开发者 B 在此基础上继续开发 → 发现基础有问题 │
│ ↓ │
│ 追溯问题 → 花费大量时间定位 → 影响多人工作 │
│ ↓ │
│ 生产环境出现 Bug → 紧急修复 → 压力巨大 │
│ │
│ 💥 结果:技术债务累积、Bug 率高、团队士气低落 │
│ │
└─────────────────────────────────────────────────────────────┘
1.2 质量门禁的价值
| 维度 | 无门禁 | 有门禁 |
|---|---|---|
| Bug 引入率 | 高(15-25%) | 低(<5%) |
| 代码审查效率 | 低(审查变形式) | 高(自动化初筛) |
| 回归风险 | 高 | 显著降低 |
| 新人上手 | 困难(无标准约束) | 容易(自动检查引导) |
| 技术债务 | 快速积累 | 可控增长 |
二、MonkeyCode 质量门禁体系概览
2.1 四级门禁架构
┌─────────────────────────────────┐
│ MonkeyCode 质量门禁体系 │
└──────────────┬──────────────────┘
│
┌──────────────────────────┼──────────────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ 🟢 L1 本地 │ │ 🟡 L2 提交 │ │ 🟠 L3 PR │
│ 门禁 │ │ 门禁 │ │ 门禁 │
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
│ • EditorConfig │ │ • Git Hooks │ │ • CI 自动化检查 │
│ • ESLint/Prettier│ │ • pre-commit │ │ • 单元测试通过 │
│ • IDE 集成 │ │ • 类型检查 │ │ • 代码覆盖率达标 │
│ • 格式化 │ │ • lint 检查 │ │ • 安全扫描 │
│ • 实时错误提示 │ │ • 格式化 │ │ • AI 辅助审查 │
└──────────────────┘ └──────────────────┘ └──────────────────┘
│
▼
┌──────────────────┐
│ 🔴 L4 发布 │
│ 门禁 │
├──────────────────┤
│ • E2E 测试通过 │
│ • 性能基准达标 │
│ • 文档完整性检查 │
│ • 变更日志生成 │
│ • 安全审计通过 │
└──────────────────┘
2.2 各级门禁职责对比
quality_gates:
level_1_local:
name: "本地开发门禁"
trigger: "保存文件时 / 编辑时"
tools:
- "IDE 内置诊断"
- "ESLint / Prettier"
- "TypeScript 类型检查"
- "EditorConfig"
blocking: false # 仅警告,不阻止
goal: "即时反馈,快速修正"
level_2_commit:
name: "提交前门禁"
trigger: "git commit 时"
tools:
- "pre-commit hooks (husky)"
- "lint-staged"
- "commitlint (规范 commit message)"
- "格式化检查"
blocking: true # 不通过则拒绝提交
goal: "保证提交的基本质量"
level_3_pr:
name: "PR 门禁"
trigger: "创建/更新 Pull Request 时"
tools:
- "CI Pipeline (GitHub Actions)"
- "单元测试 + 集成测试"
- "代码覆盖率检查"
- "安全扫描 (Snyk / Trivy)"
- "AI 代码审查 (MonkeyCode)"
blocking: true # 不通过则不能合并
goal: "保证合并代码的质量基线"
level_4_release:
name: "发布门禁"
trigger: "打 tag / 发布时"
tools:
- "E2E 测试套件"
- "性能基准测试"
- "文档生成与验证"
- "安全合规扫描"
- "变更影响分析"
blocking: true # 全部通过才能发布
goal: "保证生产环境的可靠性"
三、L1:本地开发门禁配置
3.1 EditorConfig 统一编码风格
# .editorconfig — MonkeyCode 项目编码规范
root = true
# 默认规则
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
# Markdown 文件
[*.md]
trim_trailing_whitespace = false
max_line_length = off
# JSON / YAML
[*.{json,yml,yaml}]
indent_size = 2
# Python 文件
[*.py]
indent_size = 4
# Rust / Go
[*.{rs,go}]
indent_style = tab
indent_size = 4
# Shell 脚本
[*.sh]
indent_size = 2
# Dockerfile
[Dockerfile]
indent_size = 4
3.2 ESLint 配置(JavaScript/TypeScript)
// .eslintrc.cjs — MonkeyCode ESLint 规则配置
module.exports = {
root: true,
env: {
browser: true,
es2022: true,
node: true,
jest: true,
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'prettier', // 与 Prettier 兼容
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: './tsconfig.json',
tsconfigRootDir: __dirname,
},
plugins: [
'@typescript-eslint',
'react',
'react-hooks',
'import',
'jsx-a11y',
],
rules: {
// TypeScript 严格类型检查
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unused-vars': ['error', {
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
}],
'@typescript-eslint/explicit-function-return-type': ['warn', {
allowExpressions: true,
allowTypedFunctionExpressions: true,
}],
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/await-thenable': 'error',
'@typescript-eslint/no-misused-promises': 'error',
// React 规则
'react/react-in-jsx-scope': 'off', // React 17+ 不需要
'react/prop-types': 'off', // 使用 TypeScript 替代
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
// Import 排序和规范
'import/order': ['error', {
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'type'],
'newlines-between': 'always',
alphabetize: { order: 'asc', caseInsensitive: true },
}],
'import/no-duplicates': 'error',
'import/no-cycle': ['error', { maxDepth: 10 }],
// 代码复杂度
'complexity': ['warn', { max: 15 }],
'max-lines-per-function': ['warn', { max: 80, skipBlankLines: true, skipComments: true }],
'max-depth': ['warn', { max: 4 }],
'max-params': ['warn', { max: 5 }],
// 最佳实践
'no-console': ['warn', { allow: ['warn', 'error'] }],
'no-debugger': 'error',
'no-alert': 'error',
'prefer-const': 'error',
'no-var': 'error',
eqeqeq: ['error', 'always'],
curly: ['error', 'all'],
},
settings: {
react: { version: 'detect' },
'import/resolver': {
typescript: {},
node: { extensions: ['.js', '.ts', '.tsx'] },
},
},
ignorePatterns: ['dist/**', 'build/**', '*.config.js', '*.config.ts', 'node_modules/**', '.next/**', 'coverage/**'],
};
3.3 Prettier 配置
// .prettierrc.js — MonkeyCode 格式化配置
module.exports = {
printWidth: 100, // 每行最大字符数
tabWidth: 2, // 缩进空格数
useTabs: false, // 使用空格缩进
semi: true, // 行尾分号
singleQuote: true, // 使用单引号
quoteProps: 'as-needed', // 对象属性引号
trailingComma: 'all', // 尾逗号
bracketSpacing: true, // 对象括号空格
bracketSameLine: false, // JSX 标签换行
arrowParens: 'always', // 箭头函数括号
endOfLine: 'lf', // 换行符
proseWrap: 'preserve', // Markdown 换行
htmlWhitespaceSensitivity: 'css',
embeddedLanguageFormatting: 'auto',
singleAttributePerLine: false,
overrides: [
{ files: '*.md', options: { printWidth: 80, proseWrap: 'always' } },
{ files: '*.{json,yaml,yml}', options: { tabWidth: 2 } },
],
};
3.4 VS Code 工作区配置
// .vscode/settings.json — MonkeyCode VS Code 统一配置
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never",
"source.addMissingImports": "explicit"
},
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.rulers": [100],
"files.eol": "\n",
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
"[markdown]": { "files.trimTrailingWhitespace": false },
"[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[typescriptreact]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
"typescript.preferences.importModuleSpecifier": "relative",
"typescript.suggest.autoImports": true,
"typescript.updateImportsOnFileMove.enabled": "always",
"search.exclude": {
"**/node_modules": true,
"**/dist": true,
"**/.next": true,
"**/coverage": true
}
}
四、L2:Git 提交门禁(Pre-commit Hooks)
4.1 Husky + lint-staged 配置
# 安装依赖
npm install --save-dev husky lint-staged @commitlint/cli @commitlint/config-conventional
# 初始化 husky
npx husky init
// package.json — MonkeyCode pre-commit 配置
{
"name": "monkeyCode",
"lint-staged": {
"*.{js,jsx,ts,tsx}": ["eslint --fix --max-warnings=0", "prettier --write"],
"*.{json,yaml,yml}": ["prettier --write"],
"*.{md,mdx}": ["prettier --write", "markdownlint-cli2-fix"],
"*.{css,scss,less}": ["stylelint --fix", "prettier --write"]
}
}
// commitlint.config.js — MonkeyCode Commit Message 规范
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [2, 'always', [
'feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test',
'build', 'ci', 'chore', 'revert', 'release', 'security'
]],
'subject-case': [2, 'never', ['start-case', 'pascal-case', 'UPPER-CASE']],
'subject-max-length': [2, 'always', 72],
'body-max-line-length': [2, 'always', 100],
},
};
4.2 自定义 Pre-commit Hook 示例
#!/bin/sh
# .husky/pre-commit — MonkeyCode 自定义 pre-commit hook
set -e
echo "🔍 Running MonkeyCode quality checks..."
# 检查是否有大文件被添加(> 5MB)
check_large_files() {
if git diff --cached --name-only | xargs -I {} git diff --cached --size-filter="+5M" -- {} | grep -q .; then
echo "❌ Error: Files larger than 5MB detected!"
echo "Please use git-lfs for large files."
exit 1
fi
}
# 检查是否包含敏感信息
check_secrets() {
if git diff --cached --name-only -z | xargs -0 git grep --cached -l -E '(password|secret|api_key|token)\s*[:=]\s*["\x27][^"\x27]{8,}' | grep -q .; then
echo "⚠️ Warning: Potential secrets detected in staged changes!"
read -p "Continue anyway? (y/N) " choice
case "$choice" in y|Y) ;; *) exit 1 ;; esac
fi
}
check_large_files
check_secrets
echo "✅ All quality checks passed!"
五、L3:PR 门禁与 CI 流水线
5.1 GitHub Actions PR Check 配置
# .github/workflows/pr-quality-gate.yml — MonkeyCode PR 质量门禁
name: 🔒 Quality Gate
on:
pull_request:
types: [opened, synchronize, reopened]
branches: [main, develop]
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref }}
cancel-in-progress: true
permissions:
contents: read
pull-requests: write
checks: write
env:
MIN_COVERAGE: 70
MAX_WARNINGS: 0
jobs:
code-style:
name: 🎨 Code Style
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: 20, cache: 'pnpm' }
- run: pnpm install --frozen-lockfile
- name: ESLint
run: pnpm eslint . --max-warnings=${{ env.MAX_WARNINGS }}
- name: Prettier Check
run: pnpm prettier --check "src/**/*.{ts,tsx,js,jsx,json,css}"
- name: Type Check
run: pnpm tsc --noEmit --pretty
unit-tests:
name: 🧪 Unit Tests & Coverage
runs-on: ubuntu-latest
needs: code-style
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: 'pnpm' }
- run: pnpm install --frozen-lockfile
- name: Run Tests with Coverage
run: pnpm vitest run --coverage --reporter=verbose
- name: Coverage Threshold Check
run: |
COVERAGE=$(cat coverage/coverage-summary.json | jq '.total.lines.pct')
echo "Current coverage: ${COVERAGE}%"
if (( $(echo "$COVERAGE < $MIN_COVERAGE" | bc -l) )); then
echo "::error::Coverage ${COVERAGE}% is below minimum threshold of ${MIN_COVERAGE}%"
exit 1
fi
- name: Upload Coverage Report
uses: codecov/codecov-action@v4
with: { token: ${{ secrets.CODECOV_TOKEN }}, fail_ci_if_error: false }
security-scan:
name: 🔒 Security Scan
runs-on: ubuntu-latest
needs: code-style
steps:
- uses: actions/checkout@v4
- name: Run Trivy filesystem scanner
uses: aquasecurity/trivy-action@master
with: { scan-type: 'fs', scan-ref: '.', severity: 'CRITICAL,HIGH,MEDIUM', exit-code: '1', ignore-unfixed: true }
complexity-analysis:
name: 📊 Complexity Analysis
runs-on: ubuntu-latest
needs: unit-tests
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: 'pnpm' }
- run: pnpm install --frozen-lockfile
- name: Run Complexity Report
id: complexity
run: |
pnpm eslint . --format=json > eslint-report.json
HIGH=$(jq '[.[] | select(.messages[].ruleId == "complexity") | length] | add' eslint-report.json)
DEPTH=$(jq '[.[] | select(.messages[].ruleId == "max-depth") | length] | add' eslint-report.json)
PARAMS=$(jq '[.[] | select(.messages[].ruleId == "max-params") | length] | add' eslint-report.json)
echo "high_complexity=$HIGH" >> $GITHUB_OUTPUT
echo "max_depth_violations=$DEPTH" >> $GITHUB_OUTPUT
echo "max_params_violations=$PARAMS" >> $GITHUB_OUTPUT
- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
const body = `## 📊 Code Complexity Report\n\n` +
`| Metric | Count | Status |\n|--------|-------|--------|\n` +
`| High Complexity | \`${{ steps.complexity.outputs.high_complexity }}\` | ⚠️ |\n` +
`| Max Depth Violations | \`${{ steps.complexity.outputs.max_depth_violations }}\` | ⚠️ |\n`;
github.rest.issues.createComment({
owner: context.repo.owner, repo: context.repo.repo,
issue_number: context.issue.number, body: body
});
5.2 分支保护规则配置
branch_protection_rules:
main_branch:
branch: "main"
require_pull_request_reviews:
required_approving_review_count: 2
dismiss_stale_reviews: true
require_code_owner_reviews: true
require_last_push_approval: true
required_status_checks:
strict: true
contexts:
- "🧪 Unit Tests & Coverage"
- "🔒 Security Scan"
- "📊 Complexity Analysis"
- "🎨 Code Style"
enforce_admins: true
force_pushes: { enabled: false }
deletions: { enabled: false }
六、L4:发布门禁配置
6.1 发布前 Checklist
release_quality_gate:
pre_release_checks:
- { name: "Version bump correct", check: "package.json version matches tag", mandatory: true }
- { name: "Changelog updated", check: "CHANGELOG.md contains current version", mandatory: true }
- { name: "All tests pass", check: "Full test suite passes on all platforms", mandatory: true }
- { name: "Coverage >= 80%", check: "Overall coverage meets threshold", mandatory: true }
- { name: "No critical bugs", check: "GitHub Issues has no open P0/P1", mandatory: true }
- { name: "Security scan clean", check: "No CRITICAL/HIGH vulnerabilities", mandatory: true }
- { name: "Documentation complete", check: "API docs and user guide updated", mandatory: true }
- { name: "Performance OK", check: "Key metrics within ±5% of baseline", mandatory: true }
6.2 发布流水线示例
# .github/workflows/release.yml — MonkeyCode 发布流水线
name: 🚀 Release
on:
push:
tags: ['v*']
permissions:
contents: write
packages: write
jobs:
quality-gate:
runs-on: ubuntu-latest
outputs: { should_release: "${{ steps.check.outputs.should_release }}" }
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- name: Version Validation
id: check
run: |
TAG="${GITHUB_REF_NAME#v}"
PKG=$(node -p "require('./package.json').version")
if [ "$TAG" != "$PKG" ]; then
echo "::error::Tag ($TAG) != package.json ($PKG)"
echo "should_release=false" >> $GITHUB_OUTPUT
exit 1
fi
echo "should_release=true" >> $GITHUB_OUTPUT
full-test-suite:
runs-on: ${{ matrix.os }}
needs: quality-gate
if: needs.quality-gate.outputs.should_release == 'true'
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: ${{ matrix.node-version }}, cache: 'pnpm' }
- run: pnpm install --frozen-lockfile && pnpm lint && pnpm typecheck && pnpm test:unit --coverage && pnpm test:integration
security-audit:
runs-on: ubuntu-latest
needs: quality-gate
if: needs.quality-gate.outputs.should_release == 'true'
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: 'pnpm' }
- run: pnpm install --frozen-lockfile && pnpm audit --audit-level=moderate
publish:
runs-on: ubuntu-latest
needs: [full-test-suite, security-audit]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: 20, registry-url: 'https://registry.npmjs.org', cache: 'pnpm' }
- run: pnpm install --frozen-lockfile && pnpm build
- name: Publish to npm
env: { NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN } }
run: pnpm publish --no-git-checks --access public
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with: { generate_release_notes: true, draft: false, prerelease: ${{ contains(github.ref, '-') }}, files: 'dist/*.tgz\nCHANGELOG.md' }
七、常见问题与故障排查
FAQ
| 问题 | 解决方案 |
|---|---|
| 门禁太严格影响效率? | 分级实施、渐进式收紧、例外流程 |
| 历史遗留代码? | 增量覆盖、baseline 记录、专项清理 |
| 团队不遵守? | 自动化强制、IDE集成、正向激励 |
| 平衡质量和速度? | 风险分级、智能门禁、并行化、缓存优化 |
故障排查速查表
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| PR 无法合并 | CI 未通过 | 查看 CI 日志修复 |
| Lint 报错不一致 | 版本不同步 | 锁定工具版本统一配置 |
| 覆盖率下降 | 新代码缺测试 | 补充单元测试 |
| Hook 不生效 | Husky 未安装 | 重新运行 husky install |
| Secret 泄露误报 | 测试含密钥样例 | 加入白名单或改写测试 |
八、最佳实践总结
╔═══════════════════════════════════════════════════════════╗
║ 🏆 MonkeyCode 质量门禁十大原则 ║
║ ║
║ 1️⃣ 左移原则 — 越早发现问题,修复成本越低 ║
║ 2️⃣ 自动化优先 — 能自动化的绝不依赖人工 ║
║ 3️⃣ 渐进式实施 — 从简单开始,逐步完善 ║
║ 4️⃣ 数据驱动 — 用指标衡量效果,持续优化 ║
║ 5️⃣ 文化先行 — 工具是手段,质量意识是根本 ║
║ 6️⃣ 分级管理 — 不同场景适用不同严格程度 ║
║ 7️⃣ 反馈及时 — 让开发者秒级获得质量反馈 ║
║ 8️⃣ 透明可视 — 质量指标对全团队公开 ║
║ 9️⃣ 持续迭代 — 定期回顾和调整门禁规则 ║
║ 🔟 平衡艺术 — 质量和速度需要找到平衡点 ║
║ ║
╚═══════════════════════════════════════════════════════════╝
九、总结与行动号召
本文详细介绍了 MonkeyCode 四级代码质量门禁体系的完整实施方案:
| 层级 | 核心价值 | 关键工具 | 实施难度 |
|---|---|---|---|
| L1 本地门禁 | 即时反馈 | ESLint, Prettier, EditorConfig | ⭐ |
| L2 提交门禁 | 保证提交质量 | Husky, lint-staged, commitlint | ⭐⭐ |
| L3 PR 门禁 | 保证合并质量 | GitHub Actions, 测试, 安全扫描 | ⭐⭐⭐ |
| L4 发布门禁 | 保证生产质量 | E2E 测试, 性能基准, 安全审计 | ⭐⭐⭐⭐ |
记住:质量门禁不是目的,而是手段。真正的目标是建立全员参与的质量文化!
- 🔧 贡献配置模板:帮我们完善各语言的门禁配置
- 🐛 报告质量问题:在 GitHub Issue 中标注
[quality-gate]前缀 - 💬 参与 讨论:在 GitHub Discussions 中交流心得
现在就访问 MonkeyCode GitHub,查看我们的完整质量门禁配置,提出你的改进建议吧!
本文最后更新于 2026 年 7 月 1 日。请以 GitHub 仓库最新信息为准。
相关文章推荐:
© 2026 MonkeyCode Open Source Project. Licensed under Apache License 2.0.
浙公网安备 33010602011771号