feat(ci): pre-built Android builder image + sccache
Build Android Builder Image / build (push) Failing after 3m54s

Replaces the 5 per-run tool-install steps (~2m 30s) with a pre-built
container image (git.aleshym.co/funman300/android-builder) that ships
Ubuntu 22.04 + Java 17 + Android SDK/NDK + Rust stable + aarch64 target
+ cargo-ndk + sccache. android-release.yml now runs inside the container
and adds two cache steps instead: Cargo registry and sccache directory.

sccache (RUSTC_WRAPPER) caches at the translation-unit level so partial
hits survive Cargo.lock changes — far more resilient than caching the
full target/ directory.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-05-16 10:47:05 -07:00
parent c24c7f6b61
commit e48f652454
3 changed files with 112 additions and 51 deletions
+26 -51
View File
@@ -6,10 +6,6 @@ on:
- 'v*' - 'v*'
env: env:
ANDROID_HOME: /opt/android-sdk
NDK_VERSION: 30.0.14904198
BUILD_TOOLS_VERSION: "36.1.0"
PLATFORM: android-34
APK_OUT: target/release/apk/ferrous-solitaire.apk APK_OUT: target/release/apk/ferrous-solitaire.apk
GITEA_URL: https://git.aleshym.co GITEA_URL: https://git.aleshym.co
REPO: funman300/Ferrous-Solitaire REPO: funman300/Ferrous-Solitaire
@@ -17,64 +13,42 @@ env:
jobs: jobs:
build-apk: build-apk:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container:
image: git.aleshym.co/funman300/android-builder:latest
credentials:
username: ${{ gitea.actor }}
password: ${{ secrets.CI_TOKEN }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Set up Java 17 - name: Cache Cargo registry
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
- name: Cache Android SDK
uses: actions/cache@v4
id: android-cache
with:
path: /opt/android-sdk
key: android-sdk-${{ env.NDK_VERSION }}-${{ env.BUILD_TOOLS_VERSION }}
- name: Install Android SDK + NDK
if: steps.android-cache.outputs.cache-hit != 'true'
run: |
mkdir -p $ANDROID_HOME/cmdline-tools
wget -q https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip \
-O /tmp/cmdtools.zip
unzip -q /tmp/cmdtools.zip -d $ANDROID_HOME/cmdline-tools
mv $ANDROID_HOME/cmdline-tools/cmdline-tools $ANDROID_HOME/cmdline-tools/latest
yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses >/dev/null || true
$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager \
"ndk;$NDK_VERSION" \
"build-tools;$BUILD_TOOLS_VERSION" \
"platforms;$PLATFORM"
- name: Set up Rust (stable + aarch64-android)
uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-linux-android
- name: Cache Cargo
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
path: | path: |
~/.cargo/registry/index /usr/local/cargo/registry/index
~/.cargo/registry/cache /usr/local/cargo/registry/cache
~/.cargo/git/db /usr/local/cargo/git/db
~/.cargo/bin/cargo-ndk key: cargo-registry-android-${{ hashFiles('**/Cargo.lock') }}
target/aarch64-linux-android restore-keys: cargo-registry-android-
key: cargo-android-${{ hashFiles('**/Cargo.lock') }}
restore-keys: cargo-android-
- name: Install cargo-ndk - name: Cache sccache
run: cargo-ndk --version 2>/dev/null || cargo install cargo-ndk --version 4.1.2 --locked uses: actions/cache@v4
with:
path: /root/.cache/sccache
key: sccache-android-aarch64-${{ hashFiles('**/Cargo.lock') }}
restore-keys: sccache-android-aarch64-
- name: Get tag name
id: tag
run: echo "name=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
- name: Decode release keystore - name: Decode release keystore
run: echo "${{ secrets.RELEASE_KEYSTORE_B64 }}" | base64 -d > release.jks run: echo "${{ secrets.RELEASE_KEYSTORE_B64 }}" | base64 -d > release.jks
- name: Build release APK - name: Build release APK
env: env:
ANDROID_NDK_HOME: /opt/android-sdk/ndk/${{ env.NDK_VERSION }}
PROFILE: release PROFILE: release
ABIS: arm64-v8a ABIS: arm64-v8a
KEYSTORE: ./release.jks KEYSTORE: ./release.jks
@@ -82,11 +56,13 @@ jobs:
KEY_ALIAS: release KEY_ALIAS: release
KEY_PASS: ${{ secrets.RELEASE_KEYSTORE_PASS }} KEY_PASS: ${{ secrets.RELEASE_KEYSTORE_PASS }}
VERSION_NAME: ${{ steps.tag.outputs.name }} VERSION_NAME: ${{ steps.tag.outputs.name }}
RUSTC_WRAPPER: sccache
SCCACHE_DIR: /root/.cache/sccache
run: bash scripts/build_android_apk.sh run: bash scripts/build_android_apk.sh
- name: Get tag name - name: sccache stats
id: tag if: always()
run: echo "name=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT" run: sccache --show-stats
- name: Create or get Gitea release - name: Create or get Gitea release
id: release id: release
@@ -95,7 +71,6 @@ jobs:
BASE="${{ env.GITEA_URL }}/api/v1/repos/${{ env.REPO }}" BASE="${{ env.GITEA_URL }}/api/v1/repos/${{ env.REPO }}"
AUTH="Authorization: token ${{ secrets.CI_TOKEN }}" AUTH="Authorization: token ${{ secrets.CI_TOKEN }}"
# Re-use an existing release for this tag (e.g. created manually).
ID=$(curl -sf -H "$AUTH" "$BASE/releases/tags/$TAG" \ ID=$(curl -sf -H "$AUTH" "$BASE/releases/tags/$TAG" \
| python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" \ | python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" \
2>/dev/null || true) 2>/dev/null || true)
+41
View File
@@ -0,0 +1,41 @@
name: Build Android Builder Image
on:
push:
branches: [master]
paths:
- 'docker/android-builder.Dockerfile'
- '.gitea/workflows/builder-image.yml'
env:
IMAGE: git.aleshym.co/funman300/android-builder
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Log in to Gitea registry
uses: docker/login-action@v3
with:
registry: git.aleshym.co
username: ${{ gitea.actor }}
password: ${{ secrets.CI_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: network=host
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: docker/android-builder.Dockerfile
push: true
tags: ${{ env.IMAGE }}:latest
cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache
cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max
+45
View File
@@ -0,0 +1,45 @@
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive \
ANDROID_HOME=/opt/android-sdk \
NDK_VERSION=30.0.14904198 \
BUILD_TOOLS_VERSION=36.1.0 \
PLATFORM=android-34 \
RUSTUP_HOME=/usr/local/rustup \
CARGO_HOME=/usr/local/cargo
ENV ANDROID_NDK_HOME=${ANDROID_HOME}/ndk/${NDK_VERSION} \
PATH=/usr/local/cargo/bin:$PATH
RUN apt-get update && apt-get install -y --no-install-recommends \
openjdk-17-jdk-headless \
wget unzip curl ca-certificates git zip python3 \
&& rm -rf /var/lib/apt/lists/*
# Android SDK command-line tools
RUN mkdir -p "$ANDROID_HOME/cmdline-tools" \
&& wget -q https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip \
-O /tmp/cmdtools.zip \
&& unzip -q /tmp/cmdtools.zip -d "$ANDROID_HOME/cmdline-tools" \
&& mv "$ANDROID_HOME/cmdline-tools/cmdline-tools" "$ANDROID_HOME/cmdline-tools/latest" \
&& rm /tmp/cmdtools.zip \
&& yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --licenses >/dev/null 2>&1 || true \
&& "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" \
"ndk;${NDK_VERSION}" \
"build-tools;${BUILD_TOOLS_VERSION}" \
"platforms;${PLATFORM}"
# Rust stable + aarch64-linux-android target
RUN curl -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path --default-toolchain stable \
&& rustup target add aarch64-linux-android
# cargo-ndk (compiled once into the image)
RUN cargo install cargo-ndk --version 4.1.2 --locked \
&& rm -rf "$CARGO_HOME/registry" "$CARGO_HOME/git"
# sccache — pre-built musl binary, no Rust compile needed
RUN curl -sL "https://github.com/mozilla/sccache/releases/download/v0.8.1/sccache-v0.8.1-x86_64-unknown-linux-musl.tar.gz" \
| tar xz -C /tmp \
&& mv /tmp/sccache-v0.8.1-x86_64-unknown-linux-musl/sccache /usr/local/bin/sccache \
&& rm -rf /tmp/sccache-v0.8.1-x86_64-unknown-linux-musl \
&& chmod +x /usr/local/bin/sccache