v0.316.4: build.sh refuses a push from a dirty or unpushed tree
gates / gates (push) Failing after 50s
gates / gates (push) Failing after 50s
An admission and its mechanism. Building 0.316.3 published another session's work: the shared DooPlex clone held 31 uncommitted files, and the build directory's build.sh is a symlink into that clone's WORKING COPY — which predated the FELHOM_REPO_DIR override, so the override was ignored and the build copied the shared tree. The banner printed 'Commit: 0225255' and no 'Repo:' line; the evidence was on screen and the image was already pushed. Nobody deployed it, which is luck, not a control. The clean-tree rule has been a sentence in a runbook all along. A rule without a mechanism is a wish, so it is now two questions the build asks and refuses on: is every tracked file committed, and is HEAD what origin/main has. A directory that is not a git checkout is refused too — a build whose source cannot be identified is not reproducible. Four new cases in the test (ten in total), each driving the real script; red-proved by deleting the gate, which fails all four. 0.316.3 must never be deployed. It is not re-pushed or deleted: a version number is pushed once, and that applies to a number I spoiled. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0117kRTSgs3rJWUFGxyoWN6Y
This commit is contained in:
@@ -110,6 +110,43 @@ if [[ "${ACTION}" == "--push" || "${ACTION}" == "--multiarch" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
info "${VERSION} is not present in the registry — proceeding."
|
||||
|
||||
# AND THE TREE IT BUILDS FROM MUST BE CLEAN AND PUSHED.
|
||||
#
|
||||
# Until v0.316.3 this was a sentence in a runbook, and a rule without a mechanism is a wish. It
|
||||
# cost a bad push the same evening it was written down: the shared clone had 31 files of another
|
||||
# session's work in progress, and a build from it put their unreleased code into a published
|
||||
# image under my version number. Nobody deployed it; that was luck, not a control.
|
||||
#
|
||||
# Two questions, both of which must be YES:
|
||||
# is every tracked file committed? — otherwise the image holds something git does not
|
||||
# is HEAD what origin/main has? — otherwise the image holds something nobody can fetch
|
||||
# „An unpushed change does not exist" (workspace CLAUDE.md), and an image built from one is a
|
||||
# thing that exists and cannot be reproduced.
|
||||
if [[ -d "${REPO_DIR}/.git" ]]; then
|
||||
dirty=$(cd "${REPO_DIR}" && git status --porcelain 2>/dev/null | wc -l)
|
||||
if [[ "${dirty}" -ne 0 ]]; then
|
||||
error "${REPO_DIR} has ${dirty} uncommitted change(s) — refusing to push a build from it."
|
||||
error "An image built from a dirty tree cannot be reproduced, and on a SHARED clone it"
|
||||
error "may carry work that is not yours. Commit and push, or build from a clean clone"
|
||||
error "with FELHOM_REPO_DIR pointing at it."
|
||||
(cd "${REPO_DIR}" && git status --porcelain | head -10 | sed 's/^/ /')
|
||||
exit 1
|
||||
fi
|
||||
head_sha=$(cd "${REPO_DIR}" && git rev-parse HEAD 2>/dev/null || echo unknown)
|
||||
main_sha=$(cd "${REPO_DIR}" && git rev-parse origin/main 2>/dev/null || echo unknown)
|
||||
if [[ "${head_sha}" != "${main_sha}" ]]; then
|
||||
error "${REPO_DIR} is not at origin/main — refusing to push."
|
||||
error " HEAD ${head_sha}"
|
||||
error " origin/main ${main_sha}"
|
||||
error "An unpushed change does not exist; an image built from one cannot be fetched again."
|
||||
exit 1
|
||||
fi
|
||||
info "Source tree is clean and at origin/main."
|
||||
else
|
||||
error "${REPO_DIR} is not a git checkout — refusing to push a build whose source cannot be identified."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# =========================================================================
|
||||
|
||||
Reference in New Issue
Block a user