ludic/.forgejo/workflows/commit-lint.yml
Orkuncakilkaya 709465cdd8
All checks were successful
bootstrap / cfree-fixpoint (push) Successful in 12s
ci / build-and-test (push) Successful in 50s
commit-lint / conventional-commits (push) Successful in 3s
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>
2026-08-30 23:30:45 +03:00

48 lines
1.8 KiB
YAML

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"