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
48
.forgejo/workflows/commit-lint.yml
Normal file
48
.forgejo/workflows/commit-lint.yml
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
name: commit-lint
|
||||
|
||||
# Enforce Conventional Commits in CI, as a backstop to the local commit-msg hook
|
||||
# (which a contributor only gets after `git config core.hooksPath tools/git-hooks`).
|
||||
# Lints every new commit's summary line against tools/git-hooks/lib.sh — the same
|
||||
# rule the hook uses, so the two can never drift.
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
conventional-commits:
|
||||
runs-on: docker
|
||||
container: node:20-bookworm
|
||||
steps:
|
||||
- name: Check out with history
|
||||
env:
|
||||
BEFORE: ${{ github.event.before }}
|
||||
BASE: ${{ github.base_ref }}
|
||||
run: |
|
||||
set -eu
|
||||
git config --global --add safe.directory '*'
|
||||
# Full clone so both endpoints of the range are present.
|
||||
git clone https://git.workshopsoft.io/workshopsoft/ludic.git .
|
||||
git checkout "${GITHUB_SHA}" 2>/dev/null || git checkout "${GITHUB_REF_NAME:-main}"
|
||||
|
||||
- name: Lint the new commits
|
||||
env:
|
||||
BEFORE: ${{ github.event.before }}
|
||||
BASE: ${{ github.base_ref }}
|
||||
run: |
|
||||
set -eu
|
||||
# Pick the range of *new* commits to lint:
|
||||
# - pull_request: base branch .. this commit
|
||||
# - push: the pushed range (event.before .. this commit)
|
||||
# - new branch / unknown: just the tip commit
|
||||
if [ -n "${BASE:-}" ]; then
|
||||
git fetch --quiet origin "${BASE}" 2>/dev/null || true
|
||||
RANGE="origin/${BASE}..${GITHUB_SHA}"
|
||||
elif [ -n "${BEFORE:-}" ] && ! printf '%s' "$BEFORE" | grep -qE '^0+$'; then
|
||||
RANGE="${BEFORE}..${GITHUB_SHA}"
|
||||
else
|
||||
RANGE="${GITHUB_SHA}~1..${GITHUB_SHA}"
|
||||
fi
|
||||
echo "linting range: $RANGE"
|
||||
sh tools/git-hooks/lint-range.sh "$RANGE"
|
||||
Loading…
Add table
Add a link
Reference in a new issue