Files
punktfunk/.gitea/workflows/android.yml
T
enricobuehler 4563a0490c chore(release): bump workspace version to 0.4.1; canary base to 0.5.0
The [workspace.package] version (inherited by every crate via version.workspace)
lagged at 0.3.0 through the 0.4.0 release — bump it to 0.4.1, the release being
cut, and refresh the 8 workspace entries in Cargo.lock to match (CI builds
--locked).

Also advance the CI canary-base fallbacks (deb/rpm/flatpak/android/release
workflows + build-rpm.sh) from 0.3.0 to 0.5.0 so main/canary builds sort one
minor ahead of the latest stable line, per the documented channel convention.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 19:22:42 +02:00

154 lines
8.0 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Android client CI (Gitea Actions). Builds the Rust JNI core (clients/android/native) 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]
# Single project version: a `vX.Y.Z` tag is THE release (uploads to Play's `alpha` closed
# track for manual promotion + attaches the .aab/.apk to the unified Gitea Release). A main
# push is canary (Play `internal`).
tags: ['v*']
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 1721, 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
# Single source of the version name + the Play track for the release steps below. versionCode
# stays github.run_number (monotonic across both tracks; Play rejects a regressed code).
- name: Version + channel
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
run: |
case "$GITHUB_REF" in
refs/tags/v*) VN="${GITHUB_REF_NAME#v}"; TRACK="alpha" ;; # alpha = built-in closed testing
*) VN="0.5.0-ci${GITHUB_RUN_NUMBER}"; TRACK="internal" ;;
esac
echo "VERSION_NAME=$VN" >> "$GITHUB_ENV"
echo "PLAY_TRACK=$TRACK" >> "$GITHUB_ENV"
echo "android version $VN -> Play track '$TRACK'"
- name: Build Release (signed AAB + universal APK)
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
working-directory: clients/android
env:
VERSION_CODE: ${{ github.run_number }} # VERSION_NAME comes from the Version+channel step (GITHUB_ENV)
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
# AAB for Play; a universal APK (both ABIs) for direct sideload/testing — same upload key.
./gradlew :app:bundleRelease :app:assembleRelease --stacktrace
# Publish BEFORE the Play upload so artifacts land even while the Play step is still failing.
# Generic registry is public for reads — matches windows-msix.yml / deb.yml (REGISTRY_TOKEN, user enricobuehler).
# main = canary store + `canary/` sideload alias; a `vX.Y.Z` tag = `latest/` alias + attached
# to the unified Gitea Release.
- name: Publish to generic registry + attach to Gitea release
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
env:
REGISTRY: git.unom.io
OWNER: unom
PKG: punktfunk-android
VERSION: ${{ github.run_number }}
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: |
AAB=clients/android/app/build/outputs/bundle/release/app-release.aab
APK=clients/android/app/build/outputs/apk/release/app-release.apk
base="https://$REGISTRY/api/packages/$OWNER/generic/$PKG"
# 1) immutable, run-number-versioned store (sideload + provenance)
curl -fsS --user "enricobuehler:$REGISTRY_TOKEN" --upload-file "$AAB" "$base/$VERSION/punktfunk-android-r$VERSION.aab"
curl -fsS --user "enricobuehler:$REGISTRY_TOKEN" --upload-file "$APK" "$base/$VERSION/punktfunk-android-r$VERSION.apk"
echo "published store version $VERSION (versionCode)"
# 2) channel alias for a predictable sideload URL: stable -> latest/, canary -> canary/
case "$GITHUB_REF" in refs/tags/v*) ALIAS=latest ;; *) ALIAS=canary ;; esac
curl -fsS -o /dev/null --user "enricobuehler:$REGISTRY_TOKEN" -X DELETE "$base/$ALIAS/punktfunk-android.apk" || true
curl -fsS --user "enricobuehler:$REGISTRY_TOKEN" --upload-file "$APK" "$base/$ALIAS/punktfunk-android.apk"
echo "sideload alias: $base/$ALIAS/punktfunk-android.apk"
# 3) on a real release, attach the .aab + .apk to the unified Gitea Release (X.Y.Z names)
case "$GITHUB_REF" in
refs/tags/v*)
. scripts/ci/gitea-release.sh
RID=$(ensure_release "$GITHUB_REF_NAME" "$GITHUB_REF_NAME" auto)
upsert_asset "$RID" "$AAB" "punktfunk-${VERSION_NAME}.aab"
upsert_asset "$RID" "$APK" "punktfunk-${VERSION_NAME}.apk"
;;
esac
# Direct Publishing-API upload instead of r0adkll/upload-google-play — that action hides the
# real API error behind "Unknown error occurred."; this prints it. stdlib + openssl only (no
# pip), reuses SERVICE_ACCOUNT_JSON (raw JSON or base64), auto-handles changesNotSentForReview.
# Track: canary main -> `internal`; a vX.Y.Z release -> `alpha` (closed testing) for manual
# promotion to production in the Play console.
- name: Upload to Google Play
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
env:
SERVICE_ACCOUNT_JSON: ${{ secrets.SERVICE_ACCOUNT_JSON }}
run: |
echo "uploading to Play track '$PLAY_TRACK'"
python3 clients/android/ci/play-upload.py \
--package io.unom.punktfunk \
--aab clients/android/app/build/outputs/bundle/release/app-release.aab \
--track "$PLAY_TRACK" --status completed