Git钩子脚本如何检查互操作性门禁

wen 实用脚本 1

本文目录导读:

Git钩子脚本如何检查互操作性门禁

  1. 使用 pre-commit 钩子检查文件编码和换行符
  2. 使用 pre-receive 钩子检查 API 兼容性
  3. 使用 prepare-commit-msg 钩子检查提交信息格式
  4. 综合互操作性检查脚本(pre-commit)
  5. 使用 Git 钩子管理工具
  6. 最佳实践

Git 钩子脚本可以用来在提交或推送之前检查代码的互操作性(Interoperability),确保代码不会破坏跨平台、跨语言或跨系统的兼容性。

以下是几种常见的 Git 钩子脚本实现方式,用于检查互操作性门禁:

使用 pre-commit 钩子检查文件编码和换行符

#!/bin/bash
# .git/hooks/pre-commit
# 检查文件是否包含 Windows 换行符 (CRLF)
errors=0
for file in $(git diff --cached --name-only); do
    if [[ -f "$file" ]]; then
        # 检查换行符一致性
        if file "$file" | grep -q "CRLF"; then
            echo "错误: $file 包含 CRLF 换行符,请转换为 LF"
            errors=$((errors + 1))
        fi
        # 检查 UTF-8 BOM
        if head -c 3 "$file" | od -c | grep -q "357 273 277"; then
            echo "错误: $file 包含 UTF-8 BOM,请移除"
            errors=$((errors + 1))
        fi
    fi
done
if [ $errors -gt 0 ]; then
    exit 1
fi

使用 pre-receive 钩子检查 API 兼容性

#!/bin/bash
# .git/hooks/pre-receive (服务端钩子)
while read oldrev newrev refname; do
    # 获取变更的文件列表
    for file in $(git diff --name-only $oldrev $newrev); do
        # 检查 API 版本声明
        if [[ "$file" == *.json ]] || [[ "$file" == *.yaml ]]; then
            # 检查是否更新了 API 版本号
            if grep -q "apiVersion" "$file" 2>/dev/null; then
                old_version=$(git show $oldrev:$file 2>/dev/null | grep "apiVersion" | cut -d: -f2)
                new_version=$(git show $newrev:$file | grep "apiVersion" | cut -d: -f2)
                if [ "$old_version" != "$new_version" ] && [ -z "$new_version" ]; then
                    echo "错误: $file 缺少 apiVersion 声明"
                    exit 1
                fi
            fi
        fi
        # 检查接口定义文件
        if [[ "$file" == *.proto ]] || [[ "$file" == *swagger* ]]; then
            # 运行兼容性检查脚本
            if ! check_interface_compatibility.sh $oldrev $newrev $file; then
                echo "错误: $file 存在不兼容的变更"
                exit 1
            fi
        fi
    done
done

使用 prepare-commit-msg 钩子检查提交信息格式

#!/bin/bash
# .git/hooks/prepare-commit-msg
COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
# 检查提交信息是否包含互操作性相关信息
if [ -z "$COMMIT_SOURCE" ]; then
    # 对于新提交,检查是否包含互操作性影响说明
    if grep -qi "interop\|compatibility\|breaking" "$COMMIT_MSG_FILE"; then
        # 要求填写详细的互操作性影响说明
        echo -e "\n\n## 互操作性影响说明:" >> "$COMMIT_MSG_FILE"
        echo "# 请描述本次变更对互操作性的影响:" >> "$COMMIT_MSG_FILE"
        echo "# - 是否破坏了向后兼容性? [是/否]" >> "$COMMIT_MSG_FILE"
        echo "# - 是否需要更新其他系统? [是/否]" >> "$COMMIT_MSG_FILE"
        echo "# - 是否需要升级客户端版本? [是/否]" >> "$COMMIT_MSG_FILE"
    fi
fi

综合互操作性检查脚本(pre-commit)

#!/bin/bash
# .git/hooks/pre-commit
ERRORS=0
WARNINGS=0
echo "运行互操作性检查..."
# 获取暂存的文件
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
for file in $STAGED_FILES; do
    if [[ ! -f "$file" ]]; then
        continue
    fi
    case "$file" in
        *.java|*.kt|*.scala)
            # 检查 Java/Kotlin 代码的包名规范
            if grep -q "package.*\.impl\|package.*\.internal" "$file"; then
                echo "警告: $file 包含内部实现包,外部系统可能无法直接调用"
                WARNINGS=$((WARNINGS + 1))
            fi
            ;;
        *.py)
            # 检查 Python 代码的类型提示
            if grep -q "def " "$file"; then
                if ! grep -q "->" "$file"; then
                    echo "警告: $file 缺少返回类型注解,影响跨语言互操作"
                    WARNINGS=$((WARNINGS + 1))
                fi
            fi
            ;;
        *.proto)
            # 检查 Protocol Buffers 文件的兼容性
            if ! protoc --lint_out=. "$file" 2>/dev/null; then
                echo "错误: $file 存在 protobuf 兼容性问题"
                ERRORS=$((ERRORS + 1))
            fi
            ;;
        *.json|*.yaml)
            # 检查配置文件是否符合规范
            if grep -q "version\|apiVersion" "$file"; then
                current_version=$(grep "version" "$file" | head -1)
                if [[ -z "$current_version" ]]; then
                    echo "错误: $file 缺少版本号"
                    ERRORS=$((ERRORS + 1))
                fi
            fi
            ;;
    esac
    # 通用检查:文件名编码
    if echo "$file" | grep -q '[^\x20-\x7E]'; then
        echo "错误: $file 包含非 ASCII 字符,可能导致跨平台问题"
        ERRORS=$((ERRORS + 1))
    fi
    # 检查文件大小
    file_size=$(stat -f%z "$file" 2>/dev/null || stat --printf="%s" "$file" 2>/dev/null)
    if [ "$file_size" -gt 1048576 ]; then  # 1MB
        echo "警告: $file 文件过大 (>1MB),可能影响分布式系统同步"
        WARNINGS=$((WARNINGS + 1))
    fi
done
# 检查是否有改动配置文件但未更新文档
if echo "$STAGED_FILES" | grep -q "config\|settings\|properties"; then
    if ! echo "$STAGED_FILES" | grep -qi "readme\|documentation\|docs"; then
        echo "警告: 配置文件已变更,但未更新相关文档"
        WARNINGS=$((WARNINGS + 1))
    fi
fi
# 输出检查结果
echo "互操作性检查完成: $ERRORS 个错误, $WARNINGS 个警告"
if [ $ERRORS -gt 0 ]; then
    echo "存在互操作性错误,提交被拒绝"
    exit 1
fi
exit 0

使用 Git 钩子管理工具

更推荐使用如 husky (npm) 或 pre-commit (Python) 等工具来管理钩子:

# .pre-commit-config.yaml (Python pre-commit 工具)
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.4.0
    hooks:
      - id: check-added-large-files
      - id: check-json
      - id: check-yaml
      - id: end-of-file-fixer
      - id: mixed-line-ending
        args: ['--fix=lf']
      - id: trailing-whitespace
  - repo: https://github.com/grpc-ecosystem/protoc-gen-openapiv2
    rev: v2.19.0
    hooks:
      - id: protoc-lint
        args: ['--lint_out=.', '--proto_path=protos']
  - repo: local
    hooks:
      - id: api-compatibility-check
        name: API 兼容性检查
        entry: scripts/check_api_compatibility.sh
        language: script
        files: '\.(proto|json|yaml|yml)$'

最佳实践

  1. 分阶段检查:pre-commit 检查基本格式,pre-receive 检查更严格的兼容性
  2. 提供清晰的错误信息:说明违反的具体规则和修复方法
  3. 允许跳过检查:使用 --no-verify 参数,但要记录日志
  4. 定期更新规则:随着系统演化更新检查规则
  5. 结合 CI/CD:Git 钩子作为第一道防线,CI 系统做更全面的检查

这些脚本可以根据具体需求进行调整,例如添加对特定框架、库或协议的检查规则。

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