Der Archivierungsschritt wird als erfolgreich angezeigt, doch die Pipeline bricht bei -exportArchive ab. Bei solchen Fehlern führt die letzte Meldung „export failed“ leicht in die Irre. Die eigentliche Ursache kann darin liegen, dass Exportmethode und Signaturmaterial nicht zusammenpassen, sich die Entitlements im Archiv geändert haben oder die CI eine andere Xcode-Installation verwendet. Statt den Job immer wieder neu zu starten, sollte dasselbe xcarchive beibehalten und Archivierung, Export und Diagnose in getrennte, unabhängig reproduzierbare Schritte aufgeteilt werden.
Fehlerzustand zuerst sichern
Bereinigen Sie nach einem Fehler nicht sofort das Arbeitsverzeichnis und überschreiben Sie auch nicht das ursprüngliche Archiv. Sichern Sie mindestens das xcarchive, die tatsächlich verwendete Datei ExportOptions.plist, die vollständige Standardausgabe sowie Pfad und Version von Xcode. Dedizierte physische Nodes von RunnerVM eignen sich gut, um einen solchen Zustand zu erhalten. Die Pipeline sollte die Diagnosedateien dennoch ausdrücklich in das Verzeichnis der Job-Artefakte kopieren.
set -euo pipefail
RUN_DIR="$PWD/export-diagnostics"
ARCHIVE_PATH="$PWD/build/App.xcarchive"
mkdir -p "$RUN_DIR"
xcode-select -p > "$RUN_DIR/xcode-path.txt"
xcodebuild -version > "$RUN_DIR/xcode-version.txt"
sw_vers > "$RUN_DIR/macos-version.txt"
cp ExportOptions.plist "$RUN_DIR/ExportOptions.plist"
ditto "$ARCHIVE_PATH" "$RUN_DIR/App.xcarchive"
Erfassen Sie außerdem die Prüfsumme der Archivdatei. Wird das Archiv später ausgetauscht, lässt sich sofort erkennen, dass sich der Untersuchungsgegenstand geändert hat.
ditto -c -k --keepParent "$ARCHIVE_PATH" "$RUN_DIR/App.xcarchive.zip"
shasum -a 256 "$RUN_DIR/App.xcarchive.zip" > "$RUN_DIR/checksums.txt"
Ein fehlgeschlagener Export bedeutet nicht, dass das Archiv ungültig ist. Prüfen Sie zuerst, ob das Archiv vollständig ist, und ordnen Sie den Fehler anschließend entweder der Archivierungs- oder der Distributionsphase zu.
Exportfähigkeit des Archivs prüfen
Ein xcarchive ist im Wesentlichen ein Verzeichnis. Prüfen Sie zunächst, ob Metadaten, App-Bundle und ausführbare Datei vorhanden sind. Lesen Sie danach die im Archiv hinterlegte App-ID und Version aus. Der Pfad sollte nicht aus dem Projektnamen zusammengesetzt, sondern aus der Datei Info.plist ermittelt werden.
INFO="$ARCHIVE_PATH/Info.plist"
APP_RELATIVE=$(/usr/libexec/PlistBuddy -c \
"Print :ApplicationProperties:ApplicationPath" "$INFO")
APP_PATH="$ARCHIVE_PATH/Products/$APP_RELATIVE"
plutil -lint "$INFO"
test -d "$APP_PATH"
test -f "$APP_PATH/Info.plist"
plutil -p "$INFO"
plutil -p "$APP_PATH/Info.plist"
codesign --verify --deep --strict --verbose=2 "$APP_PATH"
Kontrollieren Sie insbesondere ApplicationPath, CFBundleIdentifier, die Versionsnummer und das Ergebnis der Signaturprüfung. Fehlt das App-Bundle vollständig oder schlägt bereits codesign --verify fehl, muss die Ursache im archive-Befehl, in Skripten der Build-Phase oder beim Kopieren der Artefakte gesucht werden. Weitere Änderungen an den Exportoptionen helfen in diesem Fall nicht.
App-Entitlements und Provisioning Profile vergleichen
Während des Exports bewertet Xcode die Signaturbeziehungen erneut. Exportieren Sie die tatsächlichen Entitlements der App und die Entitlements des eingebetteten Provisioning Profiles getrennt, um sie anschließend strukturiert zu vergleichen.
codesign -d --entitlements "$RUN_DIR/app-entitlements.plist" "$APP_PATH"
PROFILE="$APP_PATH/embedded.mobileprovision"
security cms -D -i "$PROFILE" > "$RUN_DIR/profile.plist"
plutil -extract Entitlements xml1 \
-o "$RUN_DIR/profile-entitlements.plist" \
"$RUN_DIR/profile.plist"
plutil -p "$RUN_DIR/app-entitlements.plist"
plutil -p "$RUN_DIR/profile-entitlements.plist"
Vergleichen Sie nicht nur die textuelle Reihenfolge der Einträge. Entscheidend ist, ob das Provisioning Profile alle von der App verwendeten Entitlements erlaubt und ob App-ID, Team-ID sowie umgebungsabhängige Entitlements übereinstimmen. Auch jedes Extension-Target muss einzeln geprüft werden: Ein erfolgreicher Test der Haupt-App garantiert nicht, dass sich alle eingebetteten Komponenten exportieren lassen.
ExportOptions.plist validieren
Führen Sie zuerst plutil -lint ExportOptions.plist aus, um Formatfehler auszuschließen. Prüfen Sie anschließend anhand der Hilfeausgabe der aktuell verwendeten Xcode-Version, welche Schlüssel und Werte verfügbar sind. Da sich zulässige Werte für method zwischen Versionen ändern oder ältere Schreibweisen veraltet sein können, sollte eine Konfiguration aus früheren Jobs nie ungeprüft übernommen werden.
Eine Minimalkonfiguration kann sich auf die Felder beschränken, die für den aktuellen Distributionsablauf tatsächlich erforderlich sind:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>development</string>
<key>signingStyle</key>
<string>manual</string>
<key>stripSwiftSymbols</key>
<true/>
</dict>
</plist>
Der Wert für method ist hier lediglich ein Beispiel für einen Development-Export und darf nicht unverändert für andere Distributionsziele verwendet werden. Führen Sie zunächst die folgenden Befehle aus und richten Sie sich nach den Angaben der aktuellen Toolchain:
plutil -lint ExportOptions.plist
xcodebuild -help > export-help.txt
grep -A 120 "Available keys for -exportOptionsPlist" export-help.txt
Bei manueller Signierung muss außerdem geprüft werden, ob die in der Konfiguration enthaltenen Zuordnungen sowohl die Haupt-App als auch jede Extension abdecken. Fehlende Zuordnungen, falsche IDs oder vermischte Signierungsverfahren werden häufig erst während des Exports sichtbar.
Export separat reproduzieren und vollständiges Protokoll sichern
Sobald das Archiv nachweislich gültig ist, führen Sie den Export separat mit festen absoluten Pfaden aus. Das Skript darf temporäre Verzeichnisse bei einem Fehler nicht sofort löschen.
set +e
xcodebuild -exportArchive \
-archivePath "$ARCHIVE_PATH" \
-exportPath "$RUN_DIR/exported" \
-exportOptionsPlist "$RUN_DIR/ExportOptions.plist" \
2>&1 | tee "$RUN_DIR/export.log"
STATUS=${PIPESTATUS[0]}
set -e
printf '%s
' "$STATUS" > "$RUN_DIR/export-status.txt"
exit "$STATUS"
Suchen Sie im Protokoll zuerst nach dem frühesten konkreten Fehler und nicht nach der Zusammenfassung am Ende. Eine erste Filterung kann nach Signierung, Provisioning Profiles, Entitlements und Exportmethode erfolgen:
grep -Ein \
"error:|provision|entitlement|certificate|signing|export" \
"$RUN_DIR/export.log" > "$RUN_DIR/export-errors.txt" || true
Mitunter nennt xcodebuild in der Ausgabe den Pfad zu einem Distributionsprotokollpaket. Archivieren Sie dieses Verzeichnis vollständig. Es enthält üblicherweise die Entscheidungen aus den einzelnen Phasen des IDEDistribution-Ablaufs und führt damit näher an die eigentliche Ursache heran als die wenigen von der Pipeline übernommenen Fehlerzeilen.
Abnahmecheckliste für die Fehlerbehebung erstellen
Verlassen Sie sich nach der Korrektur nicht allein auf den Exit-Code. Prüfen Sie mindestens, ob das Exportverzeichnis die erwartete Datei enthält, die Signaturprüfung erfolgreich ist und App-ID sowie Version mit dem Archiv übereinstimmen. Archivieren Sie außerdem die endgültige Datei ExportOptions.plist zusammen mit der verwendeten Xcode-Version.
Die folgenden Prüfungen sollten als feste Checkliste am Ende des Jobs ausgeführt werden:
- Die Prüfsumme des komprimierten Archivs ist unverändert.
- Das aktuelle Ergebnis von
xcode-select -pentspricht der erwarteten Toolchain. - Die Haupt-App und alle Extensions bestehen die Signaturprüfung.
- Die App-Entitlements überschreiten nicht den vom Provisioning Profile erlaubten Umfang.
- Die Exportkonfiguration besteht die
plutil-Prüfung, und ihre Schlüssel und Werte werden von der aktuellen Xcode-Version unterstützt. - Exportprotokoll, Distributionsprotokollpaket und endgültige Artefakte werden gemeinsam gespeichert.
- Die Korrektur verändert nur eine Variable und lässt sich mit dem ursprünglichen Archiv wiederholt verifizieren.
Mit diesem Vorgehen ist der Archivexport kein schwer nachvollziehbarer Blackbox-Vorgang mehr. Das Team kann klar zwischen einer abweichenden Toolchain, Konfigurationsfehlern, fehlerhaften Signaturbeziehungen und einem beschädigten Archiv unterscheiden. Die meisten Korrekturen lassen sich dabei ohne erneuten Build überprüfen.
Häufig gestellte Fragen
Sollte ein Archiv nach einem fehlgeschlagenen Export sofort neu erstellt werden?
Nein. Bewahren Sie das ursprüngliche xcarchive auf und prüfen Sie Metadaten, App-Paket, eingebettetes Profil und Signaturrechte. Eine Neuerstellung kann die entscheidenden Fehlerhinweise überschreiben.
Kann dieselbe ExportOptions.plist mit mehreren Xcode-Versionen verwendet werden?
Nur nach erneuter Prüfung. Vergleichen Sie die Datei mit der xcodebuild-Hilfe der ausgewählten Xcode-Version und validieren Sie sowohl die unterstützten method-Werte als auch die plist-Syntax.
Den nächsten Build auf einem exklusiven physischen Mac ausführen
Wählen Sie einen Cloud-Mac-Knoten passend zur Auftragsdauer und verwalten Sie Bestellungen, Verbindungsdaten und Support-Tickets in der Konsole.