From 30acd34004530644a2662900944c83720e3b75d4 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Wed, 7 Oct 2026 14:23:05 +0000 Subject: [PATCH] Gate: a --ci run outside GitHub Actions builds the site in the temporary copy like the hook (the in-place build rewrote four tracked site files in the running worktree; the horizon lane, 7 Oct 2026); in place only inside Actions; self-test that the tree is unchanged after a site build Co-Authored-By: Claude Fable 5.1 --- tools/ci/pre-push.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tools/ci/pre-push.sh b/tools/ci/pre-push.sh index a8e2e8bc1..d14c068a6 100755 --- a/tools/ci/pre-push.sh +++ b/tools/ci/pre-push.sh @@ -41,8 +41,13 @@ run() { } run_quiet() { "$@" >/dev/null 2>&1; } +# In place ONLY inside GitHub Actions (a disposable checkout); a `--ci` run on a lane's Mac builds in the temporary copy like the hook, +# because the in-place build rewrote four tracked site files (bench.html, index.html, journey.html, journey.json) in the running +# worktree and every lane had to discard them before a merge (the horizon lane, 7 October 2026). --self-test proves the tree is +# unchanged after a site build outside Actions. +site_in_place() { [ "$MODE" = ci ] && [ "${GITHUB_ACTIONS:-}" = true ]; } site_build() { - if [ "$MODE" = ci ]; then node site/build.mjs; return; fi + if site_in_place; then node site/build.mjs; return; fi SITE_TMP="$(mktemp -d)"; cp -R site "$SITE_TMP/site" (cd "$SITE_TMP/site" && SITE_DOWNLOADS_OFFLINE=1 node build.mjs) } @@ -61,7 +66,7 @@ never_push_checks() { } tree_checks() { - run "site build (in a temporary copy locally, in place in CI)" site_build + run "site build (in a temporary copy here, in place only inside GitHub Actions)" site_build run "internal link check of site/*.html" node tools/ci/link-check.mjs run "every served page carries the slim bar (mark, Mine, Network, Learn, Download) with every route in its panels and the sheet (self-test, then the tree)" bash -c 'node tools/ci/site-nav-check.mjs --self-test && node tools/ci/site-nav-check.mjs' run "vendor marks: site/lib/marks.mjs is brand/marks/vendor-marks.mjs byte for byte (the app and the site draw one set)" cmp brand/marks/vendor-marks.mjs site/lib/marks.mjs @@ -183,8 +188,13 @@ case "$MODE" in touch -t 202001010000 "$(cd "$fx" && stamp_dir)/$B"; case "$(deferred_merge "$M" "$A" "$fx")" in "full the stamp for ${B:0:8} is "*) ;; *) echo "self-test failed: a stale stamp was honoured"; fails=1 ;; esac ( cd "$fx" && echo x > dirty && git add dirty && git -c user.name=t -c user.email=t@t commit -q -m d && echo y > dirty && stamp_green . | grep -q recorded ) && { echo "self-test failed: a dirty tree was stamped"; fails=1; } rm -rf "$fx" + # a --ci site build outside GitHub Actions leaves the tracked site files as they are (the horizon lane's four rewritten files) + before=$(git status --porcelain -- site | sort); ( MODE=ci GITHUB_ACTIONS= site_build >/dev/null 2>&1 ); after=$(git status --porcelain -- site | sort) + [ "$before" = "$after" ] || { echo "self-test failed: a --ci site build outside GitHub Actions changed tracked site files: $(git status --porcelain -- site | tr '\n' ' ')"; fails=1; } + MODE=ci GITHUB_ACTIONS= site_in_place && { echo "self-test failed: --ci outside GitHub Actions chose the in-place build"; fails=1; } + MODE=ci GITHUB_ACTIONS=true site_in_place || { echo "self-test failed: --ci inside GitHub Actions did not choose the in-place build"; fails=1; } declare -f tree_checks | grep -q 'never_push_checks' || { echo "self-test failed: the full gate does not run the never-push checks"; fails=1; } - [ "$fails" = 0 ] && echo "self-test passed: a failing check is RED and fails the gate, a passing one is ok; master and release-* select the full gate, other refs the light one; a merge of a green-stamped branch onto the remote tip defers to CI, every other shape takes the full gate (structural checks, no-secrets, identity grep)" + [ "$fails" = 0 ] && echo "self-test passed: a failing check is RED and fails the gate, a passing one is ok; master and release-* select the full gate, other refs the light one; a merge of a green-stamped branch onto the remote tip defers to CI, every other shape takes the full gate; a --ci site build outside GitHub Actions leaves the tree unchanged (structural checks, no-secrets, identity grep)" exit $fails ;; list) grep -E '^\s+run "' "$0" | sed -E 's/^\s+run "([^"]+)".*/\1/' ;;