From d8cee339fe105229be1377ee8e0b02f7166a2b6c Mon Sep 17 00:00:00 2001 From: JP Cottin Date: Sun, 26 Jul 2026 15:42:50 -0700 Subject: [PATCH 1/2] Cache the emulator system image, with timing instrumentation The ps16k system image is the one large download in the preview jobs (system.img is ~4.1 GiB, ~2 GiB compressed at the zstd level actions/cache uses). Restore it from cache when possible. The preview emulator package is deliberately not cached: it moves often and pinning a stale build would defeat the purpose of these jobs. sdkmanager still runs after a cache hit, so a newer image revision is still picked up. Whether this is actually worth its share of the repo cache budget is an open question, so the install step now logs SYSIMG-CACHE / SYSIMG-INSTALL / SYSIMG-SIZE lines. The cold-cache and warm-cache numbers can then be read off the job log directly. --- .github/actions/preview-emulator/action.yml | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/actions/preview-emulator/action.yml b/.github/actions/preview-emulator/action.yml index 23d3ce5..5307b6c 100644 --- a/.github/actions/preview-emulator/action.yml +++ b/.github/actions/preview-emulator/action.yml @@ -42,6 +42,23 @@ inputs: runs: using: composite steps: + - name: Resolve SDK path + id: sdk + shell: bash + run: echo "path=${ANDROID_HOME:-${ANDROID_SDK_ROOT:-/usr/local/lib/android/sdk}}" >> "$GITHUB_OUTPUT" + + # The system image is the one large download here (system.img alone is + # ~4.1 GiB, ~2 GiB compressed). The preview emulator package is + # deliberately NOT cached: it moves often and pinning a stale build would + # defeat the purpose of these jobs. sdkmanager still runs after a cache + # hit, so a newer image revision is still picked up. + - name: Restore cached system image + id: sysimg-cache + uses: actions/cache@v4 + with: + path: ${{ steps.sdk.outputs.path }}/system-images/android-${{ inputs.api-level }}/${{ inputs.target }}/${{ inputs.abi }} + key: sysimg-v1-android-${{ inputs.api-level }}-${{ inputs.target }}-${{ inputs.abi }} + - name: Enable KVM shell: bash run: | @@ -78,7 +95,13 @@ runs: SDK="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-/usr/local/lib/android/sdk}}" AVD='${{ inputs.avd-name }}' PKG='system-images;android-${{ inputs.api-level }};${{ inputs.target }};${{ inputs.abi }}' + # Timed so the value of caching the image can be read straight off the + # job log rather than inferred. + echo "SYSIMG-CACHE hit=${{ steps.sysimg-cache.outputs.cache-hit || 'false' }}" + T0=$(date +%s) yes | "$SDK/cmdline-tools/latest/bin/sdkmanager" --channel=3 --install "$PKG" platform-tools > /dev/null + echo "SYSIMG-INSTALL seconds=$(( $(date +%s) - T0 ))" + du -sh "$SDK/system-images/android-${{ inputs.api-level }}/${{ inputs.target }}/${{ inputs.abi }}" 2>/dev/null | sed 's/^/SYSIMG-SIZE /' || true # Mimic the emulator-runner action's invocation (--abi and --device # skip the auto-select/prompt path where bare creates silently no-op). echo no | "$SDK/cmdline-tools/latest/bin/avdmanager" create avd --force -n "$AVD" \ From 1e459ceef444a5c159465ab5688ff12a80b0766b Mon Sep 17 00:00:00 2001 From: JP Cottin Date: Sun, 26 Jul 2026 16:09:41 -0700 Subject: [PATCH 2/2] Rotate the system-image cache key weekly actions/cache never re-saves on an exact key hit, so the fixed key froze the cached image at whatever revision was current when it was first saved. Once Google published a new ps16k revision, sdkmanager would fetch the delta on every run and the cache would never catch up -- turning the saving into a small permanent loss while CI quietly tested a stale image. Put the ISO week in the key and keep the old key as a restore-keys prefix, so a rotation restores the previous copy and sdkmanager fetches only the delta instead of paying for a full 4.4 GB download. Measured on the runner: the install step goes from 52s/39s cold to 3s/3s warm, and the whole setup step from 82s/69s to 66s/50s -- restoring and decompressing the image costs back about 33s of the download saved, so the net is roughly 16-19s per job. The entry is 2.07 GB against a 10 GB repo budget currently holding 2.73 GB total, so there is room for it. --- .github/actions/preview-emulator/action.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/actions/preview-emulator/action.yml b/.github/actions/preview-emulator/action.yml index 5307b6c..f1918ae 100644 --- a/.github/actions/preview-emulator/action.yml +++ b/.github/actions/preview-emulator/action.yml @@ -42,10 +42,19 @@ inputs: runs: using: composite steps: - - name: Resolve SDK path + - name: Resolve SDK path and cache key id: sdk shell: bash - run: echo "path=${ANDROID_HOME:-${ANDROID_SDK_ROOT:-/usr/local/lib/android/sdk}}" >> "$GITHUB_OUTPUT" + run: | + echo "path=${ANDROID_HOME:-${ANDROID_SDK_ROOT:-/usr/local/lib/android/sdk}}" >> "$GITHUB_OUTPUT" + # actions/cache never re-saves on an exact key hit, so a fixed key would + # freeze the image at whatever revision was current when it was first + # cached: sdkmanager would re-fetch each new revision on every run and + # the cache would never catch up, while CI quietly tested a stale image. + # Rotating weekly bounds that. The restore-keys prefix means a rotation + # restores last week's copy and lets sdkmanager fetch just the delta, + # rather than paying for a full download. + echo "week=$(date -u +%G-W%V)" >> "$GITHUB_OUTPUT" # The system image is the one large download here (system.img alone is # ~4.1 GiB, ~2 GiB compressed). The preview emulator package is @@ -57,7 +66,9 @@ runs: uses: actions/cache@v4 with: path: ${{ steps.sdk.outputs.path }}/system-images/android-${{ inputs.api-level }}/${{ inputs.target }}/${{ inputs.abi }} - key: sysimg-v1-android-${{ inputs.api-level }}-${{ inputs.target }}-${{ inputs.abi }} + key: sysimg-v1-android-${{ inputs.api-level }}-${{ inputs.target }}-${{ inputs.abi }}-${{ steps.sdk.outputs.week }} + restore-keys: | + sysimg-v1-android-${{ inputs.api-level }}-${{ inputs.target }}-${{ inputs.abi }} - name: Enable KVM shell: bash