feat: commit-msg hook enforces conventional commit format
This commit is contained in:
parent
3276ff4498
commit
5bb665b089
2 changed files with 59 additions and 0 deletions
32
.githooks/commit-msg
Executable file
32
.githooks/commit-msg
Executable file
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env bash
|
||||
# .githooks/commit-msg — enforces conventional commit format
|
||||
# Format: type: description OR type(scope): description
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
||||
|
||||
VALID_TYPES="feat|fix|docs|chore|test|refactor|perf|ci|build"
|
||||
MSG_FILE="$1"
|
||||
MSG=$(head -1 "$MSG_FILE")
|
||||
|
||||
if [[ -z "${MSG// }" ]]; then
|
||||
echo -e "${RED}Commit rejected:${NC} Commit message is empty."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! echo "$MSG" | grep -qE "^($VALID_TYPES)(\(.+\))?: .+"; then
|
||||
echo -e "${RED}Commit rejected:${NC} Message does not follow conventional commit format."
|
||||
echo ""
|
||||
echo -e " Required: ${YELLOW}type: description${NC} or ${YELLOW}type(scope): description${NC}"
|
||||
echo -e " Valid types: ${YELLOW}$VALID_TYPES${NC}"
|
||||
echo ""
|
||||
echo -e " Your message: ${YELLOW}$MSG${NC}"
|
||||
echo ""
|
||||
echo -e " Examples:"
|
||||
echo -e " ${YELLOW}feat: add cover letter refinement${NC}"
|
||||
echo -e " ${YELLOW}fix(wizard): handle missing user.yaml gracefully${NC}"
|
||||
echo -e " ${YELLOW}docs: update tier system reference${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
|
@ -48,3 +48,30 @@ run_hook_with "app/app.py" "import streamlit" && pass "allowed safe file" || \
|
|||
fail "should have allowed safe file"
|
||||
|
||||
echo "All pre-commit hook tests passed."
|
||||
|
||||
# ── commit-msg hook tests ────────────────────────────────────────────────────
|
||||
COMMIT_HOOK=".githooks/commit-msg"
|
||||
tmpfile=$(mktemp)
|
||||
|
||||
echo "Test 5: accepts valid feat message"
|
||||
echo "feat: add thing" > "$tmpfile"
|
||||
bash "$COMMIT_HOOK" "$tmpfile" && pass "accepted feat" || fail "rejected valid feat"
|
||||
|
||||
echo "Test 6: accepts valid fix with scope"
|
||||
echo "fix(auth): handle token expiry" > "$tmpfile"
|
||||
bash "$COMMIT_HOOK" "$tmpfile" && pass "accepted fix(scope)" || fail "rejected valid fix(scope)"
|
||||
|
||||
echo "Test 7: rejects empty message"
|
||||
echo "" > "$tmpfile"
|
||||
bash "$COMMIT_HOOK" "$tmpfile" && fail "should reject empty" || pass "rejected empty"
|
||||
|
||||
echo "Test 8: rejects non-conventional message"
|
||||
echo "updated the thing" > "$tmpfile"
|
||||
bash "$COMMIT_HOOK" "$tmpfile" && fail "should reject non-conventional" || pass "rejected non-conventional"
|
||||
|
||||
echo "Test 9: rejects invalid type"
|
||||
echo "yolo: ship it" > "$tmpfile"
|
||||
bash "$COMMIT_HOOK" "$tmpfile" && fail "should reject invalid type" || pass "rejected invalid type"
|
||||
|
||||
rm -f "$tmpfile"
|
||||
echo "All commit-msg hook tests passed."
|
||||
|
|
|
|||
Loading…
Reference in a new issue