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>
89 lines
3.8 KiB
Markdown
89 lines
3.8 KiB
Markdown
# 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](https://appstoreconnect.apple.com) 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](https://appstoreconnect.apple.com/access/integrations/api) (for upload only)
|
||
|
||
## One-time setup
|
||
|
||
```bash
|
||
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](https://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
|
||
|
||
```bash
|
||
# 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
|
||
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](./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 Apple’s [Transporter](https://apps.apple.com/app/transporter/id1450874784) 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 |
|