mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-28 21:35:42 +00:00
Fix TestFlight upload for Xcode 14+ (#5927)
Replace deprecated altool (removed in Xcode 14) with xcodebuild -exportArchive using App Store Connect API authentication. Changes: - upload_testflight.sh: Use xcodebuild with destination=upload and API key authentication instead of altool - ios_testflight.yml: Pass xcarchive path and use new API key secrets Required new GitHub secrets: - APP_STORE_CONNECT_API_KEY_ID - APP_STORE_CONNECT_API_ISSUER_ID - APP_STORE_CONNECT_API_KEY (contents of .p8 file) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -184,11 +184,23 @@ jobs:
|
||||
- name: Upload to TestFlight
|
||||
if: ${{ github.event.inputs.skip_upload != 'true' }}
|
||||
env:
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APP_SPECIFIC_PASSWORD: ${{ secrets.APP_SPECIFIC_PASSWORD }}
|
||||
# App Store Connect API Key (replaces deprecated altool with Apple ID)
|
||||
# Create at: https://appstoreconnect.apple.com/access/api
|
||||
APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
|
||||
APP_STORE_CONNECT_API_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_ISSUER_ID }}
|
||||
APP_STORE_CONNECT_API_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
run: |
|
||||
# Write API key to file (xcodebuild needs a file path)
|
||||
API_KEY_PATH=$(mktemp)
|
||||
echo "$APP_STORE_CONNECT_API_KEY" > "$API_KEY_PATH"
|
||||
export APP_STORE_CONNECT_API_KEY_PATH="$API_KEY_PATH"
|
||||
|
||||
chmod +x ./ci/github_actions/upload_testflight.sh
|
||||
./ci/github_actions/upload_testflight.sh "$EAGLE0_BUILD_DIR/archive/eagle0.ipa"
|
||||
./ci/github_actions/upload_testflight.sh "$EAGLE0_BUILD_DIR/archive/eagle0.xcarchive" "$APPLE_TEAM_ID" "$PROFILE_UUID"
|
||||
|
||||
# Cleanup
|
||||
rm -f "$API_KEY_PATH"
|
||||
|
||||
- name: Upload IPA artifact
|
||||
# Only keep artifact if we skipped TestFlight upload (for debugging)
|
||||
|
||||
@@ -1,48 +1,102 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Upload IPA to TestFlight using Apple ID credentials (same as Mac notarization)
|
||||
# Upload xcarchive to TestFlight using App Store Connect API Key
|
||||
# This replaces the deprecated altool which was removed in Xcode 14+
|
||||
#
|
||||
# Uses xcodebuild -exportArchive with destination=upload, which is Apple's
|
||||
# recommended approach for CI/CD pipelines.
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
IPA_PATH=${1:?Usage: upload_testflight.sh <ipa_path>}
|
||||
# Ensure xcodebuild uses Xcode.app, not Command Line Tools
|
||||
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
|
||||
|
||||
if [ ! -f "$IPA_PATH" ]; then
|
||||
echo "Error: IPA file not found: $IPA_PATH"
|
||||
ARCHIVE_PATH=${1:?Usage: upload_testflight.sh <xcarchive_path> <team_id> <profile_uuid>}
|
||||
TEAM_ID=${2:?Missing team ID}
|
||||
PROFILE_UUID=${3:?Missing provisioning profile UUID}
|
||||
|
||||
if [ ! -d "$ARCHIVE_PATH" ]; then
|
||||
echo "Error: xcarchive not found: $ARCHIVE_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Uploading to TestFlight: $IPA_PATH"
|
||||
echo "Uploading to TestFlight: $ARCHIVE_PATH"
|
||||
|
||||
# Uses same credentials as Mac notarization:
|
||||
# - APPLE_ID: Your Apple ID email
|
||||
# - APP_SPECIFIC_PASSWORD: App-specific password from appleid.apple.com
|
||||
# Requires App Store Connect API Key:
|
||||
# - APP_STORE_CONNECT_API_KEY_ID: Key ID from App Store Connect
|
||||
# - APP_STORE_CONNECT_API_ISSUER_ID: Issuer ID from App Store Connect
|
||||
# - APP_STORE_CONNECT_API_KEY_PATH: Path to .p8 private key file
|
||||
#
|
||||
# To create an API key:
|
||||
# 1. Go to https://appstoreconnect.apple.com/access/api
|
||||
# 2. Click the + button to create a new key
|
||||
# 3. Give it a name and Admin or App Manager access
|
||||
# 4. Download the .p8 file (you can only download it once!)
|
||||
# 5. Note the Key ID and Issuer ID shown on the page
|
||||
|
||||
if [ -z "${APPLE_ID:-}" ]; then
|
||||
echo "Error: APPLE_ID environment variable not set"
|
||||
if [ -z "${APP_STORE_CONNECT_API_KEY_ID:-}" ]; then
|
||||
echo "Error: APP_STORE_CONNECT_API_KEY_ID environment variable not set"
|
||||
echo "Create an API key at https://appstoreconnect.apple.com/access/api"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${APP_SPECIFIC_PASSWORD:-}" ]; then
|
||||
echo "Error: APP_SPECIFIC_PASSWORD environment variable not set"
|
||||
if [ -z "${APP_STORE_CONNECT_API_ISSUER_ID:-}" ]; then
|
||||
echo "Error: APP_STORE_CONNECT_API_ISSUER_ID environment variable not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Uploading with xcrun altool..."
|
||||
|
||||
# Capture output to check for errors (altool may return 0 even on failure)
|
||||
OUTPUT=$(xcrun altool --upload-app \
|
||||
--type ios \
|
||||
--file "$IPA_PATH" \
|
||||
--username "$APPLE_ID" \
|
||||
--password "$APP_SPECIFIC_PASSWORD" 2>&1) || true
|
||||
|
||||
echo "$OUTPUT"
|
||||
|
||||
# Check for error indicators in output
|
||||
if echo "$OUTPUT" | grep -q "ERROR:"; then
|
||||
echo "ERROR: Upload failed. See error messages above."
|
||||
if [ -z "${APP_STORE_CONNECT_API_KEY_PATH:-}" ]; then
|
||||
echo "Error: APP_STORE_CONNECT_API_KEY_PATH environment variable not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$APP_STORE_CONNECT_API_KEY_PATH" ]; then
|
||||
echo "Error: API key file not found: $APP_STORE_CONNECT_API_KEY_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create export options plist with upload destination
|
||||
EXPORT_OPTIONS_PLIST=$(mktemp)
|
||||
trap "rm -f $EXPORT_OPTIONS_PLIST" EXIT
|
||||
|
||||
cat > "$EXPORT_OPTIONS_PLIST" << EOF
|
||||
<?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>destination</key>
|
||||
<string>upload</string>
|
||||
<key>method</key>
|
||||
<string>app-store-connect</string>
|
||||
<key>teamID</key>
|
||||
<string>$TEAM_ID</string>
|
||||
<key>uploadSymbols</key>
|
||||
<true/>
|
||||
<key>signingStyle</key>
|
||||
<string>manual</string>
|
||||
<key>signingCertificate</key>
|
||||
<string>Apple Distribution: Daniel Crosby (UWJ88DX8WQ)</string>
|
||||
<key>provisioningProfiles</key>
|
||||
<dict>
|
||||
<key>net.eagle0.eagle</key>
|
||||
<string>$PROFILE_UUID</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
|
||||
echo "Export options:"
|
||||
cat "$EXPORT_OPTIONS_PLIST"
|
||||
|
||||
echo "Uploading to App Store Connect..."
|
||||
|
||||
# Use xcodebuild to upload with App Store Connect API authentication
|
||||
xcodebuild -exportArchive \
|
||||
-archivePath "$ARCHIVE_PATH" \
|
||||
-exportOptionsPlist "$EXPORT_OPTIONS_PLIST" \
|
||||
-authenticationKeyPath "$APP_STORE_CONNECT_API_KEY_PATH" \
|
||||
-authenticationKeyID "$APP_STORE_CONNECT_API_KEY_ID" \
|
||||
-authenticationKeyIssuerID "$APP_STORE_CONNECT_API_ISSUER_ID"
|
||||
|
||||
echo "Upload complete! Check App Store Connect for processing status."
|
||||
echo "The build should appear in TestFlight within 15-30 minutes after processing."
|
||||
|
||||
Reference in New Issue
Block a user