build(git-hooks): enforce Conventional Commits via a hook + CI, record history decision
The convention was documented in CONTRIBUTING.md but nothing enforced it, and no decision was on record for the pre-self-hosting `Phase` history. - tools/git-hooks/commit-msg — rejects a summary that is not a Conventional Commit. tools/git-hooks/lib.sh holds the single rule (types, scope, `!`, and the merge/revert/autosquash exemptions) so the hook and CI cannot drift. - tools/git-hooks/lint-range.sh — lints a commit range with that same rule. - .forgejo/workflows/commit-lint.yml — runs it over the new commits on every push and PR, as the backstop for contributors who have not enabled the hook. - Fix the pre-commit hook, which pointed at the old build/ludic-fmt path (the toolchain moved to bin/) and so silently no-op'd; it now finds bin/ludic-fmt. - CONTRIBUTING.md — full type/scope table, the one-line enable (`git config core.hooksPath tools/git-hooks`), and a **Git history** section recording the decision: leave the pushed `Phase`-era history as-is (a rewrite is destructive and non-reversible for anyone who cloned); enforce the convention going forward; let #33's first release tag double as the clean `v0` baseline that brackets the old prefix without touching a commit. Verified: the hook accepts feat/fix/ci/refactor(!)/merge/revert and rejects "added regex" / "Fix bug" / "WIP"; lint-range passes recent history and flags the old `Phase 8b:` commit. Closes #34 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
1c1192e7c0
commit
709465cdd8
6 changed files with 193 additions and 6 deletions
25
tools/git-hooks/commit-msg
Executable file
25
tools/git-hooks/commit-msg
Executable file
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
# Reject a commit whose summary line is not a Conventional Commit.
|
||||
#
|
||||
# Enable every hook in this directory at once with:
|
||||
#
|
||||
# git config core.hooksPath tools/git-hooks
|
||||
#
|
||||
# (git then runs the hooks straight from the tree — no per-hook symlink, and new
|
||||
# hooks activate as soon as they land on your branch.)
|
||||
set -e
|
||||
MSG_FILE="$1"
|
||||
|
||||
# The header is the first line that is neither blank nor a comment (git strips
|
||||
# '#' lines itself, but a commit-msg hook runs before that, so skip them here).
|
||||
HEADER=$(grep -vE '^[[:space:]]*#' "$MSG_FILE" | sed '/^[[:space:]]*$/d' | head -n1)
|
||||
|
||||
. "$(dirname "$0")/lib.sh"
|
||||
|
||||
if conventional_ok "$HEADER"; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "commit-msg hook: rejected." >&2
|
||||
conventional_help "$HEADER" >&2
|
||||
exit 1
|
||||
Loading…
Add table
Add a link
Reference in a new issue