fix: discard-dist-on-failure keeps the step's status when its message cannot be written (closes #342)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run

With stderr closed, the wrapper's message write failed and set -e ended it
with status 2; with stderr a pipe whose reader had gone, the write killed it
with 141. The message is now written with SIGPIPE ignored and its failure
ignored, after the step has run. An interrupt while a step runs now exits with
130 once the step has ended, removing nothing: under bash, a step that caught
the interrupt and exited with a status, as check-censored does, used to get
dist/ removed. A failed check-censored --require-dist still removes dist/. The
header states both. Also the README bullet's missing period.

Model: opus-5-5
This commit was merged in pull request #485.
This commit is contained in:
2026-10-07 04:26:08 +02:00
parent 1cfd69e72d
commit 4dafd88fad
4 changed files with 108 additions and 17 deletions
+23 -16
View File
@@ -3,22 +3,21 @@
# step fails, remove dist/ before returning its exit status. Our own extension
# to scripts-to-rule-them-all, wrapped around every step of make build.
#
# Why: with AUTISTMASK_DEBUG=1 exported in the calling shell, make build
# compiles a debug bundle and then fails on it in script/verify-build — but the
# bundle is already written. It is loadable, and every wallet it creates gets
# the publicly committed test recovery phrase from src/shared/constants.js. A
# failed release build that leaves that behind is a smaller version of the trap
# the verifier exists to close, and "the failure was loud" only works on an
# operator who does not load dist/chrome/ anyway. Removing the artifact does not
# depend on that.
# Why: with AUTISTMASK_DEBUG=1 exported, make build compiles a debug bundle and
# then fails on it in script/verify-build, after the bundle is written. It is
# loadable, and every wallet it creates gets the publicly committed test
# recovery phrase from src/shared/constants.js, so a failed build must not leave
# it behind. The removal is never silent: it says on stderr that dist/ is gone
# and why.
#
# Two things this deliberately does not do. It does not wrap make build-debug: a
# debug build that failed is not a mistakable artifact, and its output is the
# evidence of what went wrong. And it never removes anything on a step that
# SUCCEEDS, including the final check-censored --require-dist pass.
#
# The removal is never silent: it says dist/ is gone and why, on stderr, above
# the build's own failure.
# A failed check-censored --require-dist removes dist/ like any other step: a
# dist/ not cleared of the name RULES.md bars must not ship either. A step that
# succeeds removes nothing. An interrupt (Ctrl-C) while a step runs removes
# nothing and says nothing, even when the step catches it and exits with a
# status of its own: the wrapper exits with 130 once the step has ended. An
# interrupt is not a build failure, and whoever interrupted the build knows it
# did not finish. make build-debug is not wrapped: a debug build that failed is
# not a mistakable artifact, and its output is the evidence of what went wrong.
set -eu
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
@@ -66,12 +65,20 @@ main() {
exit 1
}
# An interrupt is not a build failure: once the step has ended, exit
# without removing anything, even if the step caught the interrupt and
# exited with a status of its own. bash as /bin/sh would otherwise carry on.
trap 'exit 130' INT
_status=0
"$@" || _status=$?
[ "$_status" -ne 0 ] || return 0
discard_dist
# A message that cannot be written, to a closed stderr or to a pipe nobody
# reads any more, must not replace the step's status.
trap '' PIPE
discard_dist || true
exit "$_status"
}