5.5 KiB
Mobile Deployment Guide
This guide covers the automated mobile deployment pipeline for iOS and Android apps.
🚀 Quick Start
Automatic Deployments
Deployments happen automatically when PRs are merged:
- Merge to
dev→ Deploy to internal testing - Merge to
main→ Deploy to production
To skip deployment, add [skip-deploy] to your PR title or add the no-deploy label.
Manual Deployments
- Go to Actions → "Mobile App Deployments"
- Click "Run workflow"
- Select options:
- Platform: ios / android / both
- Test mode: Check to build without uploading
- Deployment track: internal / production
- Version bump: build / patch / minor / major
📋 How It Works
Branch Strategy
main (production)
↑
└── dev (internal testing)
↑
└── feature/* (no auto-deploy)
Version Management
Versions are controlled by PR labels:
version:major- Bump major version (1.0.0 → 2.0.0)version:minor- Bump minor version (1.0.0 → 1.1.0)version:patch- Bump patch version (1.0.0 → 1.0.1) [default for main]- No label on dev - Only increment build number
Deployment Tracks
| Branch | Track | iOS Target | Android Target |
|---|---|---|---|
| dev | internal | TestFlight Internal | Play Store Internal |
| main | production | App Store | Play Store Production |
🏗️ Architecture
Workflows
-
mobile-deploy.yml- Main deployment workflow- Handles both manual and automated deployments
- Builds and uploads to app stores
- Creates git tags for production releases
-
mobile-deploy-auto.yml- PR merge trigger- Detects merged PRs
- Determines deployment parameters
- Calls main deployment workflow
Version Storage
app/version.json- Tracks build numbersapp/package.json- Semantic version- Native files auto-sync during build
Caching Strategy
Build times are optimized with caching:
- Yarn dependencies
- Ruby gems
- CocoaPods (iOS)
- Gradle (Android)
- Android NDK
Average build times with cache: iOS ~15min, Android ~10min
🔧 Configuration
Required Secrets
iOS
IOS_APP_IDENTIFIER- Bundle IDIOS_TEAM_ID- Apple Team IDIOS_CONNECT_KEY_ID- App Store Connect API Key IDIOS_CONNECT_ISSUER_ID- API Key Issuer IDIOS_CONNECT_API_KEY_BASE64- API Key (base64)IOS_DIST_CERT_BASE64- Distribution certificateIOS_PROV_PROFILE_BASE64- Provisioning profileIOS_P12_PASSWORD- Certificate password
Android
ANDROID_PACKAGE_NAME- Package nameANDROID_KEYSTORE- Keystore file (base64)ANDROID_KEYSTORE_PASSWORD- Keystore passwordANDROID_KEY_ALIAS- Key aliasANDROID_KEY_PASSWORD- Key passwordANDROID_PLAY_STORE_JSON_KEY- Service account key
Notifications
SLACK_API_TOKEN- For deployment notificationsSLACK_CHANNEL_ID- Channel for build uploads
Environment Variables
Set in workflow files:
NODE_VERSION: 18
RUBY_VERSION: 3.2
JAVA_VERSION: 17
ANDROID_API_LEVEL: 35
ANDROID_NDK_VERSION: 27.0.12077973
🏷️ Git Tags & Releases
Automatic Tags (Production Only)
When deploying to production, creates:
v2.5.5- Main version tagv2.5.5-ios-148- iOS with build numberv2.5.5-android-82- Android with build number
GitHub Releases
Automatically created for production deployments with:
- Changelog from commits
- Build information
- Links to app stores
🚨 Troubleshooting
Common Issues
"Play Store upload failed: Insufficient permissions"
The service account needs permissions in Google Play Console. The build file is saved locally and can be uploaded manually.
Cache not working
- Check if lock files changed (
yarn.lock,Gemfile.lock) - Cache keys include version numbers that can be bumped
- First build on new branch may be slower
iOS build fails with provisioning profile error
- Ensure secrets are up to date
- Check certificate expiration
- Verify bundle ID matches
Version conflicts
version.jsontracks the source of truth- Always higher than store versions
- Automatically incremented each build
Build Failures
- Check the workflow logs in GitHub Actions
- Look for the specific error in the failed step
- Most issues are related to:
- Expired certificates/profiles
- Missing secrets
- Network timeouts (retry usually helps)
📊 Monitoring
Slack Notifications
Successful deployments post to Slack with:
- Platform and version info
- Download links for the builds
- Deployment track (internal/production)
Deployment History
View all deployments:
- Go to Actions
- Filter by workflow: "Mobile App Deployments"
- Check run history and logs
🔐 Security
- All secrets are stored in GitHub Secrets
- Certificates are base64 encoded
- Build artifacts are uploaded to Slack (private channel)
- Production deployments only from protected branches
🛠️ Maintenance
Updating Workflows
- Test changes with
test_mode: true - Use
workflow_dispatchfor manual testing - Monitor first automated run carefully
Cache Busting
If builds are failing due to cache issues:
- Increment cache version in workflow:
GH_CACHE_VERSION: v2 # Increment this
Certificate Renewal
Before certificates expire:
- Generate new certificates/profiles
- Update GitHub Secrets
- Test with manual deployment first
For local development and manual release processes, see app/README.md