android-builder

Native linux/amd64 Android build toolchain for CI, published to the Gitea container registry at git.helu.ca/r/android.

App repos consume this image to build signed release artifacts. Instrumented tests are not part of this toolchain — by design, CI builds are promotions of code already tested in Dev (on Apple silicon, where the emulator runs natively).

Publishing to Google Play? See docs/google-play-publishing.md — the reusable Heluca playbook (publisher setup, upload keystore, per-app checklist, internal testing, promotion to production), learned from shipping Dade.

Why amd64: Google publishes the Linux Android build-tools (aapt2, d8, …) for x86_64 only — there is no arm64 Linux build-tools package. Running the toolchain on an aarch64 runner fails at resource packaging (aapt2: Syntax error: newline unexpected, an x86_64 binary the kernel can't exec). The produced APK/AAB is architecture-neutral regardless of build host, so building on amd64 costs nothing on the output side.

What's in the image

  • Eclipse Temurin JDK 21 (native amd64)
  • Android cmdline-tools, platform, and build-tools — baked in, so prod builds don't depend on Google's download endpoint at job time
  • git, curl, unzip
  • Node.js 24 — so Gitea Actions JS actions (actions/checkout, upload-artifact, …) run when this image is used as a job container

Pinned versions live as ARGs at the top of the Dockerfile:

ARG Default Where to check
CMDLINE_TOOLS_VERSION 13114758 https://developer.android.com/studio#command-line-tools-only
BUILD_TOOLS_VERSION 36.0.0 SDK Manager / release notes
PLATFORM_VERSION android-36 your app's compileSdk

The build-tools binaries (aapt2, d8) are x86_64 ELF — this is why the image is amd64 (see "Why amd64" above).

Tagging model

The whole point of owning this image is that app repos pin a tag and a new toolchain never lands in a prod build by accident.

  • Immutable — a git tag like 2026.06 produces git.helu.ca/r/android:2026.06. This is what app repos pin to.
  • Moving — pushes to main (and any tag build) refresh git.helu.ca/r/android:latest for convenience. Don't pin prod builds to this.

Cutting a new toolchain

  1. Update the ARG defaults in the Dockerfile if you're moving SDK/tool versions. Verify CMDLINE_TOOLS_VERSION against the link above — a stale number 404s the image build.
  2. Commit to main. The workflow builds and pushes :latest; confirm it's green.
  3. Tag the release with the year-month you want app repos to reference:
    git tag 2026.06
    git push origin 2026.06
    
    This publishes the immutable git.helu.ca/r/android:2026.06.
  4. Roll app repos forward deliberately by bumping their pinned tag (see below) — one at a time if you want to validate, all at once if you trust the bump.

Using it in an app repo

Drop .gitea/workflows/build.yml (the template alongside this repo) into the app and pin the toolchain:

jobs:
  build:
    runs-on: ubuntu-24.04
    container:
      image: git.helu.ca/r/android:2026.06
      credentials:
        username: ${{ gitea.actor }}
        password: ${{ secrets.PACKAGE_TOKEN }}

The build task is selectable: assembleRelease (APK, the default) or bundleRelease (AAB — only needed for Google Play distribution).

Required secrets in each app repo (or org-level)

Signing happens at job time; nothing sensitive lives in the repo or the image.

Secret What it is
KEYSTORE_BASE64 release keystore, base64-encoded: base64 -w0 release.keystore
KEYSTORE_PASSWORD keystore password
KEY_ALIAS signing key alias
KEY_PASSWORD key password

PACKAGE_TOKEN (a PAT, the same secret the other repos here use) needs write:package in this repo (to push the image) and read:package in app repos (to pull it). Set it as a repo or org-level Actions secret. The built-in gitea.token is not used because it isn't scoped for the registry.

First-run sequencing

The image must exist in the registry before any app workflow can pull it. So: cut and push 2026.06 from this repo first, confirm it's in the registry, then the app workflows that pin it will resolve.

Description
Android build
Readme MIT 72 KiB
Languages
Dockerfile 100%