diff --git a/AGENTS.md b/AGENTS.md index ee94d42..2be39e4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -108,9 +108,9 @@ cargo build --workspace --release ./scripts/ci-checks.sh # fmt --check, clippy -D warnings, test, markdown gate, wiki-lint --strict ``` -A `git push` to `main` also runs this gate through the pre-push hook (install -once: `ln -sf ../../scripts/pre-push .git/hooks/pre-push`). The hook rejects -the push if any gate fails; bypass only in emergencies with `--no-verify`. +A `git push` to `main` also runs this gate through the pre-push hook +(activate once: `./scripts/install-hooks.sh`). The hook rejects the push if +any gate fails; bypass only in emergencies with `--no-verify`. `.forgejo/workflows/ci.yml` encodes the same checks, but **no Actions runner is currently registered**, so nothing enforces them server-side. Until a runner is diff --git a/docs/wiki/quality-gates.md b/docs/wiki/quality-gates.md index 26a91a5..2757faa 100644 --- a/docs/wiki/quality-gates.md +++ b/docs/wiki/quality-gates.md @@ -11,7 +11,7 @@ A change is not "done" until the gate passes locally: ``` The pre-push hook (`scripts/pre-push`) runs this same gate on every `git push` -to `main` — install once with `ln -sf ../../scripts/pre-push .git/hooks/pre-push`. +to `main` — activate once per clone with `./scripts/install-hooks.sh`. The hook rejects the push if any gate fails; bypass only in emergencies with `--no-verify`. diff --git a/scripts/install-hooks.sh b/scripts/install-hooks.sh new file mode 100755 index 0000000..efc0328 --- /dev/null +++ b/scripts/install-hooks.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# Install git hooks for this clone. Run once per clone (idempotent). +# +# ./scripts/install-hooks.sh +# +# After this, every `git push` runs ci-checks.sh + wiki-lint --strict and +# rejects the push if the gate fails. Bypass only with --no-verify. +set -eu + +repo_root="$(git rev-parse --show-toplevel)" +src="${repo_root}/scripts/pre-push" +[ -f "$src" ] || { echo "error: ${src} not found" >&2; exit 1; } +chmod +x "$src" + +# --git-path resolves the real hooks dir even in worktrees / custom git dirs, +# where .git is a file or the hooks live outside /.git/hooks. +cd "$repo_root" +hooks_dir="$(git rev-parse --git-path hooks)" +mkdir -p "$hooks_dir" + +# Symlink to the absolute source path → robust regardless of where the hooks +# dir actually lives (a relative target breaks for worktrees). +ln -sf "$src" "${hooks_dir}/pre-push" +echo "hooks installed: pre-push -> ${src}"