From 5e8a9888580830a3d1e87e08b7c4c54eba380d70 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Thu, 11 Jun 2026 20:59:08 +0000 Subject: [PATCH] =?UTF-8?q?android-emulator:=20api36-v2=20=E2=80=94=20mark?= =?UTF-8?q?er-file=20install=20idempotency=20+=20retries?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First boot crashed mid-SDK-install, and the dir-existence check then skipped reinstall forever: avdmanager saw the partial tree and died with 'Valid system image paths are: null' (CrashLoopBackOff). v2 tracks install completion with a marker file written only after sdkmanager succeeds + package.xml exists, wipes partial system-image trees before reinstalling, and retries sdkmanager 3x. --- stacks/android-emulator/docker/Dockerfile | 4 ++-- stacks/android-emulator/docker/entrypoint.sh | 23 ++++++++++++++++---- stacks/android-emulator/variables.tf | 2 +- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/stacks/android-emulator/docker/Dockerfile b/stacks/android-emulator/docker/Dockerfile index 25f8a367..a8372c58 100644 --- a/stacks/android-emulator/docker/Dockerfile +++ b/stacks/android-emulator/docker/Dockerfile @@ -4,8 +4,8 @@ # cmdline-tools and the native libraries the emulator needs at runtime. # # Rebuild + push (rare — only when tool/library versions bump): -# docker build -t forgejo.viktorbarzin.me/viktor/android-emulator:api36-v1 . -# docker push forgejo.viktorbarzin.me/viktor/android-emulator:api36-v1 +# docker build -t forgejo.viktorbarzin.me/viktor/android-emulator:api36-v2 . +# docker push forgejo.viktorbarzin.me/viktor/android-emulator:api36-v2 FROM eclipse-temurin:17-jdk-jammy ENV DEBIAN_FRONTEND=noninteractive diff --git a/stacks/android-emulator/docker/entrypoint.sh b/stacks/android-emulator/docker/entrypoint.sh index 4f32e1f3..b4b2dceb 100644 --- a/stacks/android-emulator/docker/entrypoint.sh +++ b/stacks/android-emulator/docker/entrypoint.sh @@ -15,13 +15,28 @@ SCREEN_GEOMETRY="${SCREEN_GEOMETRY:-1080x2280x24}" mkdir -p "$ANDROID_USER_HOME" # --- SDK packages on the PVC (idempotent; first boot downloads ~2.5GB) ------ -if [ ! -x /sdk/platform-tools/adb ] || [ ! -x /sdk/emulator/emulator ] || \ - [ ! -d "/sdk/system-images/android-${API_LEVEL}" ]; then - echo "Installing SDK packages into /sdk (first boot)..." +# A directory existing is NOT proof of a complete install (an interrupted +# sdkmanager leaves partial trees that avdmanager rejects with "Valid system +# image paths are: null") — so completion is tracked with a marker file +# written only after sdkmanager succeeds. +MARKER="/sdk/.sdk-install-complete-android-${API_LEVEL}" +if [ ! -f "$MARKER" ]; then + echo "Installing SDK packages into /sdk (first boot or prior partial install)..." + rm -rf "/sdk/system-images/android-${API_LEVEL}" # (yes || true): yes dies of SIGPIPE (141) when sdkmanager stops reading, # which set -o pipefail would otherwise turn into a fatal error. (yes || true) | sdkmanager --sdk_root=/sdk --licenses >/dev/null - sdkmanager --sdk_root=/sdk "platform-tools" "emulator" "$SYSTEM_IMAGE" + for attempt in 1 2 3; do + if sdkmanager --sdk_root=/sdk "platform-tools" "emulator" "$SYSTEM_IMAGE"; then + break + fi + echo "sdkmanager attempt $attempt failed; retrying in 10s..." >&2 + [ "$attempt" = 3 ] && exit 1 + sleep 10 + done + # the package manifest is what avdmanager actually validates against + test -f "/sdk/system-images/android-${API_LEVEL}/google_apis/x86_64/package.xml" + touch "$MARKER" fi # --- AVD (idempotent) -------------------------------------------------------- diff --git a/stacks/android-emulator/variables.tf b/stacks/android-emulator/variables.tf index 5d4927b6..2ea8b5ca 100644 --- a/stacks/android-emulator/variables.tf +++ b/stacks/android-emulator/variables.tf @@ -5,6 +5,6 @@ variable "tls_secret_name" { variable "image_tag" { type = string - default = "api36-v1" + default = "api36-v2" description = "android-emulator image tag at forgejo.viktorbarzin.me/viktor/android-emulator. Built + pushed manually from stacks/android-emulator/docker/ (see README.md) — bump this when the image is rebuilt." }