Files
beenvoice-app/docs/IOS_LOCAL_RELEASE.md
soconnor 355b14faef Add local iOS release pipeline, fix shortcuts, and improve invoice UX.
Enable App Store builds without EAS, iOS 18 App Intents plugins, and signing
fixes for distribution export. Add mobile invoice PDF preview, compact line
items, and more reliable shortcut deep-link handling.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 01:08:20 -04:00

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 beenvoice-app
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