update-changelog-precommit.sh 3.74 KB
#!/bin/bash

# ============================================
# CHANGELOG 自动更新脚本(Pre-commit 版本)
# ============================================
#
# 功能:在提交前更新 CHANGELOG.md,包含在当前提交中
# 使用:在 pre-commit hook 中调用
#
# 作者:Claude Code
# 日期:2026-02-28
# ============================================

set -e

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 参数
COMMIT_MSG_FILE=$1
CHANGELOG_FILE="CHANGELOG.md"

# 检查文件是否存在
if [ ! -f "$CHANGELOG_FILE" ]; then
    echo "  ${YELLOW}⚠️  CHANGELOG.md 不存在,跳过自动更新${NC}"
    exit 0
fi

# 读取 commit message
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")

# 解析 commit message
# 格式: type(scope): subject
if ! echo "$COMMIT_MSG" | grep -qE "^([a-z]+)\(([a-z-]+)\): .{1,50}"; then
    echo "  ${YELLOW}⚠️  Commit message 格式不匹配,跳过自动更新${NC}"
    exit 0
fi

# 提取信息
COMMIT_TYPE=$(echo "$COMMIT_MSG" | head -n 1 | sed -E 's/^([a-z]+)\(.*/\1/')
COMMIT_SCOPE=$(echo "$COMMIT_MSG" | head -n 1 | sed -E 's/^[a-z]+\(([a-z-]+)\).*/\1/')
COMMIT_SUBJECT=$(echo "$COMMIT_MSG" | head -n 1 | sed -E 's/^[a-z]+\([a-z-]+\): (.*)$/\1/')

# 类型映射到中文
case "$COMMIT_TYPE" in
    feat)
        CHANGE_TYPE="新增"
        ;;
    fix)
        CHANGE_TYPE="修复"
        ;;
    docs)
        CHANGE_TYPE="文档"
        ;;
    style)
        CHANGE_TYPE="样式"
        ;;
    refactor)
        CHANGE_TYPE="优化"
        ;;
    perf)
        CHANGE_TYPE="性能"
        ;;
    test)
        CHANGE_TYPE="测试"
        ;;
    chore)
        CHANGE_TYPE="配置"
        ;;
    revert)
        CHANGE_TYPE="回滚"
        ;;
    *)
        CHANGE_TYPE="其他"
        ;;
esac

# 获取当前日期和时间
TODAY=$(date +%Y-%m-%d)
NOW_TIME=$(date +%H:%M:%S)

# 获取暂存的变更文件(使用 git diff --cached)
CHANGED_FILES=$(git diff --cached --name-only | tr '\n' '\n' | sed 's/^/- \`/;s/$/`/' | sed '$d')
if [ -z "$CHANGED_FILES" ]; then
    CHANGED_FILES="- \`\`"
fi

# 在 pre-commit 阶段还没有 commit hash,使用占位符
COMMIT_HASH="pending"

# 生成 CHANGELOG 条目
CHANGELOG_ENTRY="### $NOW_TIME - $COMMIT_TYPE($COMMIT_SCOPE): $COMMIT_SUBJECT

**影响文件**:
$CHANGED_FILES

**变更摘要**:
- $COMMIT_SUBJECT

**相关提交**:
- \`$COMMIT_HASH\` - $COMMIT_TYPE($COMMIT_SCOPE): $COMMIT_SUBJECT

---

"

# 检查今天是否已有条目
if grep -q "^## $TODAY" "$CHANGELOG_FILE"; then
    # 今天已有条目,找到日期行号,在日期后追加
    DATE_LINE=$(grep -n "^## $TODAY" "$CHANGELOG_FILE" | head -1 | cut -d: -f1)

    # 创建临时文件
    TEMP_FILE=$(mktemp)

    # 读取日期行之前的内容
    head -n $DATE_LINE "$CHANGELOG_FILE" > "$TEMP_FILE"

    # 在日期后追加新条目
    echo "$CHANGELOG_ENTRY" >> "$TEMP_FILE"

    # 追加日期行之后的内容(从日期行+1开始)
    tail -n +$((DATE_LINE + 1)) "$CHANGELOG_FILE" >> "$TEMP_FILE"

    # 替换原文件
    mv "$TEMP_FILE" "$CHANGELOG_FILE"
else
    # 今天没有条目,创建新的日期部分
    TEMP_FILE=$(mktemp)

    # 新建日期标题和条目
    echo "## $TODAY" > "$TEMP_FILE"
    echo "" >> "$TEMP_FILE"
    echo "$CHANGELOG_ENTRY" >> "$TEMP_FILE"
    echo "" >> "$TEMP_FILE"

    # 追加原文件内容
    cat "$CHANGELOG_FILE" >> "$TEMP_FILE"

    # 替换原文件
    mv "$TEMP_FILE" "$CHANGELOG_FILE"
fi

# 将 CHANGELOG.md 加入暂存区(包含在当前提交中)
git add "$CHANGELOG_FILE"

echo "  ${GREEN}✅ CHANGELOG.md 已自动更新并加入暂存区${NC}"
echo "  ${BLUE}   类型: $CHANGE_TYPE${NC}"
echo "  ${BLUE}   范围: $COMMIT_SCOPE${NC}"
echo "  ${BLUE}   描述: $COMMIT_SUBJECT${NC}"