ci: finish release.yml's TestFlight upload, rule out Xcode Cloud for this repo (KC-71)
Spent considerable effort trying to connect Xcode Cloud directly to this repo's self-hosted Gitea - confirmed not achievable. GitHub Enterprise's provider option hits Gitea's missing /api/v3/ path; GitLab Self-Managed rejects Gitea's UUID-format OAuth2 Client IDs against App Store Connect's 64-char-hex requirement (verified by actually creating a real OAuth2 app and having it rejected). Also stood up Tailscale Funnel on the Gitea host for real public HTTPS access regardless (was LAN-only before), and switched origin to it. Replaced release.yml's commented-out altool placeholder (defunct - Apple retired that upload path in 2023) with the current supported approach: xcodebuild -exportArchive with API-key auth flags handles export and TestFlight upload in a single step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -36,51 +36,31 @@ jobs:
|
||||
-archivePath "$RUNNER_TEMP/KisaniCal.xcarchive" \
|
||||
-allowProvisioningUpdates
|
||||
|
||||
- name: Export IPA
|
||||
# Write the App Store Connect API key to disk. xcodebuild's auto-discovery
|
||||
# looks for exactly this filename pattern under ~/private_keys.
|
||||
- name: Write App Store Connect API key
|
||||
run: |
|
||||
mkdir -p ~/private_keys
|
||||
echo "${{ secrets.APP_STORE_CONNECT_API_KEY_P8 }}" > ~/private_keys/AuthKey_${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}.p8
|
||||
|
||||
# Export AND upload in one step: passing the API key credentials to
|
||||
# -exportArchive makes xcodebuild upload directly to App Store Connect
|
||||
# (method "app-store" in ExportOptions.plist) — no separate altool/
|
||||
# Transporter step needed. (altool's own upload path was retired by
|
||||
# Apple in 2023; this is the current supported mechanism.)
|
||||
- name: Export IPA and upload to TestFlight
|
||||
run: |
|
||||
set -o pipefail
|
||||
xcodebuild -exportArchive \
|
||||
-archivePath "$RUNNER_TEMP/KisaniCal.xcarchive" \
|
||||
-exportOptionsPlist ExportOptions.plist \
|
||||
-exportPath "$RUNNER_TEMP/export" \
|
||||
-allowProvisioningUpdates
|
||||
-allowProvisioningUpdates \
|
||||
-authenticationKeyPath ~/private_keys/AuthKey_${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}.p8 \
|
||||
-authenticationKeyID ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} \
|
||||
-authenticationKeyIssuerID ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
|
||||
ls -la "$RUNNER_TEMP/export"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# PLACEHOLDER: Upload to TestFlight / App Store Connect.
|
||||
#
|
||||
# Add these as Gitea repo secrets: Settings → Actions → Secrets
|
||||
# APP_STORE_CONNECT_API_KEY_ID (the "Key ID" from App Store Connect)
|
||||
# APP_STORE_CONNECT_ISSUER_ID (the "Issuer ID")
|
||||
# APP_STORE_CONNECT_API_KEY_P8 (contents of the AuthKey_XXXX.p8 file)
|
||||
#
|
||||
# Then uncomment ONE of the approaches below.
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# --- Option A: modern notarytool / App Store Connect API key (recommended) ---
|
||||
# - name: Write API key to file
|
||||
# run: |
|
||||
# mkdir -p ~/private_keys
|
||||
# echo "${{ secrets.APP_STORE_CONNECT_API_KEY_P8 }}" > ~/private_keys/AuthKey_${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}.p8
|
||||
#
|
||||
# - name: Upload to TestFlight (altool with API key)
|
||||
# run: |
|
||||
# xcrun altool --upload-app \
|
||||
# --type ios \
|
||||
# --file "$RUNNER_TEMP/export/KisaniCal.ipa" \
|
||||
# --apiKey "${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}" \
|
||||
# --apiIssuer "${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}"
|
||||
|
||||
# --- Option B: notarytool (for notarizing a macOS build, not iOS TestFlight) ---
|
||||
# - name: Notarize
|
||||
# run: |
|
||||
# xcrun notarytool submit "$RUNNER_TEMP/export/KisaniCal.ipa" \
|
||||
# --key ~/private_keys/AuthKey_${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}.p8 \
|
||||
# --key-id "${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}" \
|
||||
# --issuer "${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}" \
|
||||
# --wait
|
||||
|
||||
- name: Notice
|
||||
run: |
|
||||
echo "IPA exported. TestFlight upload step is a commented-out placeholder."
|
||||
echo "Add App Store Connect API-key secrets and uncomment Option A in release.yml."
|
||||
- name: Clean up API key
|
||||
if: always()
|
||||
run: rm -rf ~/private_keys
|
||||
|
||||
@@ -2586,3 +2586,60 @@ against the real logic (not copies, not just read):
|
||||
The SwiftUI layer itself (the Stepper row, bindings, sheet wiring) is
|
||||
self-reviewed only — balanced braces/parens confirmed per-file, one
|
||||
pre-existing stray `(` in `TaskItem.swift` predates this (see KC-62).
|
||||
|
||||
## KC-71 — Finish release.yml's TestFlight upload (Xcode Cloud ruled out for this repo)
|
||||
|
||||
Status: Implemented — `release.yml` updated; live end-to-end run still
|
||||
pending the user adding the App Store Connect API key as Gitea secrets
|
||||
Reported by: User — wanted automated TestFlight delivery on merge to main
|
||||
Area: CI/CD (`.gitea/workflows/release.yml`)
|
||||
|
||||
### Description
|
||||
Spent a long session trying to connect Apple's Xcode Cloud directly to this
|
||||
repo's self-hosted Gitea instance. Concluded it's not achievable:
|
||||
- Gitea was only reachable on the LAN (`10.10.1.21:3002`, plain HTTP) —
|
||||
fixed by standing up Tailscale Funnel on the host (`titantwo`), giving
|
||||
real public HTTPS at `https://titantwo.tail05af18.ts.net`. Also switched
|
||||
the local `origin` remote to this URL (user's explicit call — the old
|
||||
LAN address is no longer used anywhere).
|
||||
- Xcode Cloud's "GitHub Enterprise" provider option 404s against Gitea —
|
||||
GitHub Enterprise's API lives at a fixed `/api/v3/` path, Gitea's is
|
||||
`/api/v1/`.
|
||||
- Its "GitLab Self-Managed" option rejects Gitea's OAuth2 Client IDs — App
|
||||
Store Connect strictly requires a 64-character hex string (real GitLab's
|
||||
ID format); Gitea's OAuth2 provider generates 36-character UUIDs. Not
|
||||
fixable from the Gitea side — confirmed by actually creating a real
|
||||
Gitea OAuth2 application and having App Store Connect reject its ID.
|
||||
- Bitbucket Server wasn't tried — the same class of hard-coded-provider-
|
||||
format problem was already proven twice, not worth a third confirmation.
|
||||
|
||||
Conclusion: Apple only supports Gitea if it happens to be API/URL-
|
||||
compatible with GitHub/GitLab/Bitbucket's *specific* hosted or enterprise
|
||||
products, and it isn't. Pivoted to finishing the automation this repo
|
||||
already had a placeholder for instead.
|
||||
|
||||
### Change
|
||||
`release.yml`'s TestFlight upload step was a commented-out placeholder
|
||||
(altool-based) since it was originally set up. Replaced it with the
|
||||
currently-supported mechanism — `xcrun altool`'s own upload path was
|
||||
retired by Apple in 2023, so the placeholder would not have worked even if
|
||||
uncommented as-is. Now: write the App Store Connect API key (from a new
|
||||
Gitea secret) to `~/private_keys/AuthKey_<KEY_ID>.p8`, then pass
|
||||
`-authenticationKeyPath`/`-authenticationKeyID`/`-authenticationKeyIssuerID`
|
||||
directly to the existing `xcodebuild -exportArchive` call — this exports
|
||||
AND uploads to TestFlight in one step, no separate upload tool needed.
|
||||
Key file is deleted in an `if: always()` cleanup step regardless of
|
||||
success/failure.
|
||||
|
||||
Needs 3 new Gitea secrets (Settings → Actions → Secrets), from an App
|
||||
Store Connect API key with App Manager role:
|
||||
`APP_STORE_CONNECT_API_KEY_ID`, `APP_STORE_CONNECT_ISSUER_ID`,
|
||||
`APP_STORE_CONNECT_API_KEY_P8`.
|
||||
|
||||
Files: `.gitea/workflows/release.yml`.
|
||||
|
||||
### Note
|
||||
Not run end-to-end yet — needs the user to generate the App Store Connect
|
||||
API key and add the 3 secrets before the next merge to `main` actually
|
||||
exercises this path. `ExportOptions.plist` needed no changes (already
|
||||
`method: app-store` with the correct team ID).
|
||||
|
||||
Reference in New Issue
Block a user