From 5c00a8da7085d9215951b3533d5a5b6919664008 Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Wed, 8 Jul 2026 10:39:38 -0500 Subject: [PATCH] ci(e2e): route matrix emulator + system-image install through the #389-hardened installer The E2E (33) matrix leg deadlocked the merge queue for ~2h when android-emulator-runner's un-guarded "Create AVD and generate snapshot" step died with "Error on ZipFile unknown archive" installing a corrupt Android Emulator SDK zip. #389 hardened the platform/build-tools install (SHA-verify -> reject-corrupt -> purge -> re-download) but left the emulator + system-image install to the action, un-guarded. Pre-install "emulator" + "system-images;android-;google_apis;x86_64" through setup_android_sdk.py before the emulator-runner steps, so a corrupt zip is self-healed here and the action then finds both packages already installed and skips its fragile fetch. Runs on both AVD-cache hit and miss (the emulator binary + image live under the SDK root, not the ~/.android AVD-snapshot cache, so they must be present for even a cached AVD to boot). Not added to the android-sdk-v1 cache (kept small); re-install is a fast sdkmanager no-op when already present. The e2e-preview (API 37) job already routes emulator + system image through the hardened installer, so no change there. setup_android_sdk.py already handles these package ids generically; add a unit assertion pinning the matrix's google_apis/x86_64 id to the correct purge path. Closes #443 --- .github/scripts/test_setup_android_sdk.py | 7 +++++++ .github/workflows/ci.yml | 19 +++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/.github/scripts/test_setup_android_sdk.py b/.github/scripts/test_setup_android_sdk.py index 57c0cdb..5b49e6a 100644 --- a/.github/scripts/test_setup_android_sdk.py +++ b/.github/scripts/test_setup_android_sdk.py @@ -36,6 +36,13 @@ class PackageDirTests(unittest.TestCase): sdk.package_dir(root, "system-images;android-37.0;google_apis_ps16k;x86_64"), os.path.join(root, "system-images", "android-37.0", "google_apis_ps16k", "x86_64"), ) + # The matrix e2e legs (#443) pre-install the google_apis/x86_64 image for their API level + # through this same installer, so a corrupt emulator/system-image zip is purged from the + # right dir on retry — assert that (non-ps16k) id maps correctly too. + self.assertEqual( + sdk.package_dir(root, "system-images;android-33;google_apis;x86_64"), + os.path.join(root, "system-images", "android-33", "google_apis", "x86_64"), + ) def test_flat_ids_map_to_single_dir(self): root = os.path.join("opt", "sdk") diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index baab2ee..ec9b836 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -428,8 +428,9 @@ jobs: # green run doesn't re-download (and risk re-corrupting) them. Restore-only # here + the success-gated save below == "integrity gates the cache": a # corrupt/failed SDK is never saved (#389). Shared key (identical contents). - # The emulator + system image stay with android-emulator-runner (boot logic - # is out of scope for #389). + # The emulator + this leg's system image are NOT cached here; they are + # pre-installed via the same #389-hardened installer in a dedicated step below + # (#443), so re-installing is a fast sdkmanager no-op when already present. path: | /usr/local/lib/android/sdk/cmdline-tools/20.0 /usr/local/lib/android/sdk/platforms @@ -486,6 +487,20 @@ jobs: sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm + # Pre-install the Android Emulator + this leg's google_apis/x86_64 system image through the + # #389-hardened installer (SHA-verify -> reject corrupt -> purge -> re-download) BEFORE the + # android-emulator-runner steps below. The runner's un-guarded "Create AVD and generate + # snapshot" fetch died on a corrupt emulator zip ("Error on ZipFile unknown archive") and + # wedged the merge queue for ~2h (#443); routing the install through this hardened path + # self-heals a corrupt zip here, and the emulator-runner then finds both packages already + # installed and skips its fragile fetch. Runs unconditionally (both AVD-cache hit and miss): + # the emulator binary + system image live under the SDK root, not the ~/.android AVD-snapshot + # cache, so they must be present for even a cached AVD to boot. Intentionally NOT added to the + # android-sdk-v1 cache (kept small) — re-install is a fast sdkmanager no-op when already + # present. Keep target (google_apis) / arch (x86_64) in lockstep with the emulator-runner steps. + - name: Pre-install emulator + system image (hardened) + run: python3 .github/scripts/setup_android_sdk.py install "emulator" "system-images;android-${{ matrix.api-level }};google_apis;x86_64" + - name: Cache AVD snapshot uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 id: avd-cache