diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 0000000..b2d1b69 --- /dev/null +++ b/.husky/commit-msg @@ -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" diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..d6e3eeb --- /dev/null +++ b/.husky/pre-commit @@ -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 " + 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 diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100755 index 0000000..c4392cf --- /dev/null +++ b/.husky/pre-push @@ -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: +# +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 diff --git a/commitlint.config.ts b/commitlint.config.ts new file mode 100644 index 0000000..76dcb70 --- /dev/null +++ b/commitlint.config.ts @@ -0,0 +1,7 @@ +import type { UserConfig } from "@commitlint/types"; + +const config: UserConfig = { + extends: ["@commitlint/config-conventional"], +}; + +export default config;