Skip locally built images by their build: stanza instead of a list of names

update-containers kept LOCAL_BUILD, a hand-written list of services whose
images are built on the machine, so it would not try to pull them. The
compose files already say this. A service with a build: stanza names a
local image, and there is nothing in a registry to pull.

images_for now drops the image of any compose service that has a build:
stanza. Those services resolve no images, and the run skips them without a
log line. The list, and the app names it carried, are gone. On the VPS,
--list resolves the same images as before for every other service.
This commit is contained in:
Gabriel Brown committed 2026-10-06 10:52:47 -04:00
1 parent 913a57f8a6
commit f4fca1797f
2 files changed
+24 -13

No files matched your search

+22 -11
View File
@@ -46,10 +46,6 @@ set -uo pipefail
# podman pull <image> && systemctl --user restart podman-<name>.service
SKIP=(postgresql authentik watchtower)
# Services built locally rather than pulled. There is no registry image to check,
# so pulling is pointless — they are skipped automatically when no `image:` line
# resolves, but listing them here keeps the log quiet and the intent obvious.
LOCAL_BUILD=(bang completeuphoria sierraandtyler)
# ⚠️ NOTE ON GITEA: it is deliberately NOT in SKIP. The three-day outage was caused
# by watchtower's recreate mechanism, not by the act of updating — restarting the
@@ -90,8 +86,10 @@ list_units() {
| sort
}
# Images declared in a service's compose.yml. Ignores commented lines and the
# `build:` stanza, which has no pullable image.
# Images declared in a service's compose.yml. Ignores commented lines, and the
# image of any compose service that has a `build:` stanza: that tag names a
# locally built image, so there is nothing in a registry to pull. Those
# services therefore resolve no images and are skipped without a log line.
#
# Image tags frequently reference variables from the service's .env, e.g.
# ghcr.io/get-convex/convex-backend:${BACKEND_TAG:-latest}
@@ -102,8 +100,22 @@ list_units() {
images_for() {
local dir="$1"
[ -f "$dir/compose.yml" ] || return 0
grep -oE '^[[:space:]]*image:[[:space:]]*[^[:space:]#]+' "$dir/compose.yml" 2>/dev/null \
| sed -E 's/^[[:space:]]*image:[[:space:]]*//' \
awk '
function flush() { if (img != "" && !build) print img; img = ""; build = 0 }
/^[[:space:]]*#/ { next }
/^services:[[:space:]]*$/ { in_services = 1; indent = -1; next }
in_services && /^[^[:space:]]/ { flush(); in_services = 0 }
in_services && NF {
match($0, /^ */); here = RLENGTH
if (indent < 0) indent = here
if (here == indent && $0 ~ /^ *[A-Za-z0-9_.-]+:[[:space:]]*$/) { flush(); next }
if ($0 ~ /^[[:space:]]+build:/) build = 1
if (match($0, /^[[:space:]]+image:[[:space:]]*[^[:space:]#]+/)) {
img = substr($0, RSTART, RLENGTH); sub(/^[[:space:]]+image:[[:space:]]*/, "", img)
}
}
END { flush() }
' "$dir/compose.yml" 2>/dev/null \
| while IFS= read -r img; do
case "$img" in
*'${'*) ( set -a; [ -f "$dir/.env" ] && . "$dir/.env" >/dev/null 2>&1; set +a
@@ -124,8 +136,8 @@ if [ "${LIST:-0}" = "1" ]; then
for svc in $(list_units); do
printf '%-22s' "$svc"
if in_list "$svc" "${SKIP[@]}"; then echo "SKIP (frozen)"; continue; fi
if in_list "$svc" "${LOCAL_BUILD[@]}"; then echo "SKIP (built locally)"; continue; fi
echo "$(images_for "$(workdir_for "$svc")" | tr '\n' ' ')"
imgs="$(images_for "$(workdir_for "$svc")" | tr '\n' ' ')"
echo "${imgs:-(built locally, nothing to pull)}"
done
exit 0
fi
@@ -142,7 +154,6 @@ for svc in $(list_units); do
[ -n "$ONLY" ] && [ "$svc" != "$ONLY" ] && continue
if [ -z "$ONLY" ]; then
in_list "$svc" "${SKIP[@]}" && { log " $svc: frozen (SKIP list)"; continue; }
in_list "$svc" "${LOCAL_BUILD[@]}" && continue
fi
# ⚠️ NEVER resurrect a service that is deliberately stopped. `systemctl restart`