picoclaw/scripts/hooks/commit-msg
ZanzyTHEbar 3186c2d216 chore: add pre-commit and commit-msg git hooks
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.
2026-02-19 13:29:03 +00:00

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