Git钩子脚本如何检查可靠性门禁

wen 实用脚本 1

本文目录导读:

Git钩子脚本如何检查可靠性门禁

  1. 常用 Git 钩子与检查时机
  2. 常见的可靠性门禁检查项
  3. 管理多个钩子与工具链(推荐)
  4. 服务端强制门禁(服务端钩子)
  5. 绕过风险与最佳实践
  6. 完整示例脚本(pre-push)
  7. 可靠性门禁检查核心思路

常用 Git 钩子与检查时机

钩子类型 触发时机 适用场景
pre-commit 执行 git commit 之前 检查代码格式、禁止提交调试代码、运行静态分析
commit-msg 用户输入提交信息后 检查提交信息格式(如是否包含 issue 编号)
pre-push 执行 git push 之前 运行单元测试、集成测试、安全扫描、覆盖率检查
pre-receive / update 服务端接收推送时 强制分支保护规则、合规性检查

常见的可靠性门禁检查项

1 代码风格与静态分析

#!/bin/sh
# pre-commit 示例:运行 linter 和格式化检查
npm run lint
if [ $? -ne 0 ]; then
    echo "❌ Linting failed. Please fix issues before commit."
    exit 1
fi
# 检查是否有调试代码(如 console.log 在非开发环境)
if git diff --cached | grep -E "console\.log|debugger" > /dev/null; then
    echo "❌ Found debugger/console.log in staged changes. Remove them first."
    exit 1
fi

2 单元测试与覆盖率

#!/bin/sh
# pre-push 示例:运行单元测试并检查覆盖率
npm test -- --coverage
# 提取覆盖率数据(假设 Jest 输出到 coverage/lcov-report/index.html)
COVERAGE=$(node -e "const cov = require('./coverage/coverage-summary.json'); console.log(cov.total.lines.pct);")
# 设置最低覆盖率门限(80%)
THRESHOLD=80
if (( $(echo "$COVERAGE < $THRESHOLD" | bc -l) )); then
    echo "❌ Code coverage is ${COVERAGE}%, which is below the ${THRESHOLD}% threshold."
    exit 1
fi

3 安全漏洞扫描

#!/bin/sh
# pre-push 示例:运行 npm audit 或安全插件
npm audit --audit-level=high
if [ $? -ne 0 ]; then
    echo "❌ Security audit failed. Fix vulnerabilities before pushing."
    exit 1
fi

4 构建验证

#!/bin/sh
# pre-push 示例:确保代码可以编译或构建成功
npm run build
if [ $? -ne 0 ]; then
    echo "❌ Build failed. Fix compilation errors before pushing."
    exit 1
fi

管理多个钩子与工具链(推荐)

使用 Husky + lint-staged 是目前最流行的方式:

安装

npm install husky lint-staged --save-dev
npx husky init

配置 package.json

{
  "lint-staged": {
    "*.{js,ts,tsx}": ["eslint --fix", "prettier --write"],
    "*.md": ["prettier --write"]
  }
}

配置钩子 .husky/pre-commit

#!/bin/sh
npx lint-staged
npx tsc --noEmit    # TypeScript 类型检查

配置钩子 .husky/pre-push

#!/bin/sh
npm run test:coverage
npm run audit
npm run build

服务端强制门禁(服务端钩子)

如果团队需要不可绕过的门禁,可以在远程 Git 仓库(如 GitLab/GitHub Self-hosted)配置:

服务端 pre-receive 钩子(Git 原生)

#!/bin/bash
# 强制:每次 push 都必须包含测试通过记录(如 CI pipeline 传递的 token)
while read oldrev newrev refname; do
    # 检查是否在分支保护范围内
    if [ "$refname" = "refs/heads/main" ]; then
        # 实际生产环境:调用外部 CI 系统 API 确认构建状态
        echo "❌ Direct push to main is blocked. Use merge request + CI pipeline."
        exit 1
    fi
done

更推荐的做法:结合 CI/CD 系统

  • GitLab CI / GitHub Actions:在 Pipeline 中定义可靠性门禁,仅当通过后才允许合并 PR。
  • Branch Protection Rules:设置“需要状态检查通过”才能合并。

绕过风险与最佳实践

风险 解决方案
用户可以 git commit --no-verify 跳过钩子 服务端钩子(pre-receive)不可绕过
钩子运行耗时过长影响开发体验 使用 lint-staged 仅检查暂存区文件
依赖安装失败导致钩子无效 CI 中再次执行相同检查作为双重保障
不同开发环境差异导致误判 使用 Docker 容器化环境运行检查

完整示例脚本(pre-push)

#!/bin/bash
# .husky/pre-push - 综合可靠性门禁
echo "🔍 Running reliability gate checks..."
# 1. 运行单元测试并生成覆盖率报告
npm test -- --coverage --silent
TEST_EXIT=$?
if [ $TEST_EXIT -ne 0 ]; then
    echo "❌ Unit tests failed. Fix before pushing."
    exit 1
fi
# 2. 检查代码覆盖率(从 coverage-summary.json 解析)
COVERAGE=$(node -e "
    try {
        const c = require('./coverage/coverage-summary.json');
        const lines = c.total.lines.pct;
        const branches = c.total.branches.pct;
        const minLines = process.argv[1] || 85;
        console.log(JSON.stringify({ lines, branches }));
    } catch(e) {
        console.log('{}');
    }
" 2>/dev/null)
LINES=$(echo "$COVERAGE" | node -e "const d = JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')); console.log(d.lines || 0);" 2>/dev/null)
THRESHOLD=85
if (( $(echo "$LINES < $THRESHOLD" | bc -l 2>/dev/null) )); then
    echo "❌ Line coverage ${LINES}% < ${THRESHOLD}% threshold."
    exit 1
fi
# 3. 安全扫描(仅检查 high 以上级别)
npm audit --audit-level=high 2>&1 | tail -1 | grep -q "found 0 vulnerabilities"
if [ $? -ne 0 ]; then
    echo "❌ High/critical vulnerabilities found. Fix before push."
    exit 1
fi
# 4. 生产构建验证
npm run build 2>/dev/null
if [ $? -ne 0 ]; then
    echo "❌ Build failed."
    exit 1
fi
echo "✅ All reliability checks passed. Push allowed."
exit 0

可靠性门禁检查核心思路

命令行:git commit --no-verify?  →  本地钩子很容易绕过
CI/CD:merge request pipeline    →  最可靠的门禁位置
服务端钩子:pre-receive          →  不可绕过,但管理成本高
最佳组合:本地钩子 + CI 门禁     →  既快又安全

关键点:本地钩子防止低质量代码流出,CI 门禁作为最终防线,服务端保护规则封死绕过路径。

抱歉,评论功能暂时关闭!