Skip to content

Add iOS/Android build jobs to release.yml with signing secrets #3345

Description

@houko

Part of Epic #3351 — mobile client support (iOS + Android via Tauri 2).

Problem

.github/workflows/release.yml matrix only covers desktop targets (macOS x86_64+aarch64 / Linux x86_64+aarch64 gnu+musl / Windows x86_64+aarch64). After #3342 lands, mobile builds are still local-only — no automated CI artifact, no nightly, no release attached .aab / .ipa. This blocks beta distribution.

Approach

Add two CI jobs to release.yml. Treat them as best-effort initially: don't gate the desktop release on mobile build success — mobile signing infra is uniquely fragile and a flaky cert refresh shouldn't block a Linux deb.

Android job

  • Runner: ubuntu-latest
  • Toolchain: Java 17 (Temurin), Android SDK + NDK r26 via android-actions/setup-android@v3, Rust target aarch64-linux-android + armv7-linux-androideabi
  • Build: cargo tauri android build --apk --aab --target aarch64
  • Sign: ${{ secrets.ANDROID_KEYSTORE_B64 }} decoded into a temp keystore, signed via Gradle. Keystore password and key alias come from secrets.
  • Upload: attach .aab (Play Store) and .apk (sideload) to the GitHub release.

iOS job

  • Runner: macos-14 (Apple Silicon — required for current Xcode)
  • Xcode: pin to a known-good major (15.x at time of writing); use maxim-lobanov/setup-xcode@v1.
  • Rust target: aarch64-apple-ios (devices) and aarch64-apple-ios-sim for simulator dev (don't ship sim builds, just verify it compiles).
  • Signing: import .p12 from ${{ secrets.APPLE_CERT_P12 }} + ${{ secrets.APPLE_CERT_PASSWORD }} into a temp keychain via apple-actions/import-codesign-certs@v3. Provisioning profile from ${{ secrets.APPLE_PROVISIONING_PROFILE_B64 }}.
  • Build: cargo tauri ios build --target aarch64
  • Output: .ipa for TestFlight upload (TestFlight upload itself is in Mobile distribution: Apple Developer, Play Console, TestFlight, Internal Testing #3348).

Cross-cutting

  • Add mobile-build workflow_dispatch trigger so maintainers can run a one-off mobile build without cutting a release.
  • On PRs that touch crates/librefang-desktop/** or gen/**, run a build-only smoke test (no signing, debug builds) to catch breakage before merge.
  • Cache: Cargo registry + Gradle + CocoaPods. First-time runs without cache take ~25 min on Android, ~30 min on iOS — make sure cache hit gets each under 8 min.

Required secrets

Document expected secrets in .github/SECRETS.md (or update existing):

  • ANDROID_KEYSTORE_B64 — base64-encoded .jks keystore.
  • ANDROID_KEYSTORE_PASSWORD — keystore password.
  • ANDROID_KEY_ALIAS — release key alias.
  • ANDROID_KEY_PASSWORD — alias password.
  • APPLE_TEAM_ID — 10-char Apple developer team ID.
  • APPLE_CERT_P12 — base64-encoded distribution .p12.
  • APPLE_CERT_PASSWORD.p12 password.
  • APPLE_PROVISIONING_PROFILE_B64 — base64 .mobileprovision.

Rotation cadence: Apple cert is yearly, Android keystore is forever (lose it = lose Play Store identity, back it up offline).

Acceptance criteria

  • Android job in release.yml produces a signed .aab and .apk attached to GitHub releases.
  • iOS job produces a signed .ipa attached to GitHub releases.
  • PR check mobile-build-smoke runs unsigned debug builds on PRs that touch the mobile surface; turnaround < 12 min on cache hit.
  • Mobile job failures do not block the desktop release jobs (independent matrix legs).
  • .github/SECRETS.md lists every required secret with rotation guidance.
  • Manual run of the workflow_dispatch trigger from a maintainer's branch produces both artifacts without touching main.

Depends on #3342. Should land before #3348 (which depends on these artifacts existing in CI).

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/ciCI/CD and build toolingarea/desktopTauri desktop applicationdifficulty/mediumHalf day, some familiarity with the crateenhancementNew feature or requesthas-prA pull request has been linked to this issueseverity/lowMinor issue, polish, or developer ergonomics

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions