Git钩子脚本如何检查培训计划

wen 实用脚本 1

本文目录导读:

Git钩子脚本如何检查培训计划

  1. 核心工具:Git Hooks
  2. 场景A:提交前强制确认培训完成情况
  3. 场景B:检查“培训计划”文件内容或变更
  4. 场景C:检查提交信息包含培训ID
  5. 最佳实践与注意事项

针对Git钩子脚本检查“培训计划”,这个需求通常需要结合具体场景来理解,因为“培训计划”并不是Git原生的概念(如代码、分支、提交信息),我推测你可能是在以下几种场景之一工作:

  1. 场景A(最可能): 你的团队或企业内部有培训考核流程,要求开发者在提交代码前,必须确认自己已完成某项安全培训或技能培训(git commit 前弹窗提醒“你完成《代码规范》培训了吗?”)。
  2. 场景B: 你的仓库中有一个专门的目录或文件training_plan / 培训计划,你想检查这个文件是否被修改、格式是否正确,或者是否在每次提交时都包含它。
  3. 场景C: 你想在提交信息(commit message)中强制包含培训相关的ID或说明。

下面我会针对最常见的场景A(行为检查)场景B(文件内容检查)提供具体的钩子脚本示例。


核心工具:Git Hooks

钩子脚本位于项目根目录下的 .git/hooks/ 文件夹中,你需要创建一个可执行脚本(如 pre-commit)。

注意: .git/hooks/ 下的文件不会被提交到仓库,如果你想团队共享,需要将脚本放到项目目录(如 hooks/),然后通过 git config core.hooksPath hooks/ 进行配置。


场景A:提交前强制确认培训完成情况

这是最常见的企业级需求,使用 pre-commit 钩子,阻止未完成培训的开发者提交代码。

原理: 脚本读取一个本地文件、环境变量或调用内部API,检查用户是否标记为“已培训”。

示例 1:检查本地标记文件(简单版)

在用户完成培训后,本地生成一个隐藏文件 ~/.training_completed

文件:.git/hooks/pre-commit(需赋予 chmod +x 权限)

#!/bin/bash
# 检查培训标记文件是否存在
TRAINING_FILE="$HOME/.training_completed"
if [ ! -f "$TRAINING_FILE" ]; then
    echo "❌ 错误:您尚未完成《2025年度信息安全培训》!"
    echo "请前往内部培训平台完成培训,完成后系统将自动生成标记。"
    echo "(或联系管理员解决)"
    exit 1 # 非零退出码阻止提交
fi
# 可选:检查文件内容是否包含当前季度
CURRENT_QUARTER=$(date +%Y-Q%q)
if ! grep -q "$CURRENT_QUARTER" "$TRAINING_FILE"; then
    echo "❌ 错误:您的培训记录($(cat $TRAINING_FILE))不在当前周期($CURRENT_QUARTER)。"
    echo "请重新完成季度培训。"
    exit 1
fi
# 检查通过
exit 0

示例 2:调用内部API验证(生产级)

假设你们有一个内部系统 https://train.corp.com/check?user=<username> 返回 {"passed": true}

#!/bin/bash
# 获取当前Git用户
USER_EMAIL=$(git config user.email)
USER_NAME=$(git config user.name)
# 调用内部API(超时2秒,静默失败时允许提交)
RESULT=$(curl -s --connect-timeout 2 --max-time 3 \
    "https://train.corp.com/api/check?email=$USER_EMAIL" 2>/dev/null)
# 检查API是否返回成功
if echo "$RESULT" | grep -q '"passed": true'; then
    exit 0
elif echo "$RESULT" | grep -q '"passed": false'; then
    echo "❌ 提交被拒绝:用户 $USER_NAME 尚未通过【高效代码审查】培训。"
    echo "请访问 https://train.corp.com 完成培训。"
    exit 1
else
    # API不可用时,记录日志但允许提交,避免阻塞开发
    echo "⚠️ 警告:无法连接培训系统,跳过培训检查。(建议尽快修复)" >&2
    exit 0
fi

场景B:检查“培训计划”文件内容或变更

假设仓库里有一个 docs/training_plan.md 文件,你想确保它总是被更新。

示例 3:检查文件是否被修改(pre-commit

检查当前变更中是否包含了 training_plan.md,如果没有则警告。

#!/bin/bash
# 检查暂存区(staged)中是否包含培训计划文件
if ! git diff --cached --name-only | grep -q "training_plan.md"; then
    echo "⚠️ 警告:您的提交未包含 'docs/training_plan.md' 的更新。"
    echo "如果这次提交改变了培训计划,请务必包含该文件。"
    # 这里不 exit 1,只发出警告,如果必须强制,则改为 exit 1
    # exit 1
fi
exit 0

示例 4:检查文件格式是否正确(pre-commit

假设培训计划是一个JSON文件 training/plan.json,必须包含 versionparticipants 字段。

#!/bin/bash
STAGED_PLAN=$(git diff --cached --name-only | grep "training/plan.json")
if [ -n "$STAGED_PLAN" ]; then
    # 获取暂存区中的文件内容
    CONTENT=$(git show :training/plan.json)
    # 使用python或jq检查JSON格式和字段
    echo "$CONTENT" | python3 -c "
import sys, json
try:
    data = json.load(sys.stdin)
    assert 'version' in data, '缺少version字段'
    assert 'participants' in data, '缺少participants字段'
    assert isinstance(data['participants'], list), 'participants必须是数组'
    print('培训计划格式检查通过')
except Exception as e:
    print(f'❌ 培训计划格式错误: {e}')
    sys.exit(1)
" 2>&1 || exit 1 # 如果python检查失败,则退出
fi
exit 0

场景C:检查提交信息包含培训ID

要求每次提交必须包含 TRAINING-123 这样的培训任务ID。

文件:.git/hooks/commit-msg

#!/bin/bash
# commit-msg 钩子接收一个参数:提交信息文件路径
COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
# 检查是否包含培训ID模式(TRAINING-数字 或 TRN-数字)
if ! echo "$COMMIT_MSG" | grep -qE '(TRAINING|TRN)-[0-9]+'; then
    echo "❌ 提交信息错误:必须包含培训任务ID(如 TRAINING-12345)。"
    echo "示例:git commit -m \"fix: 修复登录bug (TRAINING-12345)\""
    exit 1
fi
exit 0

最佳实践与注意事项

  1. 不要完全阻塞开发:如果培训系统API不可用,建议允许提交(如示例2所示),避免开发流程完全中断。
  2. 使用commit-msg而不是pre-commit:如果检查依赖于完整的提交信息,使用 commit-msg 钩子更合适。
  3. 团队共享钩子:将钩子脚本放到项目目录(如 scripts/hooks/)并通过 git config core.hooksPath scripts/hooks/ 共享,但需要确保所有开发者都配置了该路径。
  4. 禁用钩子:永远记住 git commit --no-verify 可以跳过钩子检查,这是合法的逃生舱口,不要恼火。
  5. 避免复杂逻辑:钩子脚本最好轻量、快速,过于复杂的逻辑(如数据库查询)应放在CI/CD阶段。
  • 如果你需要阻止未培训的人提交 → 使用 pre-commit 钩子,结合API检查(示例1/2)。
  • 如果你需要检查培训计划文件的内容 → 使用 pre-commit 钩子,解析文件(示例3/4)。
  • 如果你需要提交信息包含培训编号 → 使用 commit-msg 钩子(示例5)。

请根据你的实际场景选择,如果需要更具体的代码(比如如何从LDAP获取用户组),请补充描述你的“培训计划”具体指什么。

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