Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ jobs:
in_use="$(for l in "$APP"/bin/*; do [ -e "$l" ] || continue; basename "$(readlink -f "$l")"; done | sort -u)"
ls -1dt "$APP"/artifacts/*/ 2>/dev/null | tail -n +$((KEEP+1)) | while read -r d; do
v="$(basename "$d")"
if printf '%s\n' "$in_use" | grep -qxF "$v"; then continue; fi
if grep -qxF "$v" <<<"$in_use"; then continue; fi
rm -rf "$d" && echo "pruned old artifact $v"
done
true
Expand Down
20 changes: 15 additions & 5 deletions deploy/nginx-cutover.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,21 @@ die(){ echo "ABORT: $*" >&2; exit 1; }
# ignores curlrc; --noproxy '*' ignores http(s)_proxy for every host.
cget(){ curl -q --noproxy '*' "$@"; }

# one scratch file for HTTP probes: fetch with `-o "$PROBE"` and check the FILE
# (grep/wc), never a captured variable — a piped `grep -q` SIGPIPEs under
# pipefail, and `$(...)` capture proved flakier than a file under sudo here.
# one scratch file reused by every HTTP probe below: fetch with `-o "$PROBE"`,
# then grep the file — deliberately not `curl … | grep -q`.
#
# `grep -q` exits at its first match and closes the pipe; under pipefail a writer
# still holding output then takes SIGPIPE (141) and the pipeline reports failure
# although the marker WAS found — a hit read as a miss. It is a payload-size
# threshold, not a fact about grep. Measured here 2026-08-12 (bash builtin printf,
# 5 runs each): correct through 22 KB, wrong 1/5 at 24 KB, wrong 5/5 from 28 KB.
# The nominal 64 KiB pipe capacity is NOT the limit — writes consume ring-buffer
# pages, not exact bytes — so do not reason from that number.
#
# These probes read the dashboard body, ~35 KB: past the deterministic threshold.
# This is exactly what cost many rounds of debugging as a phantom "root-vs-seil
# localhost flap" before the cutover. Do not simplify this back into a pipe.
# For short inputs a pipe is fine and needs no ceremony.
PROBE="$(mktemp)"
trap 'rm -f "$PROBE"' EXIT

Expand Down Expand Up @@ -64,8 +76,6 @@ echo "pre-flight: probing the daemon on http://$DAEMON ..."
# genuinely old/absent daemon still fails all attempts and blocks the flip.
ok=0
for attempt in 1 2 3 4 5; do
# fetch to a file and grep the FILE (never a piped grep -q or a captured var):
# a piped grep -q SIGPIPEs under pipefail, and variable capture flapped under sudo.
if cget -fsS -o "$PROBE" --max-time 5 "http://$DAEMON/" && grep -qF "$MARKER" "$PROBE"; then
ok=1; break
fi
Expand Down
2 changes: 1 addition & 1 deletion deploy/pi5-deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ echo "released $VERSION_ID on $(hostname): /ping ok at http://$ADDR"
in_use="$(for l in "$APP"/bin/*; do [ -e "$l" ] || continue; basename "$(readlink -f "$l")"; done | sort -u)"
ls -1dt "$APP"/artifacts/*/ 2>/dev/null | tail -n +$((KEEP + 1)) | while read -r d; do
v="$(basename "$d")"
if printf '%s\n' "$in_use" | grep -qxF "$v"; then continue; fi
if grep -qxF "$v" <<<"$in_use"; then continue; fi
rm -rf "$d" && echo "pruned old artifact $v"
done
true
Expand Down
Loading