Building & Submitting to Stores β
This guide covers building the mobile app with EAS Build and submitting to the Google Play Store and Apple App Store using EAS Submit.
Prerequisites β
eas-cliinstalled globally:pnpm add -g eas-cli- Logged in:
eas login - Project linked:
eas init(already done, project ID inapp.json)
Build Profiles β
| Profile | Android | iOS | API URL |
|---|---|---|---|
staging | AAB, internal track | Store | Staging backend |
production | AAB, production track | Store | Production backend |
Both profiles produce AAB (Android App Bundle) files β APKs are not accepted by Google Play.
Version numbers are auto-incremented via appVersionSource: "remote" (managed by EAS).
Building β
Staging (internal testing) β
# Android
eas build --profile staging --platform android
# iOS
eas build --profile staging --platform ios
# Both platforms
eas build --profile staging --platform allProduction β
# Android
eas build --profile production --platform android
# iOS
eas build --profile production --platform ios
# Both platforms
eas build --profile production --platform allCI (non-interactive) β
eas build --profile staging --platform android --non-interactiveSubmitting β
Google Play Store β
Submissions use a Google Play Service Account key stored as an EAS secret (GOOGLE_SERVICE_ACCOUNT_KEY). This key is managed via Terraform (infra/play-store/ module) and stored in 1Password.
# Submit the latest staging build to internal testing track
eas submit --profile staging --platform android --latest
# Submit the latest production build to production track
eas submit --profile production --platform android --latest
# Submit a specific build
eas submit --profile staging --platform android --id <build-id>Apple App Store β
# Submit the latest staging build to App Store Connect
eas submit --profile staging --platform ios --latest
# Submit the latest production build
eas submit --profile production --platform ios --latestNOTE
iOS submissions require an active Apple Developer account and App Store Connect API key or Apple ID credentials. EAS CLI will prompt for these on first submission.
Build + Submit in one step β
# Build and auto-submit when build completes
eas build --profile staging --platform android --auto-submit
eas build --profile production --platform all --auto-submitEAS Secrets β
Secrets are stored at the project level in EAS. Manage them with:
eas secret:list # List all secrets
eas secret:create # Create (interactive)
eas secret:delete # Delete (interactive)Current secrets:
| Name | Type | Purpose |
|---|---|---|
GOOGLE_SERVICE_ACCOUNT_KEY | File | Google Play Store API authentication |
Google Play Service Account Setup β
The service account is provisioned via Terraform (infra/play-store/ module):
terraform applycreates the GCP service account and stores the JSON key in 1Password- Download the JSON key from 1Password (
[dev] Google Play Store - Service Account Key) - Save it to a temp file and create the EAS secret:bash
eas secret:create # select "file", name it GOOGLE_SERVICE_ACCOUNT_KEY, point to the JSON file - The service account must be invited in Google Play Console > Users and permissions with release permissions on the app
Play Store Tracks β
| Profile | Track | Description |
|---|---|---|
staging | internal | Up to 100 testers, available within minutes |
production | production | Public release (requires review on first submission) |
IMPORTANT
Internal testing track builds are installed via the Play Store, not downloaded as APKs. Testers must be added to the internal testing group in the Play Console and accept the invite link.
Troubleshooting β
"The apk has permissions that require a privacy policy" β
Set a privacy policy URL in Google Play Console > App content > Privacy policy before submitting.
"The service account is missing the necessary permissions" β
Ensure the service account has been invited in Play Console > Users and permissions with at minimum Releases permissions on the app.
"Uploaded a google-services.json instead of your service account key" β
The EAS secret contains the wrong file. Delete and recreate it with the correct service account JSON key (the one with "type": "service_account").