Skip to main content

max / audiofiles

4.1 KB · 85 lines History Blame Raw
1 #!/bin/bash
2 # Canonical pre-push gate. Two gates, and they answer different questions:
3 #
4 # internal deps does every in-house `version` requirement in the tree still
5 # resolve against the crate it names? Runs in EVERY repo.
6 # test targets do this repo's test targets build? Runs where there is a
7 # root Cargo.toml to run one command in.
8 #
9 # DO NOT EDIT IN PLACE. The master is _private/infra/bootstrap/githooks/pre-push.
10 #
11 # Bypass for a work-in-progress push: git push --no-verify
12 #
13 # WHY THE FIRST GATE EXISTS. Every cross-repo dependency carries a `version`
14 # alongside its `git` URL, so cargo refuses a sibling it was not written against
15 # instead of compiling something surprising. That requirement is the protection
16 # and it is also the maintenance: bumping a library's minor breaks every consumer
17 # whose requirement excludes it, and CLAUDE.md's rule is that the bump and the
18 # forward fix are one pass. Nothing enforced the rule, so quasi went 0.11 -> 0.14
19 # over two evenings and MNW's server could not resolve at all for a day. The
20 # nightly sweep found it and a red cell in a grid is not the same as being told.
21 #
22 # This gate is that rule, mechanised, at the moment it is broken: the push that
23 # would leave a consumer unable to build is the push that is refused. It reads
24 # the WORKING COPIES in the tree, not the remotes, because `~/Code/.cargo/config.toml`
25 # redirects every one of these dependencies to the working copy -- so a local bump
26 # breaks a consumer's build here whether or not it has been pushed anywhere.
27 #
28 # `cargo check` and `cargo clippy` both compile only the lib and bin targets, so a
29 # break confined to `tests/` or a `#[cfg(test)]` module is clean under both and
30 # lands unnoticed (goingson's sqlx 0.9 upgrade shipped exactly that way).
31 # `--no-run` builds every test target without running them, which is the cheap
32 # half of the suite and enough to catch a compile break. Tests still run
33 # separately.
34 #
35 # `--workspace` is load-bearing wherever default-members is narrower than the
36 # workspace: goingson's is src-tauri alone, so a bare `cargo test --no-run` would
37 # skip core, db-sqlite, go-mcp and got.
38 set -euo pipefail
39
40 ROOT="$(git rev-parse --show-toplevel)"
41 cd "$ROOT"
42
43 # See the canonical pre-commit: a hook run from an editor or a cron job does not
44 # get the profile's PATH, and a hook that cannot find cargo is worse than none.
45 export PATH="$HOME/.cargo/bin:$HOME/.local/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"
46
47 # Refs arrive on stdin as "<local ref> <local sha> <remote ref> <remote sha>".
48 # A branch deletion has an all-zero local sha and no tree to push. Read once,
49 # ahead of both gates: stdin is not seekable and a second reader gets nothing.
50 pushing=0
51 while read -r _local_ref local_sha _remote_ref _remote_sha; do
52 case "$local_sha" in
53 *[!0]*) pushing=1 ;;
54 esac
55 done
56 [ "$pushing" -eq 1 ] || exit 0
57
58 # ── gate 1: internal dependency coherence ──────────────────────────────────
59 #
60 # Deliberately no cargo: this reads manifests and answers in well under a second,
61 # where `cargo metadata` on the server is tens of seconds and fails outright on
62 # exactly the state being detected.
63 CODE_ROOT="${CODE_ROOT:-$HOME/Code}"
64 if [ -d "$CODE_ROOT" ] && command -v python3 >/dev/null 2>&1; then
65 if ! python3 "$ROOT/scripts/githooks/internal-deps.py" "$CODE_ROOT" "$ROOT"; then
66 echo "pre-push: push aborted (use --no-verify to bypass)."
67 exit 1
68 fi
69 fi
70
71 # ── gate 2: test targets build ─────────────────────────────────────────────
72 #
73 # MNW and synckit have no root Cargo.toml by design (standalone crates, no root
74 # workspace), so there is no one command to run and they get gate 1 only.
75 [ -f "$ROOT/Cargo.toml" ] || exit 0
76
77 echo "pre-push: building test targets (cargo test --no-run --workspace)..."
78 if ! cargo test --no-run --workspace; then
79 echo "pre-push: test targets failed to build."
80 echo "pre-push: push aborted (use --no-verify to bypass)."
81 exit 1
82 fi
83
84 echo "pre-push: test targets build clean."
85