Formal releases with iOS runtime changes now bump MARKETING_VERSION, archive the tag via Xcode Cloud, wait until App Store Connect marks the build Valid, and submit App Review. GitHub publication stays independent of iOS outcome.
152 lines
7.3 KiB
Markdown
152 lines
7.3 KiB
Markdown
# EdgeEver Android Builds
|
|
|
|
The Android app in `apps/mobile` is built with Expo and React Native. iOS store binaries come from `apps/ios` (SwiftUI), not this tree. Main-branch Android packages are built directly on GitHub Actions, without using EAS Build quota.
|
|
|
|
## App Updates
|
|
|
|
Installed release builds use EAS Update for compatible JavaScript and asset updates. The app checks once shortly after launch and, at most once every six hours, when it returns to the foreground. Users can also open **My** -> **General settings** -> **App updates** to check manually. A downloaded update is only applied after the user confirms a restart, so an active editing session is not interrupted automatically.
|
|
|
|
The `production` build and locally generated Play build read from the `production` update channel. Preview EAS builds read from `preview`. Publish and verify an update on `preview` before promoting the same change to production:
|
|
|
|
```sh
|
|
bunx eas-cli update --channel preview --environment preview --message "Describe the update"
|
|
bunx eas-cli update --channel production --environment production --message "Describe the update"
|
|
```
|
|
|
|
The update runtime uses the app-version policy. Any native dependency, Expo SDK, native module, or native configuration change requires incrementing `expo.version` and shipping a new store build before publishing code that depends on that native change. EAS Update does not replace Google Play or App Store updates for native binaries.
|
|
|
|
## Main-Branch Android APK
|
|
|
|
The `Build EdgeEver Mobile` workflow runs on GitHub Actions and produces a
|
|
fast arm64 APK after mobile changes land on `main`. This APK uses the same
|
|
pinned production signing certificate as formal GitHub Release APKs. The fast
|
|
build only disables R8, resource shrinking, and PNG crunching; it must never
|
|
fall back to `debug.keystore`.
|
|
|
|
It runs:
|
|
|
|
```sh
|
|
bun install --frozen-lockfile
|
|
bun run typecheck:mobile
|
|
bun run build:android:fast
|
|
```
|
|
|
|
The APK is uploaded as a GitHub Actions artifact named
|
|
`edgeever-android-main-apk`. If the stable signing credentials are unavailable,
|
|
the workflow fails and does not upload an APK with a different signer.
|
|
|
|
For a local fast build, load the same signing environment used for release
|
|
builds:
|
|
|
|
```sh
|
|
bun run build:android:fast:local
|
|
```
|
|
|
|
## Release Builds
|
|
|
|
### GitHub Release APK
|
|
|
|
Every formal GitHub Release must include a directly installable APK. Build the production-signed `arm64-v8a` APK on the release Mac:
|
|
|
|
```sh
|
|
bun run build:android:apk:local
|
|
```
|
|
|
|
This produces `apps/mobile/android/app/build/outputs/apk/release/app-release.apk`.
|
|
Before upload, automation requires exactly one signer and pins its certificate
|
|
SHA-256 to
|
|
`22bf52a9501c89020f5acc966960152c826bfa64f31e578e858d088f8cd75d87`.
|
|
Any other signer fails the build. Verify the application version and APK
|
|
SHA-256 as well. Additional ABIs should only be published for an explicit
|
|
compatibility need. The Play AAB is also intentionally limited to
|
|
`arm64-v8a`, so its Play-signed universal APK remains a single-ABI download.
|
|
A release whose audited change range affects mobile runtime
|
|
code, shared code used by mobile, mobile dependencies, native configuration,
|
|
APK build tooling, or signer verification must rebuild the APK from that
|
|
release commit.
|
|
|
|
If the audited change range does not affect the mobile binary, the most recent compatible, verified APK may be attached again without rebuilding. Keep its original versioned filename and checksum, and state the source release explicitly; never rename an older binary to the current release version.
|
|
|
|
The release workflow performs this audit automatically and verifies the pinned
|
|
signer for both newly built and reused APKs. Web-only releases use an Ubuntu
|
|
planning job and copy the single verified `arm64-v8a` APK from the previous
|
|
formal Release. The self-hosted Android runner is scheduled only when the
|
|
audited range includes mobile runtime code, shared mobile packages,
|
|
dependencies, native configuration, Android build tooling, or signer
|
|
verification.
|
|
|
|
This locally signed APK is only a temporary Draft asset and is never accepted
|
|
for formal publication. After the matching AAB is delivered, the store-delivery workflow
|
|
downloads Google Play's signed universal APK and replaces the GitHub Release
|
|
asset under the established filename. Because the uploaded AAB contains only
|
|
`arm64-v8a`, the Play-generated APK also remains arm64-only. Publishing the
|
|
Play-signed APK lets Play and GitHub installations update each other without
|
|
uninstalling the app. The workflow pins and verifies the Play app-signing
|
|
certificate before replacing the asset. An independent pre-publication gate
|
|
then verifies that the Draft APK uses only that Play app-signing certificate.
|
|
|
|
### Recommended local Play build
|
|
|
|
Routine Google Play bundles should be built on the release Mac instead of in
|
|
GitHub Actions. Keep the upload keystore and signing environment outside the
|
|
repository:
|
|
|
|
```sh
|
|
mkdir -p "$HOME/.config/edgeever/android"
|
|
cp .env.android.local.example "$HOME/.config/edgeever/android/signing.env"
|
|
chmod 600 "$HOME/.config/edgeever/android/signing.env"
|
|
```
|
|
|
|
Fill in the existing upload key's absolute path and credentials. Android
|
|
keystore formats and local environment files are ignored by Git.
|
|
|
|
```sh
|
|
bun run build:android:play:local
|
|
```
|
|
|
|
This produces:
|
|
|
|
```text
|
|
apps/mobile/android/app/build/outputs/bundle/release/app-release.aab
|
|
apps/mobile/android/app/build/outputs/mapping/release/mapping.txt
|
|
```
|
|
|
|
The command builds `arm64-v8a` by default, verifies the AAB signature, and
|
|
requires a non-empty R8 mapping file. This keeps the Play-generated universal
|
|
APK suitable for the arm64 GitHub Release asset instead of bundling unused
|
|
32-bit ARM and x86 native libraries. Keep an encrypted backup of `signing.env`
|
|
and the upload keystore outside the repository. Do not replace or regenerate
|
|
the upload key for an existing Play app unless the key reset has been completed
|
|
in Play Console.
|
|
|
|
Set `EDGE_EVER_ANDROID_ENV_FILE` to use a different secure environment file.
|
|
|
|
### Automated store delivery
|
|
|
|
The GitHub Release workflow never builds or uploads a Play bundle. Before a
|
|
Draft that contains mobile changes can be published, use the separate
|
|
store-delivery workflow. It builds a signed AAB from the immutable Release tag,
|
|
preserves the AAB and R8 mapping as Actions artifacts, and uploads the bundle
|
|
through EAS Submit. It then replaces the GitHub APK with the Play-signed
|
|
universal APK. Rerun the release command after that workflow succeeds; it
|
|
audits the Play signer and resumes publication. See
|
|
[Mobile Store Delivery](store-delivery.md).
|
|
|
|
The upload keystore is only used to prove ownership when uploading bundles;
|
|
Google Play App Signing manages the app signing key delivered to users. Keep an
|
|
encrypted backup of the upload keystore and its credentials outside the
|
|
repository.
|
|
|
|
### iOS App Store build
|
|
|
|
iOS is a SwiftUI app in `apps/ios`, using the same bundle identifier
|
|
`org.edgeever.mobile`. Do not build or submit iOS from `apps/mobile` or EAS.
|
|
On macOS beta hosts, archives must go through Xcode Cloud. Formal Releases
|
|
start that Archive and submit App Review automatically when iOS runtime
|
|
changes are in the audited range. See
|
|
[iOS Xcode Cloud](ios-xcode-cloud.md) and [Mobile Store Delivery](store-delivery.md).
|
|
|
|
## EAS
|
|
|
|
The project is linked to Expo/EAS for optional future use, but routine CI builds should use GitHub Actions local Android builds to avoid consuming EAS monthly build quota.
|