| name | building-with-eas |
| description | EAS Build and Submit configuration, credentials management, and troubleshooting. Use when configuring eas.json profiles, managing iOS/Android credentials, or debugging build failures. |
EAS Build & Submit Reference
Plugin Tools
Before production builds, verify your version hasn't already been released:
cd /path/to/expo-toolkit && npm run check-version -- /path/to/your/app
node tools/check-version.js /path/to/your/app
node tools/check-version.js /path/to/your/app --json
This checks:
- Current version in app.config.js
- Recent EAS builds and their submission status
- autoIncrement settings in eas.json
- Provides guidance if version bump is needed
Essential Commands
eas init
eas build:configure
eas credentials
eas credentials --platform ios
eas credentials --platform android
eas build --platform ios --profile development
eas build --platform android --profile preview
eas build --platform all --profile production
eas build --platform ios --profile production --auto-submit
eas build --platform android --profile production --auto-submit
eas build:list
eas.json Configuration
Standard Build Profiles
The eas.json file defines build profiles. A well-configured file looks like:
{
"cli": {
"version": ">= 16.18.0",
"appVersionSource": "remote"
},
"build": {
"base": {
"env": {
"APP_VARIANT": "production"
}
},
"development": {
"extends": "base",
"developmentClient": true,
"distribution": "internal",
"env": {
"APP_VARIANT": "development"
},
"ios": {
"simulator": false
},
"android": {
"buildType": "apk",
"gradleCommand": ":app:assembleDebug"
}
},
"development-simulator": {
"extends": "development",
"ios": {
"simulator": true
},
"android": {
"buildType": "apk"
}
},
"preview": {
"extends": "base",
"distribution": "internal",
"env": {
"APP_VARIANT": "preview"
},
"android": {
"buildType": "apk"
}
},
"production": {
"extends": "base",
"autoIncrement": true,
"env": {
"APP_VARIANT": "production"
}
}
},
"submit": {
"production": {
"ios": {
"appleId": "your@email.com",
"ascAppId": "1234567890"
},
"android": {
"serviceAccountKeyPath": "./play-store-credentials.json",
"track": "internal"
}
}
}
}
Profile Properties Reference
| Property | Description | Common Values |
|---|
developmentClient | Include expo-dev-client | true for dev builds |
distribution | How build is distributed | internal, store, simulator |
autoIncrement | Auto-increment version | true, "version", "buildNumber" |
env | Environment variables | Object of key-value pairs |
extends | Inherit from another profile | Profile name string |
iOS-Specific Properties
| Property | Description |
|---|
simulator | Build for simulator (no signing) |
enterpriseProvisioning | Use enterprise distribution |
resourceClass | Build machine size (default, large) |
Android-Specific Properties
| Property | Description |
|---|
buildType | Output format (apk or app-bundle) |
gradleCommand | Custom Gradle command |
withoutCredentials | Skip signing (simulator/dev) |
Credentials Management
iOS Credentials
EAS manages three primary iOS credentials:
- Distribution Certificate - Signs your app for distribution
- Provisioning Profile - Links app, certificate, and devices
- Push Notification Key - For APNs (Apple Push Notification service)
eas credentials --platform ios
Let EAS manage credentials (recommended):
- EAS automatically creates and manages credentials
- Certificates stored securely on Expo servers
- Automatic renewal before expiration
Use local credentials:
Create credentials.json at project root:
{
"ios": {
"provisioningProfilePath": "ios/certs/profile.mobileprovision",
"distributionCertificate": {
"path": "ios/certs/dist-cert.p12",
"password": "certificate-password"
}
}
}
Android Credentials
Android requires a keystore for signing:
eas credentials --platform android
Local keystore configuration:
{
"android": {
"keystore": {
"keystorePath": "android/keystores/release.keystore",
"keystorePassword": "keystore-password",
"keyAlias": "key-alias",
"keyPassword": "key-password"
}
}
}
Push Notification Setup
iOS (APNs):
eas credentials --platform ios
Android (FCM):
eas credentials --platform android
Build Submission (--auto-submit)
iOS Submission Behaviour
iOS builds can auto-submit to App Store Connect / TestFlight:
eas build --platform ios --profile production --auto-submit
What happens:
- Build completes on EAS servers
- Build automatically uploaded to App Store Connect
- Appears in TestFlight for testing
- Still requires manual submission to App Review
Requirements:
- Valid Apple Developer account
appleId and ascAppId in submit profile
- App created in App Store Connect
Android Submission Behaviour
IMPORTANT: First submission must be manual
For a brand new app on Google Play:
- Build the AAB:
eas build --platform android --profile production
- Download the AAB from EAS dashboard
- Manually upload to Google Play Console
- Complete store listing, content rating, etc.
- After first release,
--auto-submit works
eas build --platform android --profile production --auto-submit
Submit profile for Android:
{
"submit": {
"production": {
"android": {
"serviceAccountKeyPath": "./play-store-credentials.json",
"track": "internal"
}
}
}
}
Track options:
internal - Internal testing (up to 100 testers, instant)
alpha - Closed testing
beta - Open testing
production - Production release
Service Account Setup (Android)
- Go to Google Cloud Console
- Create service account with "Service Account User" role
- Go to Play Console → Setup → API access
- Link the service account
- Grant "Release manager" permissions
- Download JSON key file
- Reference in
eas.json
Development Build Setup
For Physical Devices
eas build --platform ios --profile development
eas build --platform android --profile development
iOS device registration:
- Devices must be registered in Apple Developer Portal
- EAS can register devices automatically during build
- Or register manually:
eas device:create
For Simulators/Emulators
eas build --platform ios --profile development-simulator
eas build --platform android --profile development
Environment Variables
Build-time Variables
Set in eas.json per profile:
{
"build": {
"production": {
"env": {
"APP_VARIANT": "production",
"API_URL": "https://api.example.com"
}
}
}
}
Sensitive Variables (Secrets)
Use EAS Secrets for sensitive data:
eas secret:create --name API_KEY --value "secret-value" --scope project
eas secret:list
Client-side Variables
Use EXPO_PUBLIC_ prefix for variables accessible in app code:
{
"env": {
"EXPO_PUBLIC_API_URL": "https://api.example.com"
}
}
Access in code:
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
Common Issues & Solutions
Build Fails: Missing Credentials
Symptom: Build fails with credential errors
Solution:
eas credentials --platform [ios|android]
Build Fails: CocoaPods Error (iOS)
Symptom: pod install fails during build
Solutions:
- Clear cache:
eas build --clear-cache
- Check
Podfile compatibility
- Verify native dependencies support current iOS version
Build Fails: Gradle Error (Android)
Symptom: Gradle build fails
Solutions:
- Check
build.gradle configuration
- Verify Java version compatibility
- Check for conflicting native dependencies
Submission Fails: App Not Found
Symptom: Submit fails with "app not found" error
iOS Solution:
- Verify
ascAppId matches App Store Connect
- Ensure app is created in App Store Connect first
Android Solution:
- Ensure app is created in Play Console first
- First build must be manually uploaded
- Service account has correct permissions
Version Mismatch
Symptom: Build rejected due to version already exists
Solution:
Use autoIncrement in production profile:
{
"production": {
"autoIncrement": true
}
}
Or increment manually:
eas build:version:set --platform [ios|android]
Best Practices
- Use profile inheritance - Define common settings in
base profile
- Separate environments - Use different bundle IDs for dev/preview/production
- Let EAS manage credentials - Simpler and more secure
- Use secrets for sensitive data - Never commit API keys to repo
- Enable autoIncrement - Prevents version conflicts in production
- Test with preview builds - Catch issues before production
- Use internal track for Android - Faster distribution than other tracks
CLI Quick Reference
eas build --platform [ios|android|all] --profile [profile]
eas build:list
eas build:view [build-id]
eas build:cancel [build-id]
eas credentials --platform [ios|android]
eas credentials:configure-build
eas submit --platform [ios|android] --profile [profile]
eas submit --platform ios --latest
eas submit --platform android --id [build-id]
eas secret:create --name NAME --value VALUE
eas secret:list
eas secret:delete NAME
eas device:create
eas device:list
eas update --branch [branch] --message "Update message"
eas update:list