Context
Sub-issue of #535. Depends on #653 (iOS) and #654 (Android). Automates the build + upload process so every push to main produces a new TestFlight / Play Internal build without manual Xcode/Android Studio steps.
Strategy
Use GitHub Actions with:
- iOS:
macos-latest runner with Xcode + fastlane (or direct xcodebuild)
- Android:
ubuntu-latest runner with Java + Gradle
Secrets needed (add to GitHub repo settings)
```
APPLE_ID
APP_SPECIFIC_PASSWORD # Apple app-specific password for altool
APPLE_TEAM_ID
IOS_DISTRIBUTION_CERT_P12 # base64-encoded .p12
IOS_DISTRIBUTION_CERT_PASSWORD
IOS_PROVISIONING_PROFILE # base64-encoded .mobileprovision
ANDROID_KEYSTORE_BASE64 # base64-encoded .keystore
ANDROID_KEYSTORE_PASSWORD
ANDROID_KEY_PASSWORD
GOOGLE_PLAY_JSON_KEY # service account JSON for Play API
```
Workflow: .github/workflows/native-build.yml
Triggers on push to main or manual dispatch.
Steps (iOS job — runs on macos-latest)
- Checkout
- Install Node + yarn, run
next build
npx cap sync ios
- Decode + install distribution cert + provisioning profile
xcodebuild archive → xcodebuild -exportArchive
- Upload
.ipa to TestFlight via altool or xcrun notarytool
Steps (Android job — runs on ubuntu-latest)
- Checkout
- Install Node + yarn, run
next build
npx cap sync android
- Decode keystore from secret
./gradlew bundleRelease
- Upload
.aab to Play Internal Testing via google-github-actions/upload-to-play
Version bumping
Auto-increment build number from GITHUB_RUN_NUMBER so every CI build has a unique number. Version string set from package.json.
Tasks
Depends on
#653 (iOS build), #654 (Android build)
Context
Sub-issue of #535. Depends on #653 (iOS) and #654 (Android). Automates the build + upload process so every push to
mainproduces a new TestFlight / Play Internal build without manual Xcode/Android Studio steps.Strategy
Use GitHub Actions with:
macos-latestrunner with Xcode +fastlane(or directxcodebuild)ubuntu-latestrunner with Java + GradleSecrets needed (add to GitHub repo settings)
```
APPLE_ID
APP_SPECIFIC_PASSWORD # Apple app-specific password for altool
APPLE_TEAM_ID
IOS_DISTRIBUTION_CERT_P12 # base64-encoded .p12
IOS_DISTRIBUTION_CERT_PASSWORD
IOS_PROVISIONING_PROFILE # base64-encoded .mobileprovision
ANDROID_KEYSTORE_BASE64 # base64-encoded .keystore
ANDROID_KEYSTORE_PASSWORD
ANDROID_KEY_PASSWORD
GOOGLE_PLAY_JSON_KEY # service account JSON for Play API
```
Workflow:
.github/workflows/native-build.ymlTriggers on push to
mainor manual dispatch.Steps (iOS job — runs on
macos-latest)next buildnpx cap sync iosxcodebuild archive→xcodebuild -exportArchive.ipato TestFlight viaaltoolorxcrun notarytoolSteps (Android job — runs on
ubuntu-latest)next buildnpx cap sync android./gradlew bundleRelease.aabto Play Internal Testing viagoogle-github-actions/upload-to-playVersion bumping
Auto-increment build number from
GITHUB_RUN_NUMBERso every CI build has a unique number. Version string set frompackage.json.Tasks
.github/workflows/native-build.ymlwith iOS + Android jobs.ipaand uploads to TestFlight.aaband uploads to Play InternalDepends on
#653 (iOS build), #654 (Android build)