The pre-push hook builds the site in a temporary copy and writes nothing in the worktree; the foreign-tree check fails a hook that builds in place
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
418801fac2
commit
19b802a17b
2 changed files with 22 additions and 4 deletions
|
|
@ -1,12 +1,22 @@
|
|||
#!/usr/bin/env bash
|
||||
# Installs the repository's git hooks into this checkout (pre-push: no conflict markers, the site builds).
|
||||
# Installs the repository's git hooks into this checkout (pre-push: no conflict markers, the site builds). Linked
|
||||
# worktrees share the main repository's .git/hooks, so one install covers every worktree.
|
||||
# The hook is READ-ONLY (6 October 2026): it builds the site in a temporary copy and never writes a tracked file in the
|
||||
# worktree. Before this, `node build.mjs` in site/ rewrote downloads.json, journey.json, bench.html and the stamped pages
|
||||
# in whatever worktree the push ran from (five worktrees carried 0.3.14's rows as uncommitted edits, and generated pages
|
||||
# kept changing under agents after 063bbca). Only the ship step writes, with SITE_DOWNLOADS_REFRESH=1 node site/build.mjs.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/../.."
|
||||
cat > .git/hooks/pre-push <<'HOOK'
|
||||
HOOKS="$(git rev-parse --git-common-dir)/hooks"
|
||||
mkdir -p "$HOOKS"
|
||||
cat > "$HOOKS/pre-push" <<'HOOK'
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
bash tools/ci/no-conflict-markers.sh
|
||||
(cd site && node build.mjs >/dev/null) || { echo "pre-push: the site build fails; fix it before pushing" >&2; exit 1; }
|
||||
# the site build, in a temporary copy: a failing build blocks the push; nothing in the worktree is written
|
||||
tmp="$(mktemp -d)"; trap 'rm -rf "$tmp"' EXIT
|
||||
cp -R site "$tmp/site"
|
||||
(cd "$tmp/site" && SITE_DOWNLOADS_OFFLINE=1 node build.mjs >/dev/null) || { echo "pre-push: the site build fails; fix it before pushing" >&2; exit 1; }
|
||||
HOOK
|
||||
chmod +x .git/hooks/pre-push; echo "pre-push hook installed"
|
||||
chmod +x "$HOOKS/pre-push"; echo "pre-push hook installed at $HOOKS/pre-push (read-only site build)"
|
||||
|
|
|
|||
|
|
@ -35,6 +35,14 @@ if [ "${1:-}" = "--self-test" ]; then
|
|||
echo "self-test passed: a Projects path fails, a worktree-list loop with a write fails, an own-toplevel write passes"; exit 0
|
||||
fi
|
||||
fail=0
|
||||
# a git hook never writes a tracked file: the hook body in tools/ci/install-hooks.sh (between <<'HOOK' and HOOK) may run the
|
||||
# site build only inside a mktemp copy (6 October 2026: the in-place build rewrote generated pages in other worktrees)
|
||||
if [ -f tools/ci/install-hooks.sh ]; then
|
||||
body="$(sed -n "/<<'HOOK'/,/^HOOK$/p" tools/ci/install-hooks.sh)"
|
||||
if printf '%s' "$body" | grep -qE "build\.mjs" && ! printf '%s' "$body" | grep -qE "mktemp"; then
|
||||
echo "foreign-tree: the pre-push hook runs the site build in the worktree (no mktemp copy): a hook never writes a tracked file"; fail=1
|
||||
fi
|
||||
fi
|
||||
while IFS= read -r f; do grep -nE "$WARN" "$f" | grep -vE '^[0-9]+:\s*(#|//)' | sed "s|^|foreign-tree (warning, env-only default owed): $f:|" | cut -c1-200; done < <(git ls-files 'tools/**' 'packaging/**' 'infra/**' 'relay/**' | grep -E '\.(sh|mjs|js|py|ps1)$' | grep -v '^tools/ci/no-foreign-tree-writes.sh$')
|
||||
while IFS= read -r f; do check_file "$f" || fail=1; done < <(git ls-files 'tools/**' 'packaging/**' 'site/*.mjs' 'infra/**' 'relay/**' | grep -E '\.(sh|mjs|js|py|ps1)$' | grep -v '^tools/ci/no-foreign-tree-writes.sh$')
|
||||
[ "$fail" = 0 ] && echo "foreign-tree: every script writes under its own toplevel"
|
||||
|
|
|
|||
Loading…
Reference in a new issue