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> |
||
|---|---|---|
| .. | ||
| .env.example | ||
| config.yaml | ||
| docker-compose.yml | ||
| README.md | ||
Forgejo Actions runner (APK builds)
Run this on the roomy server (where Forgejo lives / where there's disk for the ~3–4 GB Android SDK), not on the app host — the Android build needs several GB of scratch space that the small app host doesn't have.
Deploy
- Copy this
runner/directory to the roomy server (or clone the repo there). - In Forgejo →
Beartaria/CampgroundTickets→ Settings → Actions → Runners → Create new runner, copy the registration token. - Create
.envfrom the example and fill it in:cp .env.example .env # REGISTRATION_TOKEN=<the token from Forgejo> # DOCKER_GID=<output of: stat -c %g /var/run/docker.sock on THIS server> - Start it:
mkdir -p data && sudo chown -R 1000:1000 data docker compose up -d docker compose logs -f # expect "declared successfully" then "poller launched"
The runner advertises the docker label; the build workflow (.forgejo/workflows/build-apk.yml) runs jobs in a node:22-bookworm container and installs the Android SDK itself.
Build an APK
- One-time: generate a keystore with
../scripts/gen-keystore.shand add the fourANDROID_*secrets to the repo (see the main README → APK builds). - Push a tag:
git tag v0.1.0 && git push origin v0.1.0. - The runner builds
camp-scan-v0.1.0.apkand attaches it to a Forgejo release; Obtainium picks it up.
Build caching (fast repeat builds)
The first APK build takes ~1h (downloads Gradle + the ~2GB Android NDK, resolves all Maven deps, compiles native modules). After that it should drop to a few minutes because three persistent Docker volumes are reused across runs:
| Volume | Holds |
|---|---|
camptickets-android-sdk → /opt/android-sdk |
SDK, NDK, CMake |
camptickets-gradle → /root/.gradle |
Gradle dist, Maven deps, local build cache |
camptickets-npm → /root/.npm |
npm download cache |
For this to work the runner must allow these volumes via config.yaml
(container.valid_volumes) — deploy-runner.sh writes that config, pre-creates
the volumes, and starts the daemon with --config /data/config.yaml. If you set
the runner up by hand, copy config.yaml next to the compose file and add
--config /data/config.yaml to the daemon command.
To force a clean rebuild, remove the volumes:
docker volume rm camptickets-android-sdk camptickets-gradle camptickets-npm.
Notes
- The runner I initially registered on the app host has been removed. If Forgejo
still lists an offline
camptickets-runner, delete it from Settings → Actions → Runners. DOCKER_GIDmust match the roomy server's docker socket group, or the runner can't reach the Docker daemon.- After updating to a caching-enabled runner, re-run
deploy-runner.sh(ordocker compose up -din the runner dir) so the newconfig.yaml+ volumes take effect, then push a fresh tag.