# Build a signed release APK and publish it as a Forgejo release on every v* tag. # Obtainium then tracks releases and offers the update. # # Requires: # - A Forgejo Actions RUNNER registered to this repo/instance (see docs/DISTRIBUTION.md), # with a label this job's `runs-on` matches (adjust below to your runner's labels). # - Repo Actions secrets: ANDROID_KEYSTORE_B64, ANDROID_KEYSTORE_PASSWORD, # ANDROID_KEY_ALIAS, ANDROID_KEY_PASSWORD (already set). # # Release: bump `expo.version` in app/app.json, then: git tag v0.1.1 && git push origin v0.1.1 name: build-apk on: push: tags: - 'v*' jobs: build: # Match this to a label your runner registered with (commonly "docker" or "ubuntu-latest"). runs-on: docker # 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 steps: - uses: actions/checkout@v4 - name: Install dependencies run: npm install - name: Build the API client run: npm run build --workspace parksmarter-client # RN 0.79 wants a specific NDK; install it if the image doesn't ship it (best-effort). - name: Ensure NDK run: | yes | sdkmanager --licenses >/dev/null 2>&1 || true sdkmanager "ndk;27.1.12297006" >/dev/null 2>&1 || true - name: Restore signing keystore run: echo "${{ secrets.ANDROID_KEYSTORE_B64 }}" | base64 -d > "${{ github.workspace }}/app/release.keystore" - name: Expo prebuild (generate android/) working-directory: app run: CI=1 npx expo prebuild --platform android --no-install - name: Assemble signed release working-directory: app/android env: BBP_UPLOAD_STORE_FILE: ${{ github.workspace }}/app/release.keystore 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. run: >- ./gradlew :app:assembleRelease -PreactNativeArchitectures=arm64-v8a --no-daemon --max-workers=2 -Dorg.gradle.parallel=false -Djava.net.preferIPv4Stack=true # Self-contained publish via the Forgejo API (no external action to fetch). - name: Publish release + upload APK env: TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -e TAG="${GITHUB_REF_NAME}" APK="$(ls app/android/app/build/outputs/apk/release/*.apk | head -1)" ASSET="BigBrainParking-${TAG}.apk" API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}" REL="$(curl -sf -X POST "$API/releases" -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json" \ -d "{\"tag_name\":\"$TAG\",\"target_commitish\":\"main\",\"name\":\"BigBrainParking $TAG\",\"body\":\"Install/update via Obtainium.\"}")" ID="$(printf '%s' "$REL" | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>console.log(JSON.parse(s).id))")" curl -sf -X POST "$API/releases/$ID/assets?name=$ASSET" \ -H "Authorization: token $TOKEN" -F "attachment=@$APK" echo "Published $TAG"