aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-ximage-builder/build-full-image.sh2
-rwxr-xr-ximage-builder/build-sbo-testbuild.sh2
-rw-r--r--image-builder/lib.sh15
-rwxr-xr-ximage-builder/test-image-builder.sh12
4 files changed, 29 insertions, 2 deletions
diff --git a/image-builder/build-full-image.sh b/image-builder/build-full-image.sh
index 47e034b..9a2b83c 100755
--- a/image-builder/build-full-image.sh
+++ b/image-builder/build-full-image.sh
@@ -212,7 +212,7 @@ DOCKERFILE
# docker build would otherwise fall through to push a nonexistent tag and
# log "Done". Check each step and return non-zero on failure.
_log " Building ${FULL_TAG}..."
- if ! docker build "${BUILD_FLAGS[@]}" \
+ if ! docker_build "${BUILD_FLAGS[@]}" \
-t "${FULL_TAG}" \
"${WORKDIR}"; then
_warn " build failed for ${FULL_TAG}; not pushing."
diff --git a/image-builder/build-sbo-testbuild.sh b/image-builder/build-sbo-testbuild.sh
index 2bb8487..3949c51 100755
--- a/image-builder/build-sbo-testbuild.sh
+++ b/image-builder/build-sbo-testbuild.sh
@@ -126,7 +126,7 @@ DOCKERFILE
# (see Main), which suppresses `set -e` in this subshell, so a failed build
# would otherwise push a nonexistent tag and log "Done".
_log " Building ${TB_TAG}..."
- if ! docker build "${BUILD_FLAGS[@]}" -t "${TB_TAG}" "${WORKDIR}"; then
+ if ! docker_build "${BUILD_FLAGS[@]}" -t "${TB_TAG}" "${WORKDIR}"; then
_warn " build failed for ${TB_TAG}; not pushing."
return 1
fi
diff --git a/image-builder/lib.sh b/image-builder/lib.sh
index 8a22828..9c519ac 100644
--- a/image-builder/lib.sh
+++ b/image-builder/lib.sh
@@ -91,3 +91,18 @@ require_mount() {
local dir="${base}/slackware64-${version}"
[[ -d "$dir" ]] || _err "NAS tree not mounted: ${dir}"
}
+
+# docker_build ARGS...
+# `docker build`, retried once on failure. The export of a large image can lose
+# a race on the containerd snapshotter's content lock ("failed to open writer:
+# ref ... locked for 74ms ... unavailable"); the -current full build did on
+# 2026-09-23 after all ten steps had passed. The steps are cached by then, so a
+# retry is little more than a re-export.
+# ponytail: blind single retry; a real step failure costs one extra attempt
+# (a full rebuild under --force/--no-cache). Match on the error text if that
+# ever matters.
+docker_build() {
+ docker build "$@" && return 0
+ _warn " docker build failed; retrying once..."
+ docker build "$@"
+}
diff --git a/image-builder/test-image-builder.sh b/image-builder/test-image-builder.sh
index 19f3ff8..fe6cff6 100755
--- a/image-builder/test-image-builder.sh
+++ b/image-builder/test-image-builder.sh
@@ -83,6 +83,18 @@ DOCKER_RC=0
( require_docker ) 2>/dev/null; check_rc "require_docker daemon up" 0 $?
unset -f docker
+# --- docker_build: one retry, then give up ---
+# Stub fails the first FAILS calls, counting attempts in a file (the calls run
+# in $() subshells, so a shell variable would not survive).
+docker() { local n; n=$(( $(cat "$tmp/calls") + 1 )); echo "$n" > "$tmp/calls"; (( n > FAILS )); }
+for FAILS in 0 1 2; do
+ echo 0 > "$tmp/calls"
+ ( docker_build -t x . ) 2>/dev/null; rc=$?
+ check_rc "docker_build rc after $FAILS failures" "$(( FAILS > 1 ))" "$rc"
+ check "docker_build attempts after $FAILS failures" "$(( FAILS > 1 ? 2 : FAILS + 1 ))" "$(cat "$tmp/calls")"
+done
+unset -f docker
+
# --- registry-gc.sh: -V / --help parse without touching docker; syntax valid ---
gc_ver="$(sed -n 's/^PROJECT_VERSION="\([^"]*\)".*/\1/p' registry-gc.sh)"
check "registry-gc.sh -V" "registry-gc.sh $gc_ver" "$(bash ./registry-gc.sh -V)"