From 9263ec73e76b056e6db5bd835b1281d718618ad4 Mon Sep 17 00:00:00 2001 From: Jason Ernst Date: Mon, 12 Oct 2026 12:10:25 -0700 Subject: [PATCH 1/2] SDK check: treat an empty as stable; tag images with build-tools Stable platforms since android-37.0 carry an empty in Google's repository manifest, so is_preview() skipped every 37.x and the image stayed on platform 36.1. Only a non-empty codename marks a preview now. deploy also publishes -jdkNN-sdkX.Y-btX.Y.Z-ndkX.Y.Z so consumers can let Renovate derive compileSdk, buildToolsVersion and ndkVersion from the image pin; the existing -sdk-ndk tag is kept. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/check-sdk-updates.yml | 7 ++++--- .github/workflows/deploy.yml | 8 +++++++- README.md | 6 ++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check-sdk-updates.yml b/.github/workflows/check-sdk-updates.yml index 439ddf8..fb103f1 100644 --- a/.github/workflows/check-sdk-updates.yml +++ b/.github/workflows/check-sdk-updates.yml @@ -75,8 +75,9 @@ jobs: # are listed too), which then break the unattended Docker build when # sdkmanager demands the separate Android SDK Preview license. The manifest # carries reliable preview markers, so we parse it with a real XML parser - # and skip any package that is obsolete, carries a element, or - # uses the android-sdk-preview-license. + # and skip any package that is obsolete, carries a non-empty , or + # uses the android-sdk-preview-license. Stable platforms since android-37.0 + # carry an EMPTY , so only a non-empty one marks a preview. if ! wget -q "https://dl.google.com/android/repository/repository2-3.xml" -O /tmp/android-repo.xml; then echo "Failed to download SDK repository manifest" echo "updated=false" >> $GITHUB_OUTPUT @@ -94,7 +95,7 @@ jobs: if pkg.get('obsolete') == 'true': return True for e in pkg.iter(): - if local(e.tag) == 'codename': + if local(e.tag) == 'codename' and (e.text or '').strip(): return True if local(e.tag) == 'uses-license' and e.get('ref') == 'android-sdk-preview-license': return True diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 41905cc..a07fe3b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -42,9 +42,10 @@ jobs: RUNNER_TAG=$(grep -m1 '^ARG VERSION=' Dockerfile | cut -d= -f2) RUNNER_VERSION=$(echo "$RUNNER_TAG" | cut -d- -f1) COMPILE_SDK=$(grep -m1 '^ARG COMPILE_SDK=' Dockerfile | cut -d= -f2) + BUILD_TOOLS=$(grep -m1 '^ARG BUILD_TOOLS=' Dockerfile | cut -d= -f2) NDK_VERSION=$(grep -m1 '^ARG NDK_VERSION=' Dockerfile | cut -d= -f2) - if [ -z "$RUNNER_TAG" ] || [ -z "$RUNNER_VERSION" ] || [ -z "$COMPILE_SDK" ] || [ -z "$NDK_VERSION" ]; then + if [ -z "$RUNNER_TAG" ] || [ -z "$RUNNER_VERSION" ] || [ -z "$COMPILE_SDK" ] || [ -z "$BUILD_TOOLS" ] || [ -z "$NDK_VERSION" ]; then echo "::error::Failed to extract versions from Dockerfile" exit 1 fi @@ -52,6 +53,7 @@ jobs: echo "runner_tag=${RUNNER_TAG}" >> $GITHUB_OUTPUT echo "runner_version=${RUNNER_VERSION}" >> $GITHUB_OUTPUT echo "compile_sdk=${COMPILE_SDK}" >> $GITHUB_OUTPUT + echo "build_tools=${BUILD_TOOLS}" >> $GITHUB_OUTPUT echo "ndk_version=${NDK_VERSION}" >> $GITHUB_OUTPUT - name: Login to Docker Hub @@ -83,6 +85,10 @@ jobs: # Same image, with the NDK it ships in the tag: consumers that pin an NDK (Android # Gradle ndkVersion) can let Renovate derive it from this tag so image and NDK move together. type=raw,value=${{ steps.versions.outputs.runner_version }}-jdk${{ matrix.java_version }}-sdk${{ steps.versions.outputs.compile_sdk }}-ndk${{ steps.versions.outputs.ndk_version }} + # Same image, with every Gradle-pinnable SDK component in the tag (compileSdk, build-tools, + # NDK), so consumers can let Renovate derive all three from one tag. The -sdk-ndk tag above + # stays for consumers already parsing it. + type=raw,value=${{ steps.versions.outputs.runner_version }}-jdk${{ matrix.java_version }}-sdk${{ steps.versions.outputs.compile_sdk }}-bt${{ steps.versions.outputs.build_tools }}-ndk${{ steps.versions.outputs.ndk_version }} type=raw,value=latest,enable=${{ matrix.is_default_jdk }} - name: Build and push diff --git a/README.md b/README.md index 995993f..ffb0d70 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,12 @@ version, and Android SDK level. Tags let you choose how tightly to pin: | `latest` | `latest` | Nothing | Runner, JDK, and SDK all track latest | | `jdk` | `jdk21` | JDK major version | Runner and SDK track latest | | `-jdk-sdk` | `2.332.0-jdk21-sdk36` | Everything | Nothing — fully pinned | +| `-jdk-sdk-ndk` | `2.338.0-jdk21-sdk36.1-ndk30.0.16248370` | Same image, NDK spelled out | Nothing — fully pinned | +| `-jdk-sdk-bt-ndk` | `2.338.0-jdk21-sdk37.2-bt37.0.0-ndk30.0.16248370` | Same image, build-tools and NDK spelled out | Nothing — fully pinned | + +The longer tags exist so a consumer can let Renovate derive its Gradle +`compileSdk`, `buildToolsVersion` and `ndkVersion` from the image pin: when they +match what the image ships, AGP doesn't download SDK components on every job. ### Which tag should I use? From 1c0fc592c7c02d655244dd47869bf115468b464d Mon Sep 17 00:00:00 2001 From: Jason Ernst Date: Mon, 12 Oct 2026 12:17:55 -0700 Subject: [PATCH 2/2] README: same-image tag examples use the same (current) SDK level Co-Authored-By: Claude Opus 5.5 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ffb0d70..8a8ac71 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ version, and Android SDK level. Tags let you choose how tightly to pin: | `jdk` | `jdk21` | JDK major version | Runner and SDK track latest | | `-jdk-sdk` | `2.332.0-jdk21-sdk36` | Everything | Nothing — fully pinned | | `-jdk-sdk-ndk` | `2.338.0-jdk21-sdk36.1-ndk30.0.16248370` | Same image, NDK spelled out | Nothing — fully pinned | -| `-jdk-sdk-bt-ndk` | `2.338.0-jdk21-sdk37.2-bt37.0.0-ndk30.0.16248370` | Same image, build-tools and NDK spelled out | Nothing — fully pinned | +| `-jdk-sdk-bt-ndk` | `2.338.0-jdk21-sdk36.1-bt37.0.0-ndk30.0.16248370` | Same image, build-tools and NDK spelled out | Nothing — fully pinned | The longer tags exist so a consumer can let Renovate derive its Gradle `compileSdk`, `buildToolsVersion` and `ndkVersion` from the image pin: when they