美文网首页
Gitlab pre-receive 对提交进行校验

Gitlab pre-receive 对提交进行校验

作者: 87d6dc4b11a7 | 来源:发表于2025-04-09 22:42 被阅读0次

以下是分模块实现的完整代码方案,包含 配置管理日志模块校验逻辑主程序,采用工程化结构设计:


目录结构

/opt/gitlab/custom_hooks/
├── config.sh               # 集中配置
├── pre-receive             # 主入口脚本
├── modules/
│   ├── log.sh              # 日志模块
│   ├── validator.sh        # 校验核心逻辑
│   └── utils.sh            # 工具函数
└── logs/
    └── hook_audit.log      # 审计日志

模块 1: 配置文件 (config.sh)

#!/bin/bash

# 全局配置参数
readonly MAX_FILE_SIZE=104857600              # 100MB
readonly COMMIT_MSG_REGEX='^[A-Z]+-[0-9]+: '  # 提交信息规则
readonly MAX_COMMITS_PROCESS=500              # 单次推送最多处理500个提交(防溢出)

# 文件白名单配置
readonly WHITELIST_PATTERNS=(
  "*.pdf"             # 允许所有PDF文件
  "vendor/*"          # 允许vendor目录下所有文件
  "lib/*.so"          # 允许lib目录下的.so文件
)

# 日志配置
readonly LOG_ENABLED=true
readonly LOG_FILE="/opt/gitlab/custom_hooks/logs/hook_audit.log"

模块 2: 日志模块 (modules/log.sh)

#!/bin/bash

# 导入配置
source /opt/gitlab/custom_hooks/config.sh

# 日志记录函数
log_rejection() {
  local commit_hash="$1"
  local reason="$2"
  local file_path="${3:-N/A}"

  if [ "$LOG_ENABLED" = true ]; then
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] REJECTED - Commit: ${commit_hash} - File: ${file_path} - Reason: ${reason}" >> "$LOG_FILE"
  fi
}

# 错误格式化输出
print_error() {
  local commit_hash="$1"
  local reason="$2"
  local details="$3"

  echo "==================================================================="
  echo "[REJECTED] 提交 ${commit_hash:0:8} 未通过校验"
  echo "原因: ${reason}"
  echo "详情: ${details}"
  echo "==================================================================="
}

模块 3: 校验逻辑 (modules/validator.sh)

#!/bin/bash

# 导入依赖
source /opt/gitlab/custom_hooks/config.sh
source /opt/gitlab/custom_hooks/modules/log.sh
source /opt/gitlab/custom_hooks/modules/utils.sh

# 提交信息校验
validate_commit_message() {
  local commit="$1"
  local msg=$(git log --format=%B -n 1 "$commit")
  
  if ! [[ "$msg" =~ $COMMIT_MSG_REGEX ]]; then
    print_error "$commit" "提交信息格式错误" "要求格式: ${COMMIT_MSG_REGEX}\n实际内容: ${msg}"
    log_rejection "$commit" "Invalid commit message" 
    return 1
  fi
  return 0
}

# 文件白名单检查
is_whitelisted() {
  local file="$1"
  
  for pattern in "${WHITELIST_PATTERNS[@]}"; do
    if [[ "$file" == $pattern ]]; then
      return 0
    fi
  done
  return 1
}

# 文件大小校验
validate_file_size() {
  local commit="$1"
  
  # 使用 null 分隔符处理特殊文件名
  git diff-tree -z --no-commit-id --name-only -r "$commit" | while IFS= read -r -d '' file; do
    [ -z "$file" ] && continue

    # 白名单跳过
    if is_whitelisted "$file"; then
      echo "[INFO] 跳过白名单文件: $file"
      continue
    fi

    # 获取文件大小
    file_size=$(git cat-file -s "$commit:$file" 2>/dev/null)
    [ $? -ne 0 ] && continue  # 忽略已删除文件

    if [ "$file_size" -gt "$MAX_FILE_SIZE" ]; then
      print_error "$commit" "文件大小超限" "文件: ${file}\n限制: $((MAX_FILE_SIZE/1024/1024))MB, 实际: $((file_size/1024/1024))MB"
      log_rejection "$commit" "File size exceeded" "$file"
      return 1
    fi
  done

  return 0
}

模块 4: 工具函数 (modules/utils.sh)

#!/bin/bash

# 安全获取提交列表
get_safe_commit_list() {
  local oldrev="$1"
  local newrev="$2"
  
  # 限制处理的提交数量防止内存溢出
  git rev-list --max-count=$MAX_COMMITS_PROCESS "$oldrev".."$newrev"
}

# 检查是否为新分支创建
is_new_branch() {
  [ "$oldrev" = "0000000000000000000000000000000000000000" ]
}

主入口脚本 (pre-receive)

#!/bin/bash

# 初始化环境
HOOKS_DIR="$(dirname "$0")"
source "$HOOKS_DIR/config.sh"
source "$HOOKS_DIR/modules/utils.sh"
source "$HOOKS_DIR/modules/validator.sh"
source "$HOOKS_DIR/modules/log.sh"

# 主处理流程
while read -r oldrev newrev refname; do
  # 跳过空新修订(删除分支)
  [ -z "$newrev" ] && continue

  # 处理新分支创建场景
  is_new_branch && oldrev="${newrev}^"

  # 获取安全提交列表
  commits=$(get_safe_commit_list "$oldrev" "$newrev")

  # 遍历每个提交
  for commit in $commits; do
    validate_commit_message "$commit" || exit 1
    validate_file_size "$commit" || exit 1
  done
done

exit 0

部署步骤

  1. 创建目录结构

    sudo mkdir -p /opt/gitlab/custom_hooks/{modules,logs}
    sudo chown -R git:git /opt/gitlab/custom_hooks
    
  2. 设置权限

    sudo chmod -R 755 /opt/gitlab/custom_hooks
    sudo chmod 644 /opt/gitlab/custom_hooks/logs/hook_audit.log
    
  3. 链接到仓库

    # 进入目标仓库的 hooks 目录
    cd /var/opt/gitlab/git-data/repositories/<group>/<project>.git/custom_hooks/
    
    # 创建软链接
    ln -s /opt/gitlab/custom_hooks/pre-receive .
    

验证测试

测试用例 1:提交信息违规

git commit --allow-empty -m "invalid message"
git push origin main

# 预期输出:
# [REJECTED] 提交 xxxxxxxx 未通过校验
# 原因: 提交信息格式错误

测试用例 2:文件大小超限

dd if=/dev/zero of=oversize_file bs=1M count=101
git add oversize_file
git commit -m "TASK-001: Add large file"
git push origin main

# 预期输出:
# [REJECTED] 提交 xxxxxxxx 未通过校验
# 原因: 文件大小超限
remote: -------------------------------------------------------------------
remote: [REJECTED] 提交 7e624af8 包含超大文件: oversize_file
remote: 大小限制: 100MB, 实际大小: 110MB
remote: -------------------------------------------------------------------
To ssh://<gitlab-url>/test/test.git
 ! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'ssh://<gitlab-url>/test/test.git'

检查日志

tail -f /opt/gitlab/custom_hooks/logs/hook_audit.log
# 输出示例:
# [2023-10-05 14:30:00] REJECTED - Commit: a1b2c3d4 - File: oversize_file - Reason: File size exceeded

此设计实现了以下关键特性:

  1. 模块解耦:各功能独立成模块,修改校验规则无需改动主流程
  2. 安全防护
    • 限制处理的最大提交数量 (MAX_COMMITS_PROCESS)
    • 使用 null 分隔符处理特殊文件名
  3. 审计追踪:详细日志记录所有拒绝操作
  4. 灵活配置:白名单机制和阈值参数集中管理

如需扩展功能(如添加新的校验规则),只需创建新模块并在主流程中调用即可。这种架构特别适合需要统一管理多个 GitLab 仓库的企业环境。

相关文章

  • gitlab pre-receive钩子

    概述 当我们需要对git提交的相关内容做校验时,可以使用服务端的pre-receive钩子。相对于客户端的pre-...

  • 基于 schema 的数据校验

    前端开发中,对要提交的表单数据进行校验是很常见的需求,有开源的基于框架的数据校验库,也有组件库内置的校验功能,这里...

  • 普元 NUI框架使用经验积累

    1.两种方式获取数据 onCellValidation函数是提交前对整个表单进行校验field="ordernum...

  • Springboot请求参数校验

    前端提交的请求参数需要进行校验,如果使用if else语句校验,比较繁琐。使用@Valid和@Validated注...

  • 封装axios请求并对提交参数进行校验

    本文同步更新于我的github点击前往。主要讲解如何拦截axios请求,并对请求参数进行校验,防止提交非法值。当然...

  • 表单验证(WTF)

    官方文档在Flask项目开发中针对提交表单的校验,可以使用Flask-WTF扩展库进行快速的字段校验,也可以进行页...

  • Validation(服务器端校验)

    需求在商品信息修改提交时对商品信息内容进行校验,例如商品名称必须输入,价格合法性校验。 加入jar包 配置vali...

  • Android:提交 pull request 请求

    Android:提交 pull request 请求 首先打开 Gitlab 按下图进行操作 先点击 Files ...

  • IOS 正则表达式验证

    转载自 广告比较多的网站 一、对邮箱进行校验 二、对身份证号进行校验 三、对固话进行校验 eg:010-8877...

  • 对485进行校验

    一直以为传感器很稳定,所以 485 出来的也很靠谱。很明显被打脸了,我们采集到了很诡异的数据。我们分析认为是数据丢...

网友评论

      本文标题:Gitlab pre-receive 对提交进行校验

      本文链接:https://www.haomeiwen.com/subject/xfefbjtx.html