pre-push Lens pass + make hooks installer
.githooks/pre-push runs 'make verify', tees the log to .git/lens-pass.log and, on failure, prints one summary (last step started, log path, bypass) before exiting 1. 'make hooks' symlinks .githooks/* into the clone's hooks dir. core.hooksPath is deliberately left alone: bd keeps its own pre-commit (post-merge) hooks in .git/hooks and pointing hooksPath at .githooks would silently retire them while bd still reports them installed.
This commit is contained in:
Executable
+52
@@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# pre-push: the Lens pass. Runs `make verify` (cheap gate + heavy sensors + both
|
||||||
|
# test suites) and blocks the push if anything fails.
|
||||||
|
#
|
||||||
|
# Install with `make hooks` (symlinks this file into this clone's git hooks
|
||||||
|
# directory). Deliberate bypass: `git push --no-verify`.
|
||||||
|
#
|
||||||
|
# Why a symlink and not `git config core.hooksPath .githooks`: bd keeps its own
|
||||||
|
# managed hooks in .git/hooks (pre-commit flushes .beads/issues.jsonl, post-merge
|
||||||
|
# imports it). Pointing core.hooksPath elsewhere would silently retire them, and
|
||||||
|
# bd would still report its hooks as installed. Installing one symlink per hook
|
||||||
|
# in .githooks/ keeps every hook manager's files where they expect them.
|
||||||
|
#
|
||||||
|
# stdin carries "<local ref> <local sha> <remote ref> <remote sha>" per ref being
|
||||||
|
# pushed; the Lens pass is repo-wide, so it is deliberately not read.
|
||||||
|
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
if ! cd "$(git rev-parse --show-toplevel)"; then
|
||||||
|
echo "pre-push: cannot find the repository root; refusing to let this push through" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v make >/dev/null 2>&1; then
|
||||||
|
echo "pre-push: make not found on PATH — the Lens pass cannot run, so the push is blocked" >&2
|
||||||
|
echo "pre-push: install make, or bypass deliberately with: git push --no-verify" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log=$(git rev-parse --git-dir)/lens-pass.log
|
||||||
|
echo "pre-push: running the Lens pass (make verify) — full log: $log"
|
||||||
|
|
||||||
|
set -o pipefail
|
||||||
|
if make verify 2>&1 | tee "$log"; then
|
||||||
|
echo "pre-push: Lens pass passed"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
last_step=$(grep -E '^==> ' "$log" | tail -n 1)
|
||||||
|
{
|
||||||
|
echo
|
||||||
|
echo "=================================================================="
|
||||||
|
echo "pre-push: LENS PASS FAILED — push blocked"
|
||||||
|
echo " last step started: ${last_step:-unknown (see log)}"
|
||||||
|
echo " full log: $log"
|
||||||
|
echo " triage the failure (real bug / environment-dependent test /"
|
||||||
|
echo " design nit — see AGENTS.md), then re-run: make verify"
|
||||||
|
echo " deliberate bypass: git push --no-verify"
|
||||||
|
echo "=================================================================="
|
||||||
|
} >&2
|
||||||
|
exit 1
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
MISE_BIN ?= mise
|
MISE_BIN ?= mise
|
||||||
|
|
||||||
.PHONY: check precommit deps compile test test-elisp format verify
|
.PHONY: check precommit verify hooks deps compile test test-elisp format
|
||||||
|
|
||||||
# Cheap static gate over both apps, cheapest first. No database, no coverage:
|
# Cheap static gate over both apps, cheapest first. No database, no coverage:
|
||||||
# this is the loop you run freely while working and before every commit.
|
# this is the loop you run freely while working and before every commit.
|
||||||
@@ -27,6 +27,23 @@ verify: check
|
|||||||
@echo "==> verify: blogex"
|
@echo "==> verify: blogex"
|
||||||
@$(MAKE) -C blogex MISE_BIN=$(MISE_BIN) verify
|
@$(MAKE) -C blogex MISE_BIN=$(MISE_BIN) verify
|
||||||
|
|
||||||
|
# Install the versioned hooks in .githooks/ into this clone's hooks directory as
|
||||||
|
# symlinks (edits take effect immediately, no copy to drift). Idempotent; re-run
|
||||||
|
# after moving the clone, since the links are absolute.
|
||||||
|
#
|
||||||
|
# core.hooksPath is deliberately NOT changed: bd manages its own hooks inside
|
||||||
|
# .git/hooks (pre-commit flushes .beads/issues.jsonl, post-merge imports it) and
|
||||||
|
# moving the hooks path would silently retire them.
|
||||||
|
hooks:
|
||||||
|
@hooks_dir=$$(git rev-parse --git-path hooks); \
|
||||||
|
root=$$(git rev-parse --show-toplevel); \
|
||||||
|
mkdir -p "$$hooks_dir"; \
|
||||||
|
for hook in .githooks/*; do \
|
||||||
|
name=$$(basename "$$hook"); \
|
||||||
|
ln -sfn "$$root/$$hook" "$$hooks_dir/$$name"; \
|
||||||
|
echo "installed $$hooks_dir/$$name -> $$hook"; \
|
||||||
|
done
|
||||||
|
|
||||||
# Sync dependencies
|
# Sync dependencies
|
||||||
deps:
|
deps:
|
||||||
@make -C app deps
|
@make -C app deps
|
||||||
|
|||||||
Reference in New Issue
Block a user