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

wen 实用脚本 1

本文目录导读:

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

  1. 预提交钩子 (pre-commit) 检查方案
  2. 提交信息钩子 (commit-msg) 检查
  3. 推送钩子 (pre-push) 更严格的检查
  4. 配置管理钩子
  5. 安装脚本
  6. 使用建议

Git 钩子脚本可以通过以下方式检查代码的可复现性门禁,确保提交的代码能可靠地重建出相同的构建结果:

预提交钩子 (pre-commit) 检查方案

#!/bin/bash
# .git/hooks/pre-commit
set -e
echo "🔍 检查可复现性门禁..."
# 1. 检查构建文件锁定
check_build_locks() {
    local lock_files=("package-lock.json" "yarn.lock" "pnpm-lock.yaml" "Gemfile.lock" "Cargo.lock")
    for file in "${lock_files[@]}"; do
        if [ -f "$file" ]; then
            # 确保锁文件已暂存
            if git diff --cached --name-only | grep -q "$file"; then
                echo "✅ 锁文件 $file 已包含在提交中"
            else
                echo "❌ 锁文件 $file 变更未暂存!"
                exit 1
            fi
        fi
    done
}
# 2. 检查 Dockerfile 固定版本
check_dockerfile() {
    if [ -f "Dockerfile" ]; then
        # 检查是否使用固定标签而非 latest
        if grep -qE "FROM.*:latest" Dockerfile; then
            echo "⚠️  Dockerfile 使用了 :latest 标签,建议使用固定版本"
        fi
        # 检查是否指定了具体版本号
        if ! grep -qE "FROM.*:[0-9]+\.[0-9]+" Dockerfile; then
            echo "❌ Dockerfile 未指定固定版本号!"
            exit 1
        fi
    fi
}
# 3. 检查依赖版本固定
check_dependency_versions() {
    # 检查 package.json 是否使用范围版本
    if [ -f "package.json" ]; then
        if grep -qE '"[^"]+":\s*"\^|\~' package.json; then
            echo "⚠️  package.json 中存在范围版本(^/~),建议锁定精确版本"
        fi
    fi
    # 检查 requirements.txt 是否固定版本
    if [ -f "requirements.txt" ]; then
        if grep -qE ">|<|>=" requirements.txt; then
            echo "❌ requirements.txt 中存在不固定版本依赖!"
            exit 1
        fi
    fi
}
# 4. 检查构建脚本的确定性
check_build_scripts() {
    if [ -f "Makefile" ]; then
        # 检查是否使用了随机或时间相关的操作
        if grep -qE "date|\$(date)|mktemp|random" Makefile; then
            echo "⚠️  Makefile 包含可能影响可复现性的命令"
        fi
    fi
}
# 5. 验证构建缓存
check_build_cache() {
    if [ -d "node_modules" ] || [ -d ".next" ] || [ -d "dist" ]; then
        echo "⚠️  构建缓存目录存在,建议清理后提交"
        # 检查 .gitignore 中是否排除
        if [ -f ".gitignore" ]; then
            grep -q "node_modules" .gitignore || echo "⚠️  node_modules 未在 .gitignore 中"
        fi
    fi
}
# 执行检查
check_build_locks
check_dockerfile
check_dependency_versions
check_build_scripts
check_build_cache
echo "✅ 可复现性门禁检查通过"

提交信息钩子 (commit-msg) 检查

#!/bin/bash
# .git/hooks/commit-msg
commit_msg_file=$1
commit_msg=$(cat "$commit_msg_file")
# 检查提交信息是否包含可复现性标记
if [[ ! "$commit_msg" =~ (reproducible|reproducibility|可复现) ]]; then
    echo "⚠️  建议在提交信息中添加可复现性说明"
    read -p "是否继续提交? (y/n) " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        exit 1
    fi
fi

推送钩子 (pre-push) 更严格的检查

#!/bin/bash
# .git/hooks/pre-push
# 1. 执行完整的构建验证
echo "🏗️ 执行可复现性构建验证..."
# 清理构建环境
clean_build() {
    rm -rf node_modules dist .next
    npm ci || yarn install --frozen-lockfile
}
# 计算构建哈希
compute_build_hash() {
    if [ -f "package.json" ]; then
        npm run build 2>/dev/null || yarn build 2>/dev/null
        find dist -type f -exec md5sum {} \; | sort | md5sum
    fi
}
# 两次构建验证
first_hash=$(clean_build && compute_build_hash)
second_hash=$(clean_build && compute_build_hash)
if [ "$first_hash" != "$second_hash" ]; then
    echo "❌ 构建结果不一致!请检查构建过程的可复现性"
    exit 1
fi
echo "✅ 构建可复现性验证通过"

配置管理钩子

创建 .reproducibility-check.yml 配置文件:

# 可复现性检查配置
checks:
  build_locks: true
  docker_versions: true
  dependency_versions: true
  build_scripts: true
# 排除检查的文件
exclude:
  - "*.md"
  - "docs/*"
# 强制检查的路径
include:
  - "src/**/*"
  - "Dockerfile"
  - "package.json"
# 允许的构建工具
allowed_build_tools:
  - npm
  - yarn
  - make
  - docker
# 禁止的命令
forbidden_commands:
  - curl
  - wget
  - date
  - timestamp

安装脚本

#!/bin/bash
# setup-hooks.sh
HOOKS_DIR=".git/hooks"
install_hook() {
    local hook_name=$1
    local hook_content=$2
    cat > "$HOOKS_DIR/$hook_name" << 'EOF'
#!/bin/bash
# 可复现性检查钩子
EOF
    echo "$hook_content" >> "$HOOKS_DIR/$hook_name"
    chmod +x "$HOOKS_DIR/$hook_name"
    echo "✅ 安装 $hook_name 钩子完成"
}
# 安装预提交钩子
install_hook "pre-commit" "$(cat << 'SCRIPT'
#!/bin/bash
source "$(dirname "$0")/reproducibility-check.sh"
check_reproducibility_gate
SCRIPT
)"
# 创建共享检查脚本
cat > ".git/hooks/reproducibility-check.sh" << 'SCRIPT'
#!/bin/bash
check_reproducibility_gate() {
    # 从配置文件读取设置
    CONFIG_FILE=".reproducibility-check.yml"
    if [ -f "$CONFIG_FILE" ]; then
        echo "📋 加载可复现性检查配置..."
        # 解析 YAML 配置并执行对应检查
    fi
    # 执行标准检查
    # ... 检查逻辑
}
# 导出函数
export -f check_reproducibility_gate
SCRIPT
chmod +x ".git/hooks/reproducibility-check.sh"
echo "✅ 所有可复现性门禁钩子安装完成"

使用建议

  1. 渐进式实施:先设置为警告,再逐步升级为强制检查
  2. 环境感知:根据开发/生产环境设置不同的严格程度
  3. 结果记录:将检查结果记录到日志中便于审计
  4. CI/CD集成:在持续集成流程中并行执行相同检查
  5. 白名单机制:允许特殊情况跳过检查(需审批)

这些钩子脚本可以有效确保代码的可复现性,防止因环境差异导致的构建不一致问题。

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