From 3b1e7d198251adb0120c2e4ceca2a16849dddb8a Mon Sep 17 00:00:00 2001 From: alvinlollo Date: Tue, 13 Oct 2026 18:07:05 +1100 Subject: [PATCH] chore: Add pre-commit hook running shellcheck on every commit --- AGENTS.md | 10 +++++++++ README.md | 16 +++++++++++++- githooks/pre-commit | 51 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100755 githooks/pre-commit diff --git a/AGENTS.md b/AGENTS.md index a42cbfa..857ed54 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -97,6 +97,16 @@ yamllint -d "{extends: relaxed, rules: {document-start: disable, line-length: di `packages.x86_64` syntax: one package per line, `[a-zA-Z0-9._@+\-]+` only, no trailing whitespace. +A **pre-commit hook** (`githooks/pre-commit`) runs the same ShellCheck pass on every +commit, so CI failures surface before you push. Enable it once per clone: + +```bash +git config core.hooksPath githooks +``` + +It skips linting (with a warning) when `shellcheck` is missing rather than blocking the +commit; CI remains the enforcer. Bypass it with `git commit --no-verify`. + ## Gotchas - The profile root is the **repo root** (not a `releng/` subdirectory). CI builds with `mkarchiso -v -w "$PWD/work" -o "$PWD/out" -- "$PWD"` (`.gitea/workflows/build-iso.yaml`), and the local build command above does the same — never pass a `releng` path. diff --git a/README.md b/README.md index 98f93d3..6f8ce2b 100644 --- a/README.md +++ b/README.md @@ -384,11 +384,25 @@ sudo mkarchiso -v -w work -o out/ . ### CI Checks (must pass before merge) -- **ShellCheck**: all `.sh` files checked with `shellcheck -x -s bash` +- **ShellCheck**: all `.sh` files, plus extensionless bash scripts in `airootfs/usr/local/bin/`, checked with `shellcheck -x -s bash` - **yamllint**: all `.yml`/`.yaml` files (relaxed config) - **packages.x86_64 syntax**: one package per line, no trailing whitespace, `[a-zA-Z0-9._@+\-]+` only - **Package repo check**: every package in `packages.x86_64` must be resolvable via `pacman -Si` in allowed repos (`cachyos`, `extra`, `multilib`, `chaotic-aur`), OR have a pre-built `.pkg.tar.zst` in `localrepo/`, OR appear in `localrepo/build-end4-deps.sh` +### Git Hooks + +A pre-commit hook (`githooks/pre-commit`) runs the ShellCheck pass on every commit, so lint failures surface before you push instead of in CI. + +```bash +# Enable once per clone +git config core.hooksPath githooks + +# Bypass the hook for a single commit +git commit --no-verify +``` + +If `shellcheck` is not installed the hook warns and skips rather than blocking the commit; CI remains the enforcer. + ### Recommended VirtualBox Settings (for testing) - RAM: 4GB minimum, 8GB recommended diff --git a/githooks/pre-commit b/githooks/pre-commit new file mode 100755 index 0000000..464f30a --- /dev/null +++ b/githooks/pre-commit @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# pre-commit hook: run ShellCheck on every shell script in the repo. +# +# This mirrors the CI check in .gitea/workflows/tests.yaml so the local +# lint and the CI lint cannot drift apart. Enable it in a clone with: +# +# git config core.hooksPath githooks + +set -u + +if ! command -v shellcheck >/dev/null 2>&1; then + echo "pre-commit: shellcheck not found on PATH, skipping lint." >&2 + echo "pre-commit: install it with 'pacman -S shellcheck'; CI still enforces it." >&2 + exit 0 +fi + +# Same file set as CI: *.sh plus the extensionless bash scripts in +# airootfs/usr/local/bin picked up by their shebang. +# find's stderr is dropped because localrepo/end4-pkgbuilds/*/pkg is left +# at mode d--x--x--x by makepkg and prints "Permission denied" locally. +sh_files=$( + { + find . -name '*.sh' -not -path './.git/*' 2>/dev/null + find airootfs/usr/local/bin -type f ! -name '*.sh' \ + -exec grep -lE '^#!(/usr/bin/env bash|/bin/bash)' {} + 2>/dev/null + } | sed '/^$/d' | sort -u +) + +if [ -z "$sh_files" ]; then + echo "pre-commit: no shell scripts found." + exit 0 +fi + +failed=0 +while IFS= read -r f; do + if shellcheck -x -s bash "$f"; then + echo " ok $f" + else + echo " FAIL $f" >&2 + failed=1 + fi +done <<< "$sh_files" + +if [ "$failed" -ne 0 ]; then + echo "" >&2 + echo "pre-commit: ShellCheck failed. Fix the issues above, or bypass with:" >&2 + echo " git commit --no-verify" >&2 + exit 1 +fi + +exit 0