build: remove dist/ when a release build fails (closes #333) #341
Reference in New Issue
Block a user
Delete Branch "build/333-failed-release-wipes-dist"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #333, implementing the
decision recorded on it: a failed release build removes
dist/.What changed
script/discard-dist-on-failure COMMAND [ARG...](POSIX sh): runs onerelease-build step, and if it fails removes
dist/, says on stderr that itdid and why, and returns the step's own exit status. A removal it cannot
complete is reported just as loudly, naming what is still on disk. Success
removes nothing.
Makefile: every step ofbuild:runs through it — theyarn run buildstep, the
verify-buildstep, and the finalcheck-censored --require-diststep. It composes with the existing mktemp'd receipt and its
trap: thereceipt is still removed on the way out (verified, no
/tmp/autistmask-build-receipt.*left after either run below).build-debug:is deliberately NOT wrapped — a failed debug build is not amistakable artifact and its
dist/is the evidence.script/verify-buildis untouched. What it inspects is unchanged; this isonly what happens after it says no.
README.md(Debug Builds, Entrypoints,make build/make build-debug) andTODO.mdupdated;make fmtrun.Both-directions proof
Real
make buildruns in this tree, not simulations.Failing release build (
AUTISTMASK_DEBUG=1exported):Passing release build (same tree, no env):
Third direction, since the wrapper is on the release path only: a debug build
made to fail mid-write (
chmod 500 dist/chrome, EACCES frombuild.js) exits2 and keeps its
dist/.Also exercised for real: with
dist/chromeunwritable, a failing releasebuild cannot complete the
rm -rfand printsdist/ COULD NOT BE REMOVED, so it is still on disk. Do not load it: ... Remove it by hand (make clean).— the fallback path is real, not hypothetical.Test coverage
Four new
script/test-verify-buildcases assert the POST-RUN STATE OFdist/directly (present-and-intact vs. absent), not the exit status alone: a failing
step removes it, a succeeding step leaves it alone, a failing step with no
dist/says there was none, and a wrapper handed no command removes nothing.Three
make -nwiring cases assert the wrapper is onmake build(includingaround
check-censored --require-dist) and ABSENT frommake build-debug.Mutation-checked both directions rather than assumed: disabling the
rmfailsthe "removes dist/" case (
dist/ is kept after the run, wanted gone), anddropping the success guard fails the "leaves dist/ alone" case (
dist/ is gone after the run, wanted kept). Both restored.Verification
make checkgreen: 41 suites / 835 tests,test-verify-build: 46 case(s) passed(no skips; permission cases enabled),check-censored152 files, lintand fmt-check in the Docker
lintstage. No containers left behind(
docker ps -aempty); no prune of any kind.PASS — independently verified in a fresh clone: the definition of done in #333 is met, all four discard cases are mutation-proven (disabling the
rm, dropping the success guard, unwrappingcheck-censored, and wrappingbuild-debugeach fail exactly one case),make checkgreen with the Docker lint stage genuinely executing (4.7s, realeslint/prettieroutput, notCACHED), 46 cases / 0 skips, CI green on177f592, merges cleanly intonext,script/verify-builduntouched, POSIX-clean underdash.Destructive-path probes actually executed, all safe: invoked from an unrelated cwd (removes only the script's own
$ROOT/dist), repo root containing a space and an apostrophe,dista symlink to a populated tree (link removed, target intact), dangling symlink, absentdist, missing command (exit 127), and non-1/2 statuses (3, 4, 5, 7, 8, 9) all propagated.Two trivial nits, neither blocking:
README.md:165— thescript/discard-dist-on-failurebullet ends...is reported as loudly as one that waswith no terminal period; every other sentence-form bullet in that list has one. Prettier cannot catch it.script/discard-dist-on-failure:52-58— if stderr is closed, the finalechofails,set -euaborts beforeexit "$_status", and the wrapper exits 2 instead of the step's status (measured:... sh -c 'exit 6' 2>&-returns 2). Contradicts the documented "returns the step's own exit status", but stderr is never closed on themake buildpath. Same applies to the "there was no dist/" branch.Disclosure, not a defect: on a real SIGINT to the process group mid-
make build, the wrapper is killed by the signal, sodiscard_distnever runs anddist/is left partially written with no message. The receipttrapstill fires (no/tmp/autistmask-build-receipt.*left after any of my runs). Not in scope for #333, and an operator who interrupts a build knows they did, but nothing states it.Also confirmed by real
make buildruns, not by reading: failing release build (AUTISTMASK_DEBUG=1) exits 2 and leaves nodist/; passing release build keeps all 15 emitted files;make build-debugfailed mid-write with EACCES keeps itsdist/; and withdist/chromeunwritable a failing release build prints theCOULD NOT BE REMOVEDfallback, which is accurate —rm -rfhad removed what it could and the remaining tree really is still on disk.177f592094to92318cb60e