chore(tooling): migrate pre-commit framework to husky
Replaces the Python pre-commit framework (.pre-commit-config.yaml) with husky 9, kept faithful to the existing checks: - Block direct commits to main (was: no-commit-to-branch). - git diff --cached --check covers trailing-whitespace and merge-conflict marker detection. - Custom large-file check (>500KB), excluding crawler test fixtures. - Backend Go: gofmt -l (fail on diff), go vet, golangci-lint — only when backend/*.go is staged. - Backend deps: go mod tidy -diff — only when go.mod/go.sum is staged. - Web: prettier --check, eslint, svelte-check — only when web/ is staged. lint-staged was intentionally not adopted — the previous config ran hooks tree-wide (pass_filenames: false), so per-file optimisation would be a behaviour change. Install: pnpm install at repo root (the prepare script wires husky into .git/hooks via core.hooksPath=.husky/_).
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -14,6 +14,9 @@ vendor/
|
||||
eval-report.json
|
||||
cat-eval-report.json
|
||||
|
||||
# ── Root tooling (husky) ─────────────────────
|
||||
/node_modules/
|
||||
|
||||
# ── Web ──────────────────────────────────────
|
||||
/web/node_modules/
|
||||
/web/.svelte-kit/
|
||||
|
||||
84
.husky/pre-commit
Executable file
84
.husky/pre-commit
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/bin/sh
|
||||
# Pre-commit checks for marktvogt monorepo.
|
||||
# Replaces .pre-commit-config.yaml (Python pre-commit framework).
|
||||
# Install via: pnpm install (at repo root). Husky 9 reads this file directly.
|
||||
|
||||
set -e
|
||||
|
||||
red() { printf '\033[31m%s\033[0m\n' "$*" >&2; }
|
||||
|
||||
# 1. Block direct commits to main.
|
||||
branch=$(git symbolic-ref --short HEAD 2>/dev/null || echo "")
|
||||
if [ "$branch" = "main" ]; then
|
||||
red "ERROR: direct commits to main are blocked. Create a feature branch."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2. Detect whitespace errors and merge-conflict markers in staged hunks.
|
||||
# Replaces pre-commit-hooks: trailing-whitespace, check-merge-conflict.
|
||||
if ! git diff --cached --check; then
|
||||
red "ERROR: whitespace errors or merge-conflict markers in staged changes."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 3. Reject staged files larger than 500 KB (excluding crawler test fixtures).
|
||||
# Replaces pre-commit-hooks: check-added-large-files.
|
||||
big=$(git diff --cached --name-only --diff-filter=ACMR -z |
|
||||
while IFS= read -r -d '' f; do
|
||||
case "$f" in
|
||||
backend/internal/domain/discovery/crawler/testdata/*) continue ;;
|
||||
esac
|
||||
[ -f "$f" ] || continue
|
||||
size=$(wc -c <"$f" 2>/dev/null || echo 0)
|
||||
if [ "$size" -gt 524288 ]; then
|
||||
printf '%s (%s bytes)\n' "$f" "$size"
|
||||
fi
|
||||
done)
|
||||
if [ -n "$big" ]; then
|
||||
red "ERROR: large files staged (>500 KB):"
|
||||
printf '%s\n' "$big" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Helper: list staged files matching a pattern.
|
||||
staged_match() {
|
||||
git diff --cached --name-only --diff-filter=ACMR | grep -E "$1" || true
|
||||
}
|
||||
|
||||
# 4. Backend Go checks — only when backend/*.go is staged.
|
||||
if [ -n "$(staged_match '^backend/.*\.go$')" ]; then
|
||||
echo "→ backend: gofmt"
|
||||
unformatted=$(cd backend && gofmt -l .)
|
||||
if [ -n "$unformatted" ]; then
|
||||
red "ERROR: gofmt would change these files:"
|
||||
printf '%s\n' "$unformatted" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "→ backend: go vet"
|
||||
( cd backend && go vet ./... )
|
||||
|
||||
echo "→ backend: golangci-lint"
|
||||
( cd backend && golangci-lint run --config .golangci.yml ./... )
|
||||
fi
|
||||
|
||||
# 5. go.mod / go.sum tidy — only when those files are staged.
|
||||
if [ -n "$(staged_match '^backend/go\.(mod|sum)$')" ]; then
|
||||
echo "→ backend: go mod tidy (diff check)"
|
||||
( cd backend && go mod tidy -diff ) || {
|
||||
red "ERROR: go mod tidy would change go.mod/go.sum. Run \`cd backend && go mod tidy\` and stage the result."
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
|
||||
# 6. Web checks — only when web/ files are staged.
|
||||
if [ -n "$(staged_match '^web/')" ]; then
|
||||
echo "→ web: prettier --check"
|
||||
( cd web && pnpm run format:check )
|
||||
|
||||
echo "→ web: eslint"
|
||||
( cd web && pnpm run lint )
|
||||
|
||||
echo "→ web: svelte-check"
|
||||
( cd web && pnpm run check -- --threshold error )
|
||||
fi
|
||||
@@ -1,66 +0,0 @@
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-yaml
|
||||
exclude: ^helm/marktvogt/templates/
|
||||
- id: check-json
|
||||
exclude: ^web/tsconfig\.json$
|
||||
- id: check-merge-conflict
|
||||
- id: check-added-large-files
|
||||
exclude: ^backend/internal/domain/discovery/crawler/testdata/
|
||||
- id: no-commit-to-branch
|
||||
args: ['--branch', 'main']
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: golangci-lint
|
||||
name: golangci-lint
|
||||
entry: bash -c 'cd backend && golangci-lint run --config .golangci.yml ./...'
|
||||
language: system
|
||||
files: ^backend/.*\.go$
|
||||
pass_filenames: false
|
||||
|
||||
- id: go-fmt
|
||||
name: go fmt
|
||||
entry: bash -c 'cd backend && gofmt -w .'
|
||||
language: system
|
||||
files: ^backend/.*\.go$
|
||||
pass_filenames: false
|
||||
|
||||
- id: go-vet
|
||||
name: go vet
|
||||
entry: bash -c 'cd backend && go vet ./...'
|
||||
language: system
|
||||
files: ^backend/.*\.go$
|
||||
pass_filenames: false
|
||||
|
||||
- id: go-mod-tidy
|
||||
name: go mod tidy
|
||||
entry: bash -c 'cd backend && go mod tidy'
|
||||
language: system
|
||||
files: ^backend/go\.(mod|sum)$
|
||||
pass_filenames: false
|
||||
|
||||
- id: prettier
|
||||
name: prettier
|
||||
entry: bash -c 'cd web && pnpm run format:check'
|
||||
language: system
|
||||
files: ^web/
|
||||
pass_filenames: false
|
||||
|
||||
- id: eslint
|
||||
name: eslint
|
||||
entry: bash -c 'cd web && pnpm run lint'
|
||||
language: system
|
||||
files: ^web/
|
||||
pass_filenames: false
|
||||
|
||||
- id: svelte-check
|
||||
name: svelte-check
|
||||
entry: bash -c 'cd web && pnpm run check -- --threshold error'
|
||||
language: system
|
||||
files: ^web/
|
||||
pass_filenames: false
|
||||
12
package.json
Normal file
12
package.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "marktvogt-monorepo",
|
||||
"private": true,
|
||||
"description": "Repo-root tooling — husky pre-commit hooks. Application code lives in backend/, web/, app/.",
|
||||
"packageManager": "pnpm@10.33.0",
|
||||
"scripts": {
|
||||
"prepare": "husky"
|
||||
},
|
||||
"devDependencies": {
|
||||
"husky": "^9.1.7"
|
||||
}
|
||||
}
|
||||
24
pnpm-lock.yaml
generated
Normal file
24
pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
lockfileVersion: '9.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
importers:
|
||||
|
||||
.:
|
||||
devDependencies:
|
||||
husky:
|
||||
specifier: ^9.1.7
|
||||
version: 9.1.7
|
||||
|
||||
packages:
|
||||
|
||||
husky@9.1.7:
|
||||
resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
snapshots:
|
||||
|
||||
husky@9.1.7: {}
|
||||
Reference in New Issue
Block a user