Install via `make hooks`. Pre-commit runs format check, go vet, build, and tests on staged Go files with clear pass/fail output. Commit-msg validates Conventional Commits format. Both hooks skip gracefully and can be bypassed with --no-verify.
65 lines
2.7 KiB
Bash
Executable file
65 lines
2.7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# picoclaw commit-msg hook
|
|
#
|
|
# Validates commit messages against Conventional Commits 1.0.0.
|
|
# Install: make hooks
|
|
# Skip: git commit --no-verify
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
BOLD='\033[1m'
|
|
DIM='\033[2m'
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
MSG_FILE="$1"
|
|
SUBJECT=$(head -1 "$MSG_FILE")
|
|
|
|
# Allow merge commits and reverts untouched
|
|
if [[ "$SUBJECT" =~ ^Merge\ branch ]] || [[ "$SUBJECT" =~ ^Revert\ \" ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
# ── Conventional Commit regex ────────────────────────────────────────────────
|
|
# type(optional-scope)optional-!: description
|
|
TYPES="feat|fix|refactor|perf|style|test|docs|build|ops|chore|ci|revert"
|
|
PATTERN="^(${TYPES})(\([a-zA-Z0-9._-]{1,30}\))?\!?: .{1,100}$"
|
|
|
|
if [[ "$SUBJECT" =~ $PATTERN ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
# ── Failure output ───────────────────────────────────────────────────────────
|
|
|
|
echo ""
|
|
printf " ${RED}${BOLD}Invalid commit message${NC}\n"
|
|
printf " ${DIM}────────────────────────────────────────────${NC}\n"
|
|
printf " ${DIM}Got:${NC} %s\n" "$SUBJECT"
|
|
echo ""
|
|
printf " ${BOLD}Expected format:${NC}\n"
|
|
printf " ${CYAN}type${NC}${DIM}(scope)${NC}${DIM}!${NC}: ${CYAN}description${NC}\n"
|
|
echo ""
|
|
printf " ${BOLD}Types:${NC} ${DIM}%s${NC}\n" "$TYPES"
|
|
echo ""
|
|
printf " ${BOLD}Examples:${NC}\n"
|
|
printf " feat(memory): add KV store subsystem\n"
|
|
printf " fix: prevent nil pointer in session cleanup\n"
|
|
printf " refactor(agent)!: replace provider interface\n"
|
|
printf " docs: update roadmap with completed milestones\n"
|
|
echo ""
|
|
printf " ${BOLD}Rules:${NC}\n"
|
|
printf " ${DIM}•${NC} Type is required (see list above)\n"
|
|
printf " ${DIM}•${NC} Scope is optional, max 30 chars, in parentheses\n"
|
|
printf " ${DIM}•${NC} Description: imperative, lowercase start, no period\n"
|
|
printf " ${DIM}•${NC} Max subject line: 100 characters\n"
|
|
printf " ${DIM}•${NC} Add ${BOLD}!${NC} before ${BOLD}:${NC} for breaking changes\n"
|
|
echo ""
|
|
printf " ${DIM}Skip: git commit --no-verify${NC}\n"
|
|
echo ""
|
|
|
|
exit 1
|