-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpre-commit
More file actions
executable file
·92 lines (78 loc) · 3.14 KB
/
Copy pathpre-commit
File metadata and controls
executable file
·92 lines (78 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#!/bin/bash
# =============================================================================
# 3d-cli REPO-DEV pre-commit gate (TRACKED source of truth).
#
# Runs the repo's own Python dev gate before each commit: ruff -> pytest -> mypy.
# Prefer `dev run test` (the primary runner surface). If the external dev CLI is
# unavailable or cannot execute the repo script, fall back to the literal
# rig.yaml scripts.test command. The commit is blocked if any step fails or no
# runner can execute checks.
#
# This is DISTINCT from the `3d init` user-facing template
# (assets/templates/pre-commit): that one gates a *user's* .scad project via
# `3d check`. This hook gates THIS repo's own Python source. Both can exist;
# they live in different repos and never collide.
#
# Install into .git/hooks/pre-commit with: scripts/install-dev-hooks.sh
# Bypass (rare, discouraged): git commit --no-verify
# =============================================================================
set -euo pipefail
cd "$(git rev-parse --show-toplevel)" || exit 1
echo "=== 3d-cli pre-commit: ruff -> pytest -> mypy ==="
# Use the project-scoped dev runner; rig.yaml scripts.test owns the actual command.
if command -v dev >/dev/null 2>&1; then
set +e
dev run --repo-only test
dev_rc=$?
set -e
if [ "$dev_rc" -eq 0 ]; then
exit 0
fi
if [ "$dev_rc" -ne 2 ] && [ "$dev_rc" -ne 127 ]; then
exit "$dev_rc"
fi
echo "[pre-commit] dev CLI could not execute repo-local scripts.test (exit $dev_rc); falling back to rig.yaml scripts.test." >&2
else
echo "[pre-commit] dev CLI not found; falling back to rig.yaml scripts.test." >&2
fi
python_bin=".venv/bin/python"
if [ ! -x "$python_bin" ] && command -v python3 >/dev/null 2>&1; then
python_bin="$(command -v python3)"
fi
if [ ! -x "$python_bin" ]; then
echo "[pre-commit] neither .venv/bin/python nor python3 is available; cannot read rig.yaml." >&2
exit 1
fi
"$python_bin" - <<'PY'
from __future__ import annotations
import subprocess
import sys
from pathlib import Path
from typing import Any, cast
root = Path.cwd()
rig_path = root / "rig.yaml"
try:
text = rig_path.read_text(encoding="utf-8")
except Exception as exc:
print(f"[pre-commit] failed to read {rig_path}: {exc}", file=sys.stderr)
sys.exit(1)
try:
import yaml
except ImportError:
print("[pre-commit] PyYAML is required to read rig.yaml; run `uv sync --extra dev` first.", file=sys.stderr)
sys.exit(1)
try:
rig = cast(dict[str, Any], yaml.safe_load(text))
except Exception as exc:
print(f"[pre-commit] failed to parse {rig_path}: {exc}", file=sys.stderr)
sys.exit(1)
scripts = rig.get("scripts") if isinstance(rig, dict) else None
script: object = scripts.get("test") if isinstance(scripts, dict) else None
if not isinstance(script, str) or not script.strip():
print("[pre-commit] rig.yaml must define a non-empty scripts.test command.", file=sys.stderr)
sys.exit(1)
print("[pre-commit] running rig.yaml scripts.test fallback.", flush=True)
result = subprocess.run(script, cwd=root, shell=True, executable="/bin/sh")
sys.exit(result.returncode)
PY
echo "=== pre-commit checks passed — commit allowed ==="