Files
beenvoice/apps/mobile/docs/IOS_LOCAL_RELEASE.md

3.8 KiB
Raw Permalink Blame History

Local iOS release (no EAS)

Archive and upload beenvoice to App Store Connect using Xcode on your Mac — no Expo Application Services (EAS) subscription required.

Prerequisites

  • macOS with Xcode (same major version you use for development)
  • Apple Developer Program membership
  • App record in App Store Connect with bundle ID com.beenvoice.app
  • Distribution signing set up in Xcode (automatic signing + team is enough for most cases)
  • App Store Connect API key (for upload only)

One-time setup

cd apps/mobile
cp .ios-release.env.example .ios-release.env

Edit .ios-release.env:

Variable Where to find it
APPLE_TEAM_ID developer.apple.com/account → Membership → Team ID
APP_STORE_CONNECT_API_KEY_ID App Store Connect → Users and Access → Integrations → Keys
APP_STORE_CONNECT_API_ISSUER_ID Same page (Issuer ID at top)
APP_STORE_CONNECT_API_KEY_PATH Path to downloaded AuthKey_XXXXXX.p8
EXPO_PUBLIC_API_URL Production API URL baked into the release bundle

Optional: store the .p8 in ~/.appstoreconnect/private_keys/ (never commit it).

Open the iOS project once in Xcode and confirm Signing & Capabilities succeeds for targets beenvoice and ExpoWidgetsTarget.

Commands

# Archive + export signed IPA to dist/ios-release/export/
bun run ios:release

# Archive + export + upload to App Store Connect (TestFlight)
bun run ios:release:upload

Flags (pass through to the script)

bash scripts/ios-release.sh --archive-only          # .xcarchive only
bash scripts/ios-release.sh --export-only --upload  # re-upload existing archive
bash scripts/ios-release.sh --no-prebuild           # skip expo prebuild
bash scripts/ios-release.sh --no-bump               # don't increment build number

With IOS_BUMP_BUILD=1 in .ios-release.env, each run bumps CFBundleVersion via agvtool (recommended for repeated TestFlight uploads).

What the script does

  1. expo prebuild --platform ios (unless --no-prebuild)
  2. pod install
  3. Optional build-number bump (agvtool)
  4. xcodebuild archive (Release, generic iOS device)
  5. xcodebuild -exportArchive → App Store IPA
  6. xcrun altool --upload-app (with --upload only)

Artifacts land in dist/ios-release/ (gitignored).

After upload

  1. App Store Connect → TestFlight — wait for “Processing” to finish
  2. Smoke-test on device
  3. Submit for App Store review when ready

See also APP_STORE_CONNECT.md for metadata, screenshots, and review notes.

Notes

  • Dev client: expo-dev-client is in the native project today. Store builds still work, but the binary includes the dev client shell. For a slimmer production binary, remove that plugin and re-run prebuild before release (or maintain a separate app.config variant).
  • Manual upload: After bun run ios:release, drag the IPA into Apples Transporter app instead of using --upload.
  • CI: Run the same script on a Mac runner (GitHub macos-latest, etc.) with secrets injected as env vars instead of .ios-release.env.

Troubleshooting

Issue Fix
No signing certificate Xcode → Settings → Accounts → Download Manual Profiles; or open project and enable automatic signing
pod install fails cd ios && pod repo update && pod install
Upload auth error Verify API key has Developer access; check Key ID, Issuer ID, and .p8 path
Duplicate build number Enable IOS_BUMP_BUILD=1 or bump CURRENT_PROJECT_VERSION in Xcode
Widget extension signing Both beenvoice and ExpoWidgetsTarget need the same team