CI: cap Kotlin daemon heap (the real memory hog) + container swap off
Some checks are pending
build-apk / build (push) Waiting to run

Server report (20GB/4-core box) showed 3 Kotlin daemons at -Xmx5376m each + clang
swarm ~9GB thrashing swap. Cap kotlin.daemon.jvmargs and org.gradle.jvmargs to
1536m in gradle.properties, workers.max=2, no parallel. Container: --cpus=2
--memory=8g with swap disabled (--memory-swap==--memory) so it OOM-fails instead
of thrashing disk. Build now uses ~5GB.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Hank 2026-07-08 10:40:39 -07:00
parent 0b8713790b
commit 208cddee33

View file

@ -22,9 +22,10 @@ jobs:
# A purpose-built RN Android image (Android SDK + NDK + Node). Runner needs Docker.
container:
image: reactnativecommunity/react-native-android:latest
# Hard caps so the build can't starve the host: at most 2 CPUs and 6 GB RAM.
# Adjust to your box (e.g. --cpus=1 / --memory=4g on a smaller server).
options: --cpus=2 --memory=6g --memory-swap=6g
# Hard caps so the build can't starve the 20GB/4-core host: 2 CPUs, 8 GB RAM,
# and NO container swap (--memory-swap == --memory) so it OOM-fails cleanly
# instead of thrashing the disk with swap. With the JVM caps below it uses ~5 GB.
options: --cpus=2 --memory=8g --memory-swap=8g
steps:
- uses: actions/checkout@v4
@ -47,6 +48,21 @@ jobs:
working-directory: app
run: CI=1 npx expo prebuild --platform android --no-install
# The real memory hog is the Kotlin daemon (default ~5.4 GB heap EACH, several
# spawned). Cap every JVM in gradle.properties so the build fits comfortably.
- name: Cap Gradle/Kotlin memory
working-directory: app/android
run: |
cat >> gradle.properties <<'PROPS'
# --- CI resource caps (host is small; don't thrash swap) ---
org.gradle.jvmargs=-Xmx1536m -XX:MaxMetaspaceSize=512m -Djava.net.preferIPv4Stack=true
org.gradle.workers.max=2
org.gradle.parallel=false
org.gradle.daemon=false
kotlin.daemon.jvmargs=-Xmx1536m
PROPS
- name: Assemble signed release
working-directory: app/android
env:
@ -54,16 +70,13 @@ jobs:
BBP_UPLOAD_STORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
BBP_UPLOAD_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
BBP_UPLOAD_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
# Force IPv4 (runner container has no IPv6 -> dl.google.com unreachable) and
# cap the build JVM heap so it stays within the container's memory limit.
GRADLE_OPTS: "-Xmx3g -XX:MaxMetaspaceSize=768m -Djava.net.preferIPv4Stack=true"
# --max-workers=2 + no parallel project builds => at most ~2 concurrent tasks,
# so gradle/kotlin/C++ compiles don't fan out across every core on the host.
# Also cap the no-daemon launcher JVM (org.gradle.jvmargs targets the daemon).
GRADLE_OPTS: "-Xmx1536m -Djava.net.preferIPv4Stack=true"
# --max-workers=2 limits concurrent tasks; container --cpus=2 caps clang -j.
run: >-
./gradlew :app:assembleRelease
-PreactNativeArchitectures=arm64-v8a
--no-daemon --max-workers=2 -Dorg.gradle.parallel=false
-Djava.net.preferIPv4Stack=true
--no-daemon --max-workers=2
# Self-contained publish via the Forgejo API (no external action to fetch).
- name: Publish release + upload APK