ci: finish release.yml's TestFlight upload, rule out Xcode Cloud for this repo (KC-71)
Some checks failed
CI / build-and-test (push) Failing after 39s
CI / build-and-test (pull_request) Failing after 30s

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:
kutesir
2026-07-13 00:03:19 +03:00
parent c992554f99
commit 266c3a6dda
2 changed files with 77 additions and 40 deletions

View File

@@ -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

View File

@@ -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).