chore(hooks): enforce conventional commits and the branch policy
commitlint has been sitting in the repo wired to nothing. Hook it up: commit-msg lints the message, pre-commit formats staged files and blocks direct commits to main, pre-push blocks pushing it. The test suite deliberately does not run in pre-commit. It runs in checks.yml on every PR and locally via `make preflight`, and a full `turbo run test` on every commit would tax exactly the fast checkpoint commits this repo lives on while catching nothing the PR gate would not. A hook is only ever a courtesy — it can be skipped with --no-verify — so CI runs the same rules over a PR's commits.
This commit is contained in:
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
# Conventional Commits, enforced. commitlint.config.ts has been in this repo
|
||||
# since the beginning wired to nothing, which is why the log is a wall of
|
||||
# "checkpoint". checks.yml runs the same rule over a PR's commits, because a
|
||||
# hook is only ever a courtesy — it can be skipped with --no-verify.
|
||||
pnpm commitlint --edit "$1"
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
#!/bin/sh
|
||||
# Block direct commits to main — branch first, then open a PR. This and the
|
||||
# pre-push guard are the only main protection there is until the repo has a
|
||||
# remote with branch protection turned on (see .github/README.md).
|
||||
branch="$(git rev-parse --abbrev-ref HEAD)"
|
||||
if [ "$branch" = "main" ]; then
|
||||
echo "✖ Direct commits to 'main' are blocked — branch first: git switch -c <name>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The test suite deliberately does NOT run here. It runs in checks.yml on every
|
||||
# PR, and locally via `make preflight` before you open one. A full `turbo run
|
||||
# test` on every commit taxes exactly the fast checkpoint commits this repo
|
||||
# lives on, and catches nothing that the PR gate would not.
|
||||
|
||||
# ultracite
|
||||
# Check if there are any staged files
|
||||
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR)
|
||||
if [ -z "$STAGED_FILES" ]; then
|
||||
echo "No staged files to format"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Run formatter, capturing the exit code so we can still re-stage and report
|
||||
FORMAT_EXIT_CODE=0
|
||||
pnpm dlx ultracite fix || FORMAT_EXIT_CODE=$?
|
||||
|
||||
# Re-stage files that were already staged
|
||||
echo "$STAGED_FILES" | while IFS= read -r file; do
|
||||
if [ -f "$file" ]; then
|
||||
git add -- "$file"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $FORMAT_EXIT_CODE -ne 0 ]; then
|
||||
echo "Ultracite found issues that could not be auto-fixed."
|
||||
exit $FORMAT_EXIT_CODE
|
||||
fi
|
||||
|
||||
echo "✨ Files formatted by Ultracite"
|
||||
# ultracite end
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
# Block pushing to main — open a PR from a branch instead.
|
||||
#
|
||||
# git feeds pre-push the refs being pushed on stdin, one per line:
|
||||
# <local_ref> <local_sha> <remote_ref> <remote_sha>
|
||||
while read -r _local_ref _local_sha remote_ref _remote_sha; do
|
||||
case "$remote_ref" in
|
||||
refs/heads/main)
|
||||
echo "✖ Pushing to 'main' is blocked — open a PR from your branch."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
@@ -0,0 +1,7 @@
|
||||
import type { UserConfig } from "@commitlint/types";
|
||||
|
||||
const config: UserConfig = {
|
||||
extends: ["@commitlint/config-conventional"],
|
||||
};
|
||||
|
||||
export default config;
|
||||
Reference in New Issue
Block a user