ci: add App Store submission pipeline via GitHub Actions
Some checks failed
CI / TypeScript (pull_request) Failing after 4s
CI / ESLint (pull_request) Failing after 4s
CI / Tests (pull_request) Failing after 12s
CI / Build Check (pull_request) Has been skipped
CI / Admin Web Tests (pull_request) Successful in 2m7s
CI / Deploy Edge Functions (pull_request) Has been skipped
Some checks failed
CI / TypeScript (pull_request) Failing after 4s
CI / ESLint (pull_request) Failing after 4s
CI / Tests (pull_request) Failing after 12s
CI / Build Check (pull_request) Has been skipped
CI / Admin Web Tests (pull_request) Successful in 2m7s
CI / Deploy Edge Functions (pull_request) Has been skipped
This commit is contained in:
82
.github/workflows/app-store.yml
vendored
Normal file
82
.github/workflows/app-store.yml
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
name: App Store Submission
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
upload-to-app-store:
|
||||
name: Archive & Upload to App Store
|
||||
runs-on: macos-15
|
||||
timeout-minutes: 60
|
||||
defaults:
|
||||
run:
|
||||
working-directory: tabatago-swift
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Select Xcode
|
||||
run: sudo xcode-select -switch /Applications/Xcode.app
|
||||
|
||||
- name: Cache SPM dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/Library/Developer/Xcode/DerivedData/**/SourcePackages
|
||||
key: spm-macos-${{ hashFiles('tabatago-swift/project.yml') }}
|
||||
restore-keys: |
|
||||
spm-macos-
|
||||
|
||||
- name: Write App Store Connect API key
|
||||
env:
|
||||
API_KEY_P8: ${{ secrets.APP_STORE_CONNECT_API_KEY_P8 }}
|
||||
run: |
|
||||
printf '%s' "$API_KEY_P8" > "$RUNNER_TEMP/AuthKey.p8"
|
||||
|
||||
- name: Archive
|
||||
run: |
|
||||
xcodebuild archive \
|
||||
-project TabataGo.xcodeproj \
|
||||
-scheme TabataGo \
|
||||
-configuration Release \
|
||||
-archivePath ./build/TabataGo.xcarchive \
|
||||
-allowProvisioningUpdates \
|
||||
-authenticationKeyPath "$RUNNER_TEMP/AuthKey.p8" \
|
||||
-authenticationKeyID "${{ secrets.APP_STORE_CONNECT_KEY_ID }}" \
|
||||
-authenticationKeyIssuerID "${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}" \
|
||||
|| { echo "❌ Archive failed — check signing and API key permissions"; exit 1; }
|
||||
|
||||
- name: Verify build settings
|
||||
run: |
|
||||
echo "Checking version and build number..."
|
||||
xcodebuild -showBuildSettings \
|
||||
-project TabataGo.xcodeproj \
|
||||
-scheme TabataGo \
|
||||
-configuration Release \
|
||||
| grep -E "MARKETING_VERSION|CURRENT_PROJECT_VERSION"
|
||||
|
||||
- name: Export IPA
|
||||
run: |
|
||||
xcodebuild -exportArchive \
|
||||
-archivePath ./build/TabataGo.xcarchive \
|
||||
-exportPath ./build/export \
|
||||
-exportOptionsPlist ExportOptions.plist \
|
||||
-allowProvisioningUpdates \
|
||||
-authenticationKeyPath "$RUNNER_TEMP/AuthKey.p8" \
|
||||
-authenticationKeyID "${{ secrets.APP_STORE_CONNECT_KEY_ID }}" \
|
||||
-authenticationKeyIssuerID "${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}" \
|
||||
|| { echo "❌ Export failed — check ExportOptions.plist and provisioning"; exit 1; }
|
||||
|
||||
# NOTE: The first upload automatically creates the app record in
|
||||
# App Store Connect if one does not already exist.
|
||||
- name: Upload to App Store
|
||||
run: |
|
||||
xcrun altool --upload-app \
|
||||
--type ios \
|
||||
--file ./build/export/TabataGo.ipa \
|
||||
--apiKey "${{ secrets.APP_STORE_CONNECT_KEY_ID }}" \
|
||||
--apiIssuer "${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}" \
|
||||
|| { echo "❌ Upload failed — check API key permissions and app record"; exit 1; }
|
||||
71
docs/app-store-submission.md
Normal file
71
docs/app-store-submission.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# App Store Submission
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before triggering the CI pipeline, you need:
|
||||
|
||||
1. **Apple Developer Program membership** (paid, $99/year)
|
||||
2. **App Store Connect access** with Admin or App Manager role
|
||||
|
||||
## Step 1: Create App Store Connect API Key
|
||||
|
||||
1. Go to [App Store Connect → Users and Access → Integrations → App Store Connect API](https://appstoreconnect.apple.com/access/integrations/api)
|
||||
2. Click **Generate API Key** (or "+" button)
|
||||
3. Name it: `GitHub Actions CI`
|
||||
4. Set access to: **App Manager** (required for auto-signing + upload)
|
||||
5. Download the `.p8` file immediately (you cannot re-download it later)
|
||||
6. Note the **Key ID** and **Issuer ID** displayed on the page
|
||||
|
||||
## Step 2: Add GitHub Secrets
|
||||
|
||||
Go to your GitHub repo → **Settings → Secrets and variables → Actions → New repository secret**.
|
||||
|
||||
| Secret Name | Value |
|
||||
|---|---|
|
||||
| `APP_STORE_CONNECT_KEY_ID` | The Key ID from Step 1 (e.g., `ABC123XYZ`) |
|
||||
| `APP_STORE_CONNECT_ISSUER_ID` | The Issuer ID from Step 1 (UUID format) |
|
||||
| `APP_STORE_CONNECT_API_KEY_P8` | The **entire contents** of the `.p8` file, including `-----BEGIN PRIVATE KEY-----` and `-----END PRIVATE KEY-----` lines |
|
||||
|
||||
## Step 3: Trigger the Submission
|
||||
|
||||
Push a version tag to the repository:
|
||||
|
||||
```bash
|
||||
git tag v1.0.0
|
||||
git push origin v1.0.0
|
||||
```
|
||||
|
||||
Or run manually:
|
||||
- Go to **Actions** tab → **App Store Submission** → **Run workflow**
|
||||
|
||||
## What Happens
|
||||
|
||||
1. GitHub Actions runner (macOS) checks out your code
|
||||
2. Archives the app with Xcode auto-signing
|
||||
3. Exports an App Store IPA
|
||||
4. Uploads to App Store Connect
|
||||
5. The first upload **automatically creates** the app record in App Store Connect (bundle ID: `com.tabatago.app`)
|
||||
|
||||
## After Upload
|
||||
|
||||
1. Go to [App Store Connect → Apps](https://appstoreconnect.apple.com/apps)
|
||||
2. Select **TabataGo**
|
||||
3. Complete the **App Information** (description, screenshots, keywords, etc.)
|
||||
4. Complete the **Pricing and Availability** section
|
||||
5. Go to the new build under **TestFlight** or **App Store** tab
|
||||
6. Submit for review
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Likely Cause |
|
||||
|---|---|
|
||||
| "No accounts with iTunes Connect access" | API key doesn't have App Manager permissions — recreate the key with correct access |
|
||||
| "No profiles found" | The bundle ID `com.tabatago.app` isn't registered yet — check Apple Developer portal |
|
||||
| "Duplicate build number" | Build number already used — bump `CFBundleVersion` in `project.yml` and re-tag |
|
||||
| "Authentication failed" | API key was revoked, expired, or secret is misspelled — verify secrets in repository settings |
|
||||
|
||||
## Build Number Increments
|
||||
|
||||
Each submission requires a unique build number. Edit `tabatago-swift/project.yml`:
|
||||
- Change `CFBundleVersion: "2"` → `"3"` in all three targets (TabataGo, TabataGoWatch, TabataGoWatchWidget)
|
||||
- Then regenerate the project: `cd tabatago-swift && xcodegen`
|
||||
18
tabatago-swift/ExportOptions.plist
Normal file
18
tabatago-swift/ExportOptions.plist
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>method</key>
|
||||
<string>app-store</string>
|
||||
<key>teamID</key>
|
||||
<string>2MJF39L8VY</string>
|
||||
<key>signingStyle</key>
|
||||
<string>automatic</string>
|
||||
<key>uploadBitcode</key>
|
||||
<false/>
|
||||
<key>uploadSymbols</key>
|
||||
<true/>
|
||||
<key>manageAppVersionAndBuildNumber</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -46,7 +46,7 @@ targets:
|
||||
properties:
|
||||
CFBundleDisplayName: TabataGo
|
||||
CFBundleShortVersionString: "1.0"
|
||||
CFBundleVersion: "1"
|
||||
CFBundleVersion: "2"
|
||||
UILaunchScreen:
|
||||
UIColorName: ""
|
||||
UIImageName: ""
|
||||
@@ -110,7 +110,7 @@ targets:
|
||||
properties:
|
||||
CFBundleDisplayName: TabataGo
|
||||
CFBundleShortVersionString: "1.0"
|
||||
CFBundleVersion: "1"
|
||||
CFBundleVersion: "2"
|
||||
WKApplication: true
|
||||
WKCompanionAppBundleIdentifier: com.tabatago.app
|
||||
NSHealthShareUsageDescription: "TabataGo reads your heart rate and calories during workouts."
|
||||
@@ -147,7 +147,7 @@ targets:
|
||||
properties:
|
||||
CFBundleDisplayName: TabataGoWidget
|
||||
CFBundleShortVersionString: "1.0"
|
||||
CFBundleVersion: "1"
|
||||
CFBundleVersion: "2"
|
||||
NSExtension:
|
||||
NSExtensionPointIdentifier: com.apple.widgetkit-extension
|
||||
settings:
|
||||
|
||||
Reference in New Issue
Block a user