本文目录导读:

Git钩子脚本检查“健壮性门禁”通常指在代码提交前(pre-commit)或推送前(pre-push)自动运行一系列静态分析、单元测试或安全检查,以下是实现这一目标的完整方案:
核心检查项设计
代码质量门禁
# pre-commit 示例:检查代码风格和潜在错误
#!/bin/bash
set -e
echo "🔍 开始代码质量检查..."
# ESLint/TSLint 检查(JavaScript/TypeScript)
if [ -f "node_modules/.bin/eslint" ]; then
npm run lint || {
echo "❌ 代码风格检查未通过"
exit 1
}
fi
# Pylint/Flake8 检查(Python)
if command -v flake8 &> /dev/null; then
flake8 . --max-line-length=120 || {
echo "❌ Python 代码规范检查未通过"
exit 1
}
fi
# Checkstyle(Java)
if [ -f "gradlew" ]; then
./gradlew checkstyleMain || {
echo "❌ Java 代码风格检查未通过"
exit 1
}
fi
单元测试门禁
# 运行单元测试 - 覆盖率要求
run_tests() {
local min_coverage=80 # 最低覆盖率要求
if [ -f "package.json" ]; then
npm test -- --coverage --coverageThreshold="{\"global\":{\"lines\":$min_coverage}}"
elif [ -f "pytest.ini" ]; then
pytest --cov=. --cov-fail-under=$min_coverage
elif [ -f "build.gradle" ]; then
./gradlew jacocoTestReport
fi
if [ $? -ne 0 ]; then
echo "❌ 单元测试未通过或覆盖率不足 $min_coverage%"
exit 1
fi
}
安全扫描门禁
# 依赖安全扫描
check_security() {
echo "🔒 运行安全扫描..."
# npm 审计
if [ -f "package-lock.json" ]; then
npm audit --audit-level=high || {
echo "❌ 发现高危安全漏洞"
exit 1
}
fi
# Bandit (Python)
if command -v bandit &> /dev/null; then
bandit -r . -ll || {
echo "❌ 发现 Python 安全漏洞"
exit 1
}
fi
# OWASP Dependency Check (Java)
if [ -f "pom.xml" ]; then
mvn org.owasp:dependency-check-maven:check || exit 1
fi
}
静态分析门禁
# 静态代码分析
run_static_analysis() {
echo "📊 运行静态代码分析..."
# SonarQube (需要配置)
if command -v sonar-scanner &> /dev/null; then
sonar-scanner -Dsonar.qualitygate.wait=true || {
echo "❌ SonarQube 质量门禁未通过"
exit 1
}
fi
# Infer (Facebook)
if command -v infer &> /dev/null; then
infer -- pom.xml || exit 1
fi
}
完整 pre-commit 脚本示例
#!/bin/bash
# .git/hooks/pre-commit
set -euo pipefail
# 配置
MIN_COVERAGE=80
FAIL_ON_WARNING=true
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
echo "========================================"
echo " 开始执行 Git 健壮性门禁检查"
echo "========================================"
# 1. 语法检查
check_syntax() {
echo "[1/5] 语法检查..."
for file in $STAGED_FILES; do
case "$file" in
*.js|*.jsx|*.ts|*.tsx)
npx eslint --quiet "$file" || exit 1
;;
*.py)
python -m py_compile "$file" || exit 1
;;
*.java)
javac -version > /dev/null 2>&1 && javac "$file" || exit 1
;;
esac
done
}
# 2. 单元测试(仅跑受影响的测试)
run_affected_tests() {
echo "[2/5] 运行单元测试..."
if [ -f "jest.config.js" ]; then
# 仅测试受变更影响的模块
affected_modules=$(echo "$STAGED_FILES" | grep -E '\.(js|ts)$' | sed 's/\.[^.]*$//')
if [ -n "$affected_modules" ]; then
npx jest --findRelatedTests $affected_modules --coverage || exit 1
fi
fi
}
# 3. 代码规范检查
check_code_style() {
echo "[3/5] 代码规范检查..."
if command -v prettier &> /dev/null; then
npx prettier --check $STAGED_FILES || {
echo "格式错误,使用 npx prettier --write 自动修复"
exit 1
}
fi
}
# 4. 大文件检查(防止过大文件提交)
check_file_size() {
echo "[4/5] 文件大小检查..."
local max_size=1048576 # 1MB
for file in $STAGED_FILES; do
size=$(stat -c%s "$file" 2>/dev/null || echo 0)
if [ "$size" -gt "$max_size" ]; then
echo "❌ 文件 $file 超过 1MB"
exit 1
fi
done
}
# 5. 密钥泄露检查
check_secrets() {
echo "[5/5] 密钥泄露检查..."
if command -v detect-secrets &> /dev/null; then
detect-secrets scan $STAGED_FILES || exit 1
elif command -v trufflehog &> /dev/null; then
trufflehog --files $STAGED_FILES || exit 1
else
# 简单正则检查
grep -E -i "(password|secret|token|api_key)" $STAGED_FILES && {
echo "⚠️ 发现可能的敏感信息"
exit 1
}
fi
}
# 执行所有检查
check_syntax
run_affected_tests
check_code_style
check_file_size
check_secrets
echo "========================================"
echo "✅ 所有健壮性检查通过!"
echo "========================================"
pre-push 脚本(更严格的检查)
#!/bin/bash
# .git/hooks/pre-push
set -euo pipefail
# 推送时执行更完整的检查
echo "🚀 推送前全面验证..."
# 1. 全量测试
if [ -f "gradlew" ]; then
./gradlew clean test || exit 1
fi
# 2. 集成测试
if [ -f "docker-compose.yml" ]; then
docker-compose run --rm integration-tests || exit 1
fi
# 3. 构建检查
if [ -f "pom.xml" ]; then
mvn clean verify || exit 1
fi
# 4. 安全扫描
if [ -f "package-lock.json" ]; then
npm audit --audit-level=moderate || exit 1
fi
# 5. 质量网关(集成sonarqube)
if command -v sonar-scanner &> /dev/null; then
sonar-scanner -Dsonar.qualitygate.wait=true || exit 1
fi
echo "✅ 推送前检查通过,可以推送!"
配置管理最佳实践
跳过检查(紧急修复时)
# 允许绕过(需谨慎使用) SKIP_CHECKS="" git commit -m "紧急修复" # 或设置环境变量 export CI=true # 部分工具会跳过检查
性能优化
# 增量检查(仅检查变更文件)
changed_files=$(git diff --name-only --cached)
# 并行执行检查
run_parallel() {
pids=""
for check in "$@"; do
$check &
pids+=" $!"
done
for pid in $pids; do
wait $pid || exit 1
done
}
团队统一管理(使用 Husky)
// package.json
{
"husky": {
"hooks": {
"pre-commit": "npm run lint-staged && npm test -- --coverage=80",
"pre-push": "npm run full-test && npm audit"
}
},
"lint-staged": {
"*.{js,ts,vue}": ["eslint --fix", "prettier --write"],
"*.py": ["black --check", "flake8"]
}
}
自定义跳过机制
# 支持通过 commit message 标记跳过
if [[ "$(head -1 .git/COMMIT_EDITMSG)" == *"[skip ci]"* ]]; then
echo "🔄 跳过CI检测"
exit 0
fi
常见问题处理
钩子执行失败排查
# 查看详细错误 bash -x .git/hooks/pre-commit # 临时禁用钩子 git commit --no-verify
跨平台兼容
# 使用 shebang 指定解释器
#!/usr/bin/env bash
# 检测操作系统
case "$(uname -s)" in
Darwin*) # macOS
stat -f%z "$file"
;;
Linux*) # Linux
stat -c%s "$file"
;;
esac
推荐配置模板
| 检查项 | 工具 | 优先级 | 执行阶段 |
|---|---|---|---|
| 语法检查 | ESLint/Pylint | 高 | pre-commit |
| 代码格式化 | Prettier/Black | 中 | pre-commit |
| 单元测试 | Jest/Pytest | 高 | pre-commit |
| 测试覆盖率 | Istanbul/Coverage | 中 | pre-push |
| 安全扫描 | npm audit/Bandit | 高 | pre-push |
| 密钥检测 | detect-secrets | 高 | pre-commit |
| 文件大小 | 自定义命令 | 低 | pre-commit |
这样配置的 Git 钩子系统可以在开发流程早期拦截问题,显著提高代码库的健壮性,记住根据团队实际情况调整检查的严格程度和覆盖范围。