# Android client CI (Gitea Actions). Builds the Rust JNI core (crates/punktfunk-android) via # cargo-ndk for both shipping ABIs and assembles the debug APK (clients/android). Mirrors apple.yml # but on a Linux runner — the NDK is cross-platform, so no self-hosted host is needed. # # Prereq: the runner needs ~6 GB free + internet (it pulls the Android SDK/NDK and the Gradle # distribution in-job). If android-actions/setup-android is not mirrored on this Gitea instance, # replace that step with a manual cmdline-tools download, or bake an `android-ci` image like # ci/rust-ci.Dockerfile. Emulator instrumentation tests are deferred until a KVM-capable runner # exists (they self-skip otherwise, like apple.yml's RemoteFirstLightTests). name: android on: push: branches: [main] pull_request: workflow_dispatch: jobs: android: runs-on: ubuntu-24.04 timeout-minutes: 60 steps: - uses: actions/checkout@v4 - name: JDK 21 (AGP 9.2 runs on JDK 17–21, not the host default) uses: actions/setup-java@v4 with: distribution: temurin java-version: "21" - name: Rust toolchain + Android targets (self-healing on a fresh runner) run: | if ! command -v rustup >/dev/null && [ ! -x "$HOME/.cargo/bin/rustup" ]; then curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \ | sh -s -- -y --no-modify-path --profile minimal fi RUSTUP="$(command -v rustup || echo "$HOME/.cargo/bin/rustup")" dirname "$RUSTUP" >> "$GITHUB_PATH" "$RUSTUP" target add aarch64-linux-android x86_64-linux-android - name: Android SDK uses: android-actions/setup-android@v3 - name: NDK r30 + platform 36 + build-tools + CMake (libopus cross-build) # cmake;3.22.1 installs cmake + ninja under $ANDROID_SDK/cmake/3.22.1/bin — the exact path # kit/build.gradle.kts prepends to PATH for cargo-ndk's audiopus_sys (libopus) CMake build. # Note: platforms;android-37 is sometimes missing from standard channels; AGP will # auto-download it if needed during the build. run: sdkmanager "platform-tools" "platforms;android-36" "build-tools;37.0.0" "ndk;30.0.14904198" "cmake;3.22.1" - name: Caches (cargo + gradle) uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git ~/.gradle/caches ~/.gradle/wrapper target key: android-${{ hashFiles('Cargo.lock', 'clients/android/**/*.gradle.kts') }} restore-keys: android- - name: cargo-ndk run: command -v cargo-ndk >/dev/null || cargo install cargo-ndk - name: assembleDebug (cargo-ndk → jniLibs → APK) working-directory: clients/android env: VERSION_CODE: ${{ github.run_number }} run: ./gradlew :app:assembleDebug --stacktrace - name: Build Release Bundle (AAB) if: github.event_name == 'push' && github.ref == 'refs/heads/main' working-directory: clients/android env: VERSION_CODE: ${{ github.run_number }} RELEASE_KEYSTORE_FILE: "../release.jks" RELEASE_KEYSTORE_PASSWORD: ${{ secrets.RELEASE_KEYSTORE_PASSWORD }} RELEASE_KEY_ALIAS: ${{ secrets.RELEASE_KEY_ALIAS }} RELEASE_KEY_PASSWORD: ${{ secrets.RELEASE_KEY_PASSWORD }} run: | echo "${{ secrets.RELEASE_KEYSTORE_BASE64 }}" | base64 -d > release.jks ./gradlew :app:bundleRelease --stacktrace - name: Upload to Google Play (Internal Testing) if: github.event_name == 'push' && github.ref == 'refs/heads/main' uses: r0adkll/upload-google-play@v1 with: serviceAccountJsonKeyData: ${{ secrets.SERVICE_ACCOUNT_JSON }} packageName: io.unom.punktfunk releaseFiles: clients/android/app/build/outputs/bundle/release/app-release.aab track: internal status: completed