Preserve BaseURL/Location, warm up MPD, clear sinf for VLC, and retry early stops so custom live DRM plays instead of Gestopt.
209 lines
7.2 KiB
Bash
209 lines
7.2 KiB
Bash
#!/bin/bash
|
|
# TestFlight upload via App Store Connect API key (headless, no GUI).
|
|
# Expects: ~/AuthKey.p8 (or AUTH_KEY_PATH)
|
|
# Requires: KEY_ID, ISSUER_ID (env or --key-id / --issuer-id)
|
|
# Optional: KEYCHAIN_PASS to unlock login keychain
|
|
set -euo pipefail
|
|
|
|
IOS_DIR="${IOS_DIR:-$HOME/Code/mediacluster/apps/ios}"
|
|
AUTH_KEY_PATH="${AUTH_KEY_PATH:-$HOME/AuthKey.p8}"
|
|
EXPORT_OPTIONS="${EXPORT_OPTIONS:-$IOS_DIR/ExportOptions.plist}"
|
|
ARCHIVE_PATH="${ARCHIVE_PATH:-$IOS_DIR/build/VMC.xcarchive}"
|
|
EXPORT_PATH="${EXPORT_PATH:-$IOS_DIR/build/export}"
|
|
SCHEME="${SCHEME:-VMC}"
|
|
CONFIGURATION="${CONFIGURATION:-Release}"
|
|
TEAM_ID="${TEAM_ID:-X25NYX3K49}"
|
|
BUNDLE_ID="${BUNDLE_ID:-nl.vonas.mediacluster.ios}"
|
|
SKIP_ARCHIVE=0
|
|
SKIP_EXPORT=0
|
|
IPA_PATH=""
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: upload-testflight.sh [options]
|
|
|
|
--key-id ID App Store Connect API Key ID (or env KEY_ID)
|
|
--issuer-id UUID App Store Connect Issuer ID (or env ISSUER_ID)
|
|
--auth-key PATH Path to .p8 (default: ~/AuthKey.p8)
|
|
--ipa PATH Skip archive/export; upload existing IPA
|
|
--skip-archive Reuse existing xcarchive
|
|
--skip-export Reuse existing IPA in export path
|
|
-h, --help Show help
|
|
|
|
Env:
|
|
KEY_ID, ISSUER_ID, AUTH_KEY_PATH, KEYCHAIN_PASS, IOS_DIR
|
|
EOF
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--key-id) KEY_ID="${2:-}"; shift 2 ;;
|
|
--issuer-id) ISSUER_ID="${2:-}"; shift 2 ;;
|
|
--auth-key) AUTH_KEY_PATH="${2:-}"; shift 2 ;;
|
|
--ipa) IPA_PATH="${2:-}"; SKIP_ARCHIVE=1; SKIP_EXPORT=1; shift 2 ;;
|
|
--skip-archive) SKIP_ARCHIVE=1; shift ;;
|
|
--skip-export) SKIP_EXPORT=1; shift ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*) echo "Unknown arg: $1" >&2; usage; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
KEY_ID="${KEY_ID:-}"
|
|
ISSUER_ID="${ISSUER_ID:-}"
|
|
|
|
# Derive Key ID from AuthKey_XXXXX.p8 filename if missing
|
|
if [[ -z "$KEY_ID" && -f "$AUTH_KEY_PATH" ]]; then
|
|
base="$(basename "$AUTH_KEY_PATH")"
|
|
if [[ "$base" =~ ^AuthKey_([A-Z0-9]+)\.p8$ ]]; then
|
|
KEY_ID="${BASH_REMATCH[1]}"
|
|
echo "KEY_ID derived from filename: $KEY_ID"
|
|
fi
|
|
fi
|
|
|
|
# Also accept ~/AuthKey_XXXXX.p8 if ~/AuthKey.p8 missing
|
|
if [[ ! -f "$AUTH_KEY_PATH" ]]; then
|
|
for cand in "$HOME"/AuthKey_*.p8; do
|
|
if [[ -f "$cand" ]]; then
|
|
AUTH_KEY_PATH="$cand"
|
|
base="$(basename "$cand")"
|
|
if [[ -z "$KEY_ID" && "$base" =~ ^AuthKey_([A-Z0-9]+)\.p8$ ]]; then
|
|
KEY_ID="${BASH_REMATCH[1]}"
|
|
fi
|
|
echo "Using API key file: $AUTH_KEY_PATH"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
die() { echo "ERROR: $*" >&2; exit 1; }
|
|
|
|
[[ -n "$KEY_ID" ]] || die "KEY_ID ontbreekt (env KEY_ID of --key-id, of AuthKey_XXXXX.p8)"
|
|
[[ -n "$ISSUER_ID" ]] || die "ISSUER_ID ontbreekt (env ISSUER_ID of --issuer-id)"
|
|
[[ -f "$AUTH_KEY_PATH" ]] || die "API key niet gevonden: $AUTH_KEY_PATH (scp AuthKey*.p8 naar ~ op de Mac)"
|
|
|
|
# Private keys for altool/transporter must live in a predictable API Keys folder
|
|
API_KEYS_DIR="$HOME/.appstoreconnect/private_keys"
|
|
mkdir -p "$API_KEYS_DIR"
|
|
API_KEY_DEST="$API_KEYS_DIR/AuthKey_${KEY_ID}.p8"
|
|
if [[ "$(cd "$(dirname "$AUTH_KEY_PATH")" && pwd)/$(basename "$AUTH_KEY_PATH")" != "$API_KEY_DEST" ]]; then
|
|
cp -f "$AUTH_KEY_PATH" "$API_KEY_DEST"
|
|
chmod 600 "$API_KEY_DEST"
|
|
fi
|
|
# Also keep canonical ~/AuthKey.p8 symlink/copy for convenience
|
|
if [[ ! -f "$HOME/AuthKey.p8" ]]; then
|
|
cp -f "$AUTH_KEY_PATH" "$HOME/AuthKey.p8"
|
|
chmod 600 "$HOME/AuthKey.p8"
|
|
fi
|
|
|
|
echo "=== VMC TestFlight upload ==="
|
|
echo "KEY_ID=$KEY_ID"
|
|
echo "ISSUER_ID=$ISSUER_ID"
|
|
echo "AUTH_KEY=$AUTH_KEY_PATH"
|
|
echo "BUNDLE_ID=$BUNDLE_ID"
|
|
echo "TEAM_ID=$TEAM_ID"
|
|
|
|
# Unlock keychain if password provided (headless codesign)
|
|
if [[ -n "${KEYCHAIN_PASS:-}" ]]; then
|
|
echo "Unlocking login keychain..."
|
|
security unlock-keychain -p "$KEYCHAIN_PASS" "$HOME/Library/Keychains/login.keychain-db" || \
|
|
security unlock-keychain -p "$KEYCHAIN_PASS" "$HOME/Library/Keychains/login.keychain" || true
|
|
security set-keychain-settings -t 3600 -u "$HOME/Library/Keychains/login.keychain-db" 2>/dev/null || true
|
|
fi
|
|
security list-keychains -s "$HOME/Library/Keychains/login.keychain-db" /Library/Keychains/System.keychain || true
|
|
|
|
cd "$IOS_DIR"
|
|
mkdir -p build "$EXPORT_PATH" store
|
|
|
|
# Ensure ExportOptions.plist for App Store
|
|
if [[ ! -f "$EXPORT_OPTIONS" ]]; then
|
|
cat > "$EXPORT_OPTIONS" <<PLIST
|
|
<?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>${TEAM_ID}</string>
|
|
<key>signingStyle</key>
|
|
<string>automatic</string>
|
|
<key>uploadSymbols</key>
|
|
<true/>
|
|
<key>destination</key>
|
|
<string>export</string>
|
|
<key>manageAppVersionAndBuildNumber</key>
|
|
<false/>
|
|
</dict>
|
|
</plist>
|
|
PLIST
|
|
echo "Created $EXPORT_OPTIONS"
|
|
fi
|
|
|
|
if [[ "$SKIP_ARCHIVE" -eq 0 ]]; then
|
|
echo "=== Archive (Release / generic iOS) ==="
|
|
rm -rf "$ARCHIVE_PATH"
|
|
xcodebuild \
|
|
-project VMC.xcodeproj \
|
|
-scheme "$SCHEME" \
|
|
-configuration "$CONFIGURATION" \
|
|
-destination 'generic/platform=iOS' \
|
|
-archivePath "$ARCHIVE_PATH" \
|
|
-allowProvisioningUpdates \
|
|
DEVELOPMENT_TEAM="$TEAM_ID" \
|
|
CODE_SIGN_STYLE=Automatic \
|
|
archive
|
|
echo "ARCHIVE_OK: $ARCHIVE_PATH"
|
|
fi
|
|
|
|
if [[ "$SKIP_EXPORT" -eq 0 ]]; then
|
|
[[ -d "$ARCHIVE_PATH" ]] || die "Archive ontbreekt: $ARCHIVE_PATH"
|
|
echo "=== Export IPA ==="
|
|
rm -rf "$EXPORT_PATH"
|
|
mkdir -p "$EXPORT_PATH"
|
|
xcodebuild -exportArchive \
|
|
-archivePath "$ARCHIVE_PATH" \
|
|
-exportPath "$EXPORT_PATH" \
|
|
-exportOptionsPlist "$EXPORT_OPTIONS" \
|
|
-allowProvisioningUpdates
|
|
IPA_PATH="$(find "$EXPORT_PATH" -name '*.ipa' -type f | head -1)"
|
|
[[ -n "$IPA_PATH" && -f "$IPA_PATH" ]] || die "Geen IPA na export in $EXPORT_PATH"
|
|
VER="$(/usr/libexec/PlistBuddy -c 'Print :ApplicationProperties:CFBundleShortVersionString' "$ARCHIVE_PATH/Info.plist" 2>/dev/null || echo '0.5.0')"
|
|
BUILD="$(/usr/libexec/PlistBuddy -c 'Print :ApplicationProperties:CFBundleVersion' "$ARCHIVE_PATH/Info.plist" 2>/dev/null || echo 'unknown')"
|
|
cp -f "$IPA_PATH" "$IOS_DIR/store/VMC-${VER}-${BUILD}.ipa"
|
|
echo "IPA_OK: $IPA_PATH (copied to store/VMC-${VER}-${BUILD}.ipa)"
|
|
fi
|
|
|
|
if [[ -z "${IPA_PATH:-}" ]]; then
|
|
IPA_PATH="$(find "$EXPORT_PATH" -name '*.ipa' -type f 2>/dev/null | head -1 || true)"
|
|
fi
|
|
[[ -n "${IPA_PATH:-}" && -f "$IPA_PATH" ]] || die "Geen IPA om te uploaden"
|
|
|
|
echo "=== Upload via altool (API key) ==="
|
|
# Prefer modern notary/upload path; altool still works for ASC API key upload
|
|
set +e
|
|
xcrun altool --upload-app \
|
|
--type ios \
|
|
--file "$IPA_PATH" \
|
|
--apiKey "$KEY_ID" \
|
|
--apiIssuer "$ISSUER_ID" \
|
|
2>&1 | tee "$IOS_DIR/build/testflight-upload.log"
|
|
UPLOAD_EC=${PIPESTATUS[0]}
|
|
set -e
|
|
|
|
if [[ "$UPLOAD_EC" -ne 0 ]]; then
|
|
echo "altool failed (exit $UPLOAD_EC); trying iTMSTransporter..."
|
|
TRANSPORTER="/Applications/Xcode.app/Contents/SharedFrameworks/ContentDeliveryServices.framework/Versions/A/itms/bin/iTMSTransporter"
|
|
if [[ -x "$TRANSPORTER" ]]; then
|
|
"$TRANSPORTER" -m upload \
|
|
-assetFile "$IPA_PATH" \
|
|
-apiKey "$KEY_ID" \
|
|
-apiIssuer "$ISSUER_ID" \
|
|
-v informational 2>&1 | tee -a "$IOS_DIR/build/testflight-upload.log"
|
|
else
|
|
die "Upload mislukt (altool exit $UPLOAD_EC) en iTMSTransporter niet gevonden"
|
|
fi
|
|
fi
|
|
|
|
echo "UPLOAD_OK $(date)"
|
|
echo "IPA=$IPA_PATH"
|
|
echo "Log: $IOS_DIR/build/testflight-upload.log"
|