fix(commit): AGENTS 규칙과 커밋 메시지 검사 스크립트를 정합화한다
This commit is contained in:
@@ -1,71 +1,121 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Check if a commit message follows project rules
|
||||
# Rules: 50/72 formatting, no advertisements/branding
|
||||
# Usage: ./check-commit-message-rules.sh [commit-hash]
|
||||
# If no commit-hash is provided, checks the latest commit
|
||||
print_usage() {
|
||||
echo "Usage:"
|
||||
echo " $0"
|
||||
echo " $0 <commit-hash>"
|
||||
echo " $0 --message \"<commit-message>\""
|
||||
echo " $0 --message-file <file-path>"
|
||||
}
|
||||
|
||||
# Determine which commit to check
|
||||
if [ $# -eq 0 ]; then
|
||||
commit_ref="HEAD"
|
||||
echo "Checking latest commit..."
|
||||
else
|
||||
commit_ref="$1"
|
||||
echo "Checking commit: $commit_ref"
|
||||
fi
|
||||
load_commit_message() {
|
||||
if [ $# -eq 0 ]; then
|
||||
local commit_ref="HEAD"
|
||||
echo "Checking latest commit..." >&2
|
||||
git log -1 --pretty=format:"%s%n%b" "$commit_ref"
|
||||
return
|
||||
fi
|
||||
|
||||
# Get the commit message
|
||||
commit_message=$(git log -1 --pretty=format:"%s%n%b" "$commit_ref")
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
--message)
|
||||
shift
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "[FAIL] --message option requires a commit message"
|
||||
print_usage
|
||||
exit 1
|
||||
fi
|
||||
echo "Checking provided commit message..." >&2
|
||||
printf '%s' "$*"
|
||||
;;
|
||||
--message-file)
|
||||
shift
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "[FAIL] --message-file option requires a file path"
|
||||
print_usage
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "$1" ]; then
|
||||
echo "[FAIL] Commit message file not found: $1"
|
||||
exit 1
|
||||
fi
|
||||
echo "Checking commit message file: $1" >&2
|
||||
cat "$1"
|
||||
;;
|
||||
*)
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "[FAIL] Invalid arguments"
|
||||
print_usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Split into subject and body
|
||||
subject=$(echo "$commit_message" | head -n1)
|
||||
body=$(echo "$commit_message" | tail -n +2 | sed '/^$/d')
|
||||
local commit_ref="$1"
|
||||
if ! git rev-parse --verify "$commit_ref^{commit}" >/dev/null 2>&1; then
|
||||
echo "[FAIL] Invalid commit reference: $commit_ref"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checking commit: $commit_ref" >&2
|
||||
git log -1 --pretty=format:"%s%n%b" "$commit_ref"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
commit_message=$(load_commit_message "$@")
|
||||
subject=$(printf '%s\n' "$commit_message" | head -n1)
|
||||
body=$(printf '%s\n' "$commit_message" | tail -n +2)
|
||||
|
||||
echo "Checking commit message format..."
|
||||
echo "Subject: $subject"
|
||||
|
||||
# Check subject line length
|
||||
subject_length=${#subject}
|
||||
if [ $subject_length -gt 50 ]; then
|
||||
echo "[FAIL] Subject line too long: $subject_length characters (max 50)"
|
||||
exit_code=1
|
||||
else
|
||||
echo "[PASS] Subject line length OK: $subject_length characters"
|
||||
exit_code=0
|
||||
exit_code=0
|
||||
|
||||
if [ -z "$subject" ]; then
|
||||
echo "[FAIL] Subject must not be empty"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check body line lengths if body exists
|
||||
if [ -n "$body" ]; then
|
||||
echo "Checking body line lengths..."
|
||||
while IFS= read -r line; do
|
||||
line_length=${#line}
|
||||
if [ $line_length -gt 72 ]; then
|
||||
echo "[FAIL] Body line too long: $line_length characters (max 72)"
|
||||
echo "Line: $line"
|
||||
exit_code=1
|
||||
fi
|
||||
done <<< "$body"
|
||||
subject_pattern='^([a-z]+)(\([a-z0-9._/-]+\))?(!)?: (.+)$'
|
||||
if [[ "$subject" =~ $subject_pattern ]]; then
|
||||
type="${BASH_REMATCH[1]}"
|
||||
description="${BASH_REMATCH[4]}"
|
||||
|
||||
if [ $exit_code -eq 0 ]; then
|
||||
echo "[PASS] All body lines within 72 characters"
|
||||
echo "[PASS] Subject follows Conventional Commit format"
|
||||
echo "[PASS] Type is lowercase: $type"
|
||||
|
||||
if printf '%s\n' "$description" | grep -Eq '[가-힣]'; then
|
||||
echo "[PASS] Description contains Korean text"
|
||||
else
|
||||
echo "[FAIL] Description must contain Korean text"
|
||||
exit_code=1
|
||||
fi
|
||||
else
|
||||
echo "[INFO] No body content to check"
|
||||
echo "[FAIL] Subject must match: <type>(scope): <description>"
|
||||
echo " scope is optional, example: feat: 기능을 추가한다"
|
||||
exit_code=1
|
||||
fi
|
||||
|
||||
# Check for advertisements, branding, or promotional content
|
||||
echo "Checking for advertisements and branding..."
|
||||
if echo "$commit_message" | grep -qi "generated with\|claude code\|anthropic\|co-authored-by.*claude\|🤖"; then
|
||||
echo "[FAIL] Commit message contains advertisements, branding, or promotional content"
|
||||
exit_code=1
|
||||
else
|
||||
echo "[PASS] No advertisements or branding detected"
|
||||
if [ -n "$body" ] && printf '%s\n' "$body" | grep -Eq '^Refs:'; then
|
||||
while IFS= read -r refs_line; do
|
||||
if ! printf '%s\n' "$refs_line" | grep -Eq '^Refs: #[0-9]+(, #[0-9]+)*$'; then
|
||||
echo "[FAIL] Refs footer format is invalid: $refs_line"
|
||||
echo " expected format: Refs: #123 or Refs: #123, #456"
|
||||
exit_code=1
|
||||
fi
|
||||
done < <(printf '%s\n' "$body" | grep -E '^Refs:')
|
||||
|
||||
if [ $exit_code -eq 0 ]; then
|
||||
echo "[PASS] Refs footer format is valid"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $exit_code -eq 0 ]; then
|
||||
echo "[PASS] Commit message follows all rules"
|
||||
echo "[PASS] Commit message follows AGENTS.md rules"
|
||||
else
|
||||
echo "[FAIL] Commit message violates project rules"
|
||||
echo "[FAIL] Commit message violates AGENTS.md rules"
|
||||
fi
|
||||
|
||||
exit $exit_code
|
||||
|
||||
Reference in New Issue
Block a user