--- project: pre-commit-framework-migration type: project-plan status: active path: Tech/Projects tags: - homelab - tooling - git - ansible - security created: 2026-05-03 updated: 2026-05-03 --- # pre-commit framework migration ## Goal Replace the raw `.git/hooks/pre-commit` bash script (currently shared via `core.hooksPath`) with the [pre-commit framework](https://pre-commit.com), and adopt it as the standard for all new repos. Codify a curated set of checks that catch the mistakes most likely to bite a solo homelab operator working across Python, Go, Ansible, and YAML-heavy infra repos. ## Why The current raw hook works but has limits: - not version-controlled (lives in `.git/hooks/`, not tracked) - single-purpose (vault encryption check only) - adding more checks means growing a bash script - no portability across machines without re-running the `core.hooksPath` setup The framework solves all four: config lives in `.pre-commit-config.yaml` at the repo root, gets committed, and gives access to a large ecosystem of pre-built hooks. ## Scope ### In scope - Install `pre-commit` framework on dev machines - Migrate the existing ansible-vault check from raw bash to a framework hook - Curate a default `.pre-commit-config.yaml` template covering Python, Go, Ansible, YAML, and secret-detection - Document the install/onboarding flow as the standard for new repos - Decide how the framework coexists with (or replaces) the current `core.hooksPath` setup - Add the template to project scaffolding so new repos start with it pre-wired ### Out of scope - Migrating every existing repo today (do them as they're touched) - Full CI integration (pre-commit can also run in GitHub Actions, but that's a follow-up) - Replacing `zero-check` or other post-generation validation skills ## Decisions to confirm - **Coexistence with `core.hooksPath`** — once the framework is in a repo, its `pre-commit install` will overwrite `.git/hooks/pre-commit` for that repo. Need to decide: leave `core.hooksPath` as a fallback for repos without `.pre-commit-config.yaml`, or unset it once all active repos are migrated? - **Vault check location** — keep the bash script in-repo at `scripts/check-vault.sh` (referenced as a `local` hook), or rewrite as a tiny standalone repo and pin like other framework hooks? - **Template repo or scaffold-generated** — does the default `.pre-commit-config.yaml` live in a `homelab-templates` repo for `web_fetch` access, or get generated by the project scaffolding tool? ## Curated check list Grouped by category. Each is a separate hook entry; opt in per repo by what's actually relevant. ### Universal (every repo) - `trailing-whitespace` — strip trailing spaces - `end-of-file-fixer` — ensure files end with a newline - `check-merge-conflict` — block commits with unresolved conflict markers - `check-added-large-files` — block accidental large file commits (default 500KB) - `mixed-line-ending` — enforce LF - `detect-private-key` — block committing SSH/TLS private keys ### Secrets & sensitive data - `detect-secrets` (Yelp) — broader secret scanning beyond just private keys; catches AWS keys, API tokens, high-entropy strings - `gitleaks` — alternative or complement; well-maintained, fast - **Custom: ansible-vault encryption check** — port of the existing bash hook ### YAML / config - `check-yaml` — basic YAML syntax validation - `yamllint` — style + structure (line length, indentation, truthy values) - `check-json` — JSON syntax - `check-toml` — TOML syntax ### Python - `ruff` — lint + format in one tool (replaces flake8, isort, black for most cases) - `ruff-format` — formatter - `mypy` — optional, type-checking (heavier; opt in per project) ### Go - `go-fmt` — gofmt enforcement - `go-vet` — basic static analysis - `golangci-lint` — broader linting (opt in per project) ### Ansible-specific - **Custom: ansible-vault encryption check** (existing logic, ported) - `ansible-lint` — full Ansible playbook/role linting - `yamllint` (already covered above, but Ansible repos lean on it heavily) ### Shell scripts - `shellcheck` — catches common bash bugs and bad patterns - `shfmt` — formatter for shell scripts ### Markdown / docs - `markdownlint` — style/structure for `.md` files - (Skip if it gets noisy on Obsidian-flavored markdown — the project notes use front-matter and Obsidian syntax that vanilla markdownlint may complain about.) ## Migration path 1. Pick one active repo as the pilot — likely the new project where this conversation started. 2. `pip install pre-commit` (or `uv tool install pre-commit`) on the dev machine. 3. Drop in a starter `.pre-commit-config.yaml` covering universal + secrets + ansible + relevant language checks. 4. Port the vault check as a `local` hook pointing at `scripts/check-vault.sh`. 5. `pre-commit install` to wire it up. 6. `pre-commit run --all-files` to flush out anything the existing code violates. 7. Iterate on the config until baseline is clean. 8. Once stable, copy `.pre-commit-config.yaml` to the template location (TBD — see decisions). 9. Decide on `core.hooksPath` — leave or unset. 10. Add `pre-commit install` to the project scaffolding flow so new repos get it automatically. ## Tasks - [ ] Confirm decisions: coexistence with `core.hooksPath`, vault check location, template hosting - [ ] Install `pre-commit` framework on dev machines - [ ] Pilot on one active repo - [ ] Port vault encryption check as a `local` hook - [ ] Build default `.pre-commit-config.yaml` template covering universal + secrets + Python + Go + Ansible + YAML - [ ] Run `pre-commit run --all-files` on pilot, fix or ignore findings - [ ] Document the install/onboarding flow (README section or standalone doc) - [ ] Decide whether to keep or unset `core.hooksPath` - [ ] Migrate active repos one by one as they're touched - [ ] Add template to scaffolding tool or `homelab-templates` repo - [ ] Evaluate whether to add CI run of `pre-commit run --all-files` on PRs (follow-up) ## Open questions - Does `pre-commit` play well with the `zero-check` skill, or is there overlap to resolve? - For Obsidian-flavored markdown, is `markdownlint` worth the noise or skip entirely? - Should `mypy` be in the default Python config, or opt-in per project? ## References - pre-commit docs: https://pre-commit.com - Hook list: https://pre-commit.com/hooks.html - Existing raw hook: stored at `~/.config/git-hooks/pre-commit` (per `core.hooksPath` setup) ...sent from Jenny & Travis