CI: cache Android SDK/NDK, Gradle, and npm across APK builds

Persist three Docker volumes into the build job (android-sdk, gradle home, npm
cache) and enable the Gradle build cache, so repeat builds skip the ~2GB NDK
download, Maven dependency resolution, and unchanged native/Kotlin compilation
— cutting builds from ~1h to a few minutes after the first run.

The runner must whitelist these volumes via config.yaml (container.valid_volumes);
deploy-runner.sh now writes that config, pre-creates the volumes, and starts the
daemon with --config. Requires re-running deploy-runner.sh on the runner host
before the next tag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Hank 2026-07-08 16:26:06 +00:00
parent 1ca2c38fbf
commit 3583c2e15f
5 changed files with 89 additions and 12 deletions

View file

@ -11,14 +11,27 @@ jobs:
runs-on: docker
container:
image: node:22-bookworm
# Persistent caches across runs (Docker named volumes). These must be
# allowed in the runner's config.yaml `container.valid_volumes` — the
# deploy-runner.sh script sets that up. First run populates them (~1h);
# later runs reuse the SDK/NDK, Gradle deps + build cache, and npm cache,
# dropping the build to a few minutes.
volumes:
- camptickets-android-sdk:/opt/android-sdk
- camptickets-gradle:/root/.gradle
- camptickets-npm:/root/.npm
env:
ANDROID_HOME: /opt/android-sdk
ANDROID_SDK_ROOT: /opt/android-sdk
GRADLE_USER_HOME: /root/.gradle
# Force IPv4 for all JVMs (Gradle launcher, daemon, Kotlin/CMake workers).
# The runner host has no working IPv6 route, so Maven Central (which has
# AAAA records) was unreachable — this makes Java ignore AAAA and use IPv4.
JAVA_TOOL_OPTIONS: -Djava.net.preferIPv4Stack=true
GRADLE_OPTS: -Dorg.gradle.jvmargs=-Xmx4g -Dorg.gradle.daemon=false
# org.gradle.caching enables the local build cache (persisted in
# GRADLE_USER_HOME), so unchanged native/Kotlin tasks are restored instead
# of recompiled.
GRADLE_OPTS: -Dorg.gradle.jvmargs=-Xmx4g -Dorg.gradle.daemon=false -Dorg.gradle.caching=true
steps:
- name: Checkout
uses: actions/checkout@v4
@ -36,16 +49,25 @@ jobs:
apt-get install -y --no-install-recommends openjdk-17-jdk-headless unzip wget git
echo "JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64" >> "$GITHUB_ENV"
- name: Install Android SDK
- name: Install Android SDK (cached)
run: |
set -eux
mkdir -p "$ANDROID_HOME/cmdline-tools"
cd /tmp
wget -q https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O cmdtools.zip
unzip -q cmdtools.zip -d "$ANDROID_HOME/cmdline-tools"
mv "$ANDROID_HOME/cmdline-tools/cmdline-tools" "$ANDROID_HOME/cmdline-tools/latest"
set -eu
# Skip the whole install when the cache volume already has the SDK.
# (NDK + CMake are auto-installed by Gradle into the same volume on
# the first build, so they persist too.)
if [ ! -x "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" ]; then
echo "Installing Android command-line tools..."
mkdir -p "$ANDROID_HOME/cmdline-tools"
cd /tmp
wget -q https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O cmdtools.zip
unzip -q cmdtools.zip -d "$ANDROID_HOME/cmdline-tools"
mv "$ANDROID_HOME/cmdline-tools/cmdline-tools" "$ANDROID_HOME/cmdline-tools/latest"
else
echo "Android SDK found in cache volume — skipping download."
fi
export PATH="$ANDROID_HOME/cmdline-tools/latest/bin:$PATH"
yes | sdkmanager --licenses >/dev/null || true
yes | sdkmanager --licenses >/dev/null 2>&1 || true
# sdkmanager is a no-op for packages already present in the volume.
sdkmanager --install "platform-tools" \
"platforms;android-36" "platforms;android-35" \
"build-tools;36.0.0" "build-tools;35.0.0" >/dev/null
@ -73,7 +95,7 @@ jobs:
CAMPSCAN_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
run: |
chmod +x ./gradlew
./gradlew assembleRelease --init-script ../../ci/signing.gradle --no-daemon
./gradlew assembleRelease --init-script ../../ci/signing.gradle --no-daemon --build-cache
mkdir -p "$GITHUB_WORKSPACE/artifacts"
cp app/build/outputs/apk/release/app-release.apk \
"$GITHUB_WORKSPACE/artifacts/camp-scan-${{ steps.ver.outputs.tag }}.apk"