Skip to content

Mobile App Release & CI/CD

This guide covers the complete CI/CD pipeline for the PersiaNation mobile application, including automated builds, testing, and deployment processes using Expo Application Services (EAS) and GitHub Actions.

The PersiaNation mobile app uses a sophisticated CI/CD pipeline that includes:

  • Automated Testing: Type checking, linting, and E2E tests
  • Multi-Environment Builds: Development, staging, and production builds
  • Over-The-Air (OTA) Updates: JavaScript and asset updates without app store submissions
  • Automated Releases: GitHub releases with automatic version management
  • Store Deployment: Automated submission to iOS App Store and Google Play Store

The app supports multiple build environments configured in eas.json:

  • Purpose: Local development and testing
  • Distribution: Internal
  • Features: Development client enabled, simulator support
  • Channel: development
  • Purpose: Pre-production testing and QA
  • Distribution: Internal
  • Features: Internal distribution for testing
  • Channel: staging
  • Store Submission: Draft releases to internal testing tracks
  • Purpose: Production app store releases
  • Distribution: Store
  • Features: Optimized builds for app stores
  • Channel: production
  • Store Submission: Full app store releases

1. Automated Testing (test.yml, lint-ts.yml, type-check.yml)

Section titled “1. Automated Testing (test.yml, lint-ts.yml, type-check.yml)”

Runs on every push and pull request:

# Triggered on: push, pull_request
- Type checking with TypeScript
- ESLint code quality checks
- Unit and integration tests
- E2E testing on Android

Triggers on hotfix branches:

# Triggered on: push/PR to hotfix branch
- Creates EAS Update for quick testing
- Posts preview link in PR comments
- Uses staging channel for testing

3. GitHub Release (new-github-release.yml)

Section titled “3. GitHub Release (new-github-release.yml)”

Automatically creates GitHub releases:

# Triggered on: git tag push
- Creates draft GitHub release
- Generates release notes automatically
- Links to build artifacts

The eas.json configuration defines three main build profiles:

{
"build": {
"production": {
"channel": "production",
"distribution": "store",
"android": { "buildType": "app-bundle" },
"env": { "APP_ENV": "production" }
},
"staging": {
"channel": "staging",
"distribution": "internal",
"env": { "APP_ENV": "staging" }
},
"development": {
"channel": "development",
"developmentClient": true,
"distribution": "internal",
"env": { "APP_ENV": "development" }
}
}
}
Terminal window
# Build for different environments
eas build --platform all --profile production
eas build --platform all --profile staging
eas build --platform all --profile development
# Platform-specific builds
eas build --platform ios --profile production
eas build --platform android --profile staging

Builds are automatically triggered by:

  • Git tags: Production builds for releases
  • Push to staging: Staging builds for testing
  • Pull requests: Development builds for review

OTA updates allow pushing JavaScript and asset changes without app store approval:

Terminal window
# Deploy OTA update to staging
eas update --branch staging-branch --message "Fix login issue"
# Deploy OTA update to production
eas update --branch production-branch --message "Add new feature"
# Auto-deploy (used in CI/CD)
eas update --auto
  • production: Live app users receive these updates
  • staging: Internal testing and QA
  • development: Developer testing and debugging
  1. Code Changes: Make JavaScript/asset changes
  2. Testing: Test locally and in development
  3. Staging Deploy: eas update --branch staging-branch
  4. QA Approval: Test on staging channel
  5. Production Deploy: eas update --branch production-branch

Version numbers are managed in:

  • app.config.ts: App version and build number
  • package.json: Package version
  • Environment variables: Runtime version
app.config.ts
export default {
version: Env.VERSION, // e.g., "1.2.3"
ios: {
buildNumber: Env.BUILD_NUMBER, // e.g., "123"
},
android: {
versionCode: parseInt(Env.BUILD_NUMBER), // e.g., 123
},
};
  1. Create Release Branch:

    Terminal window
    git checkout -b release/v1.2.3
  2. Update Version Numbers:

    Terminal window
    # Update package.json, app.config.ts, etc.
    npm version 1.2.3
  3. Push and Tag:

    Terminal window
    git push origin release/v1.2.3
    git tag v1.2.3
    git push origin v1.2.3
  4. Automated Process:

    • GitHub Actions detects tag
    • Builds production app
    • Creates GitHub release
    • Submits to app stores (if configured)
  1. Build Production App:

    Terminal window
    eas build --platform all --profile production
  2. Submit to Stores:

    Terminal window
    eas submit --platform all --profile production
  3. Create GitHub Release:

    Terminal window
    gh release create v1.2.3 --title "Release v1.2.3" --notes "Release notes"
Terminal window
# Automatic submission
eas submit --platform ios --profile production
# Manual submission via App Store Connect
# - Upload build via Xcode or Transporter
# - Configure app metadata
# - Submit for review
Terminal window
# Automatic submission to internal track
eas submit --platform android --profile staging
# Production release
eas submit --platform android --profile production
Terminal window
EXPO_TOKEN # Expo account token for EAS operations
GOOGLE_SERVICES_JSON # Android Google Services configuration
APPLE_TEAM_ID # iOS development team ID
Terminal window
# Development
APP_ENV=development
BASE_API_URL=https://dev-api.example.com
# Staging
APP_ENV=staging
BASE_API_URL=https://staging-api.example.com
# Production
APP_ENV=production
BASE_API_URL=https://api.example.com
  • EAS Dashboard: Monitor build status and logs
  • GitHub Actions: View workflow execution and failures
  • Expo Updates: Track OTA update adoption
  • App Store Connect: iOS download and crash analytics
  • Google Play Console: Android metrics and performance
  • Expo Analytics: User engagement and update metrics
Terminal window
# Clear cache and retry
eas build --clear-cache --platform all --profile production
# Check build logs in EAS dashboard
eas build:list --status=errored
Terminal window
# Verify channel configuration
eas channel:list
# Check update deployment
eas update:list --branch production-branch
# Rollback problematic update
eas update:rollback --branch production-branch --group-id <group-id>
Terminal window
# Check submission status
eas submit:list
# Retry failed submission
eas submit --platform ios --profile production --latest
Terminal window
# View build details
eas build:view <build-id>
# Check project configuration
eas config
# Validate eas.json
eas build:configure
# View update history
eas update:list --branch <branch-name>
  • Use semantic versioning (1.2.3)
  • Increment build numbers for each build
  • Tag releases in git for traceability
  • Run full test suite before releases
  • Use staging environment for QA
  • Test OTA updates on staging first
  • Schedule releases during low-traffic periods
  • Prepare rollback plans for major releases
  • Monitor crash reports after releases
  • Rotate Expo tokens regularly
  • Use separate credentials for different environments
  • Never commit sensitive data to git