Skip to content

Commit d81ae33

Browse files
BrettKinnyclaude
andcommitted
fix: make runtime apt installs resilient to flaky build-time repos
Runtime package installs chained `apt-get update && apt-get install`. `apt-get update` refreshes every configured source, including the github-cli and gierens/eza third-party repos that are only needed to install gh/eza at image-build time but whose source lists linger in the image. When one of those briefly serves no Release file (deb.gierens.de did on 2026-07-10), `apt-get update` exits non-zero, the `&&` short-circuits, and a base-repo package like tmux never installs — which failed the v1.1.0-rc2 E2E run (setup-editors: "not ok 3.8a tmux installed") and blocked the release image from publishing. Add an `apt_install` helper (setup.sh) that lets `apt-get update` fail soft — the reachable indexes, incl. the Debian base repo, still refresh — and gates on the install itself. Route the tmux/zsh/fish/build-essential sites through it, and apply the same fail-soft pattern to the xz-utils/ zstd installs in squarebox-update.sh. tmux install now also returns non-zero on genuine failure (previously it did not). Reproduced the exact failure (repo present but no Release file → update exits 100) in a Debian container: old chain fails rc=100, new pattern installs tmux rc=0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent e31ffcf commit d81ae33

2 files changed

Lines changed: 29 additions & 8 deletions

File tree

scripts/squarebox-update.sh

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,15 +258,19 @@ update_tool() {
258258

259259
printf " ${CYAN}Updating %s to %s...${RESET}" "$display" "$latest_clean"
260260

261-
# Ensure xz-utils is available for helix
261+
# Ensure xz-utils is available for helix. Let `apt-get update` fail soft: a
262+
# transient outage of a build-time third-party repo (github-cli, gierens/eza)
263+
# must not block installing a base-repo package. Gate on the install itself.
262264
if [ "$tool" = "helix" ] && ! command -v xz &>/dev/null; then
263-
sudo apt-get update -qq && sudo apt-get install -y -qq xz-utils >/dev/null 2>&1
265+
sudo apt-get update -qq || true
266+
sudo apt-get install -y -qq xz-utils >/dev/null 2>&1
264267
fi
265268

266-
# Ensure zstd is available for edit
269+
# Ensure zstd is available for edit (same fail-soft update rationale as above)
267270
local cleanup_zstd=""
268271
if [ "$tool" = "edit" ] && ! command -v zstd &>/dev/null; then
269-
sudo apt-get update -qq && sudo apt-get install -y -qq zstd >/dev/null 2>&1
272+
sudo apt-get update -qq || true
273+
sudo apt-get install -y -qq zstd >/dev/null 2>&1
270274
cleanup_zstd=1
271275
fi
272276

setup.sh

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,23 @@ run_with_spinner() {
9191
fi
9292
}
9393

94+
# Install Debian packages resiliently.
95+
#
96+
# `apt-get update` refreshes *every* configured source, including the
97+
# third-party repos wired up at build time (github-cli, gierens/eza). Those are
98+
# only needed to install gh/eza during the image build — but their source lists
99+
# linger in the image, so a transient outage of one of them (e.g. deb.gierens.de
100+
# briefly serving no Release file) makes `apt-get update` exit non-zero. With the
101+
# old `update && install` chaining that aborted the whole install of a base-repo
102+
# package like tmux, failing E2E and sinking the release build.
103+
#
104+
# So let update fail soft — the reachable indexes (incl. the Debian base repo)
105+
# still refresh — and gate on the install itself, which is the real requirement.
106+
apt_install() {
107+
sudo apt-get update -qq || true
108+
sudo apt-get install -y -qq "$@" >/dev/null 2>&1
109+
}
110+
94111
if $SB_RERUN; then
95112
_sb_banner="🟧📦 squarebox setup (reconfigure)"
96113
else
@@ -643,7 +660,7 @@ install_lazyvim() {
643660
_install_lazyvim_inner() {
644661
# nvim-treesitter compiles parsers on first launch, which needs a C compiler
645662
if ! command -v cc &>/dev/null && ! command -v gcc &>/dev/null; then
646-
sudo apt-get update -qq && sudo apt-get install -y -qq build-essential >/dev/null 2>&1 || return 1
663+
apt_install build-essential || return 1
647664
fi
648665
git clone --depth 1 https://github.com/LazyVim/starter ~/.config/nvim >/dev/null 2>&1 || return 1
649666
rm -rf ~/.config/nvim/.git
@@ -871,7 +888,7 @@ else
871888
fi
872889

873890
_install_tmux_inner() {
874-
sudo apt-get update -qq && sudo apt-get install -y -qq tmux >/dev/null 2>&1
891+
apt_install tmux || return 1
875892
# Install default config (Omarchy-inspired defaults)
876893
mkdir -p ~/.config/tmux
877894
if [ ! -f ~/.config/tmux/tmux.conf ]; then
@@ -1382,7 +1399,7 @@ else
13821399
fi
13831400

13841401
_install_zsh_inner() {
1385-
sudo apt-get update -qq && sudo apt-get install -y -qq zsh >/dev/null 2>&1 || return 1
1402+
apt_install zsh || return 1
13861403
command -v zsh >/dev/null 2>&1 || return 1
13871404
# Trust boundary: the Oh My Zsh installer manages its own files via HTTPS.
13881405
# We resolve the latest release tag at setup time (matching the trust model
@@ -1485,7 +1502,7 @@ _squarebox_bash_line_to_fish() {
14851502
}
14861503

14871504
_install_fish_inner() {
1488-
sudo apt-get update -qq && sudo apt-get install -y -qq fish >/dev/null 2>&1 || return 1
1505+
apt_install fish || return 1
14891506
command -v fish >/dev/null 2>&1 || return 1
14901507
mkdir -p "$HOME/.config/fish/conf.d" || return 1
14911508
# Generate ~/.config/fish/config.fish mirroring the default bashrc in

0 commit comments

Comments
 (0)