Files
beenvoice-app/docs/IOS_LOCAL_RELEASE.md
T
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

89 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 Apples [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 |