Swift 6 und strict concurrency untergraben das Vertrauen in die CI, wenn lokal alles grün ist, die Pipeline aber flaky wirkt. Häufig sind nicht Business-Logik sondern abweichende Build-Settings, DerivedData-Races, andere Simulator-Destinations oder Warnungen ohne Gate die Ursache. Dieser Leitfaden bündelt sieben typische Schmerzpunkte, eine Vergleichstabelle der Ausführungsumgebungen und ein sechsstufiges Runbook inklusive Abnahme. Ergänzend: SwiftPM, CocoaPods und DerivedData, reproduzierbare Build-Fingerabdrücke, Self-Hosted-Runner und Cache-Trennung.
Concurrency-Diagnosen sind timing-sensitiv; minimale Umgebungsunterschiede zerstreuen Fehlerbilder.
Swift- und Xcode-Kombination weicht zwischen Laptop und CI ab:Ohne swift --version und xcodebuild -version in den Logs fehlt selbst die Basis für Sendable-Diagnosen.
Strenge Prüfungen nur vor dem Release aktivieren:Tagesgeschäft bleibt lax, Staging wird hart konfiguriert und die Delta-Flut verzögert Rollbacks.
Parallele xcodebuild-Aufrufe teilen ein DerivedData-Verzeichnis:Rennen zerstören inkrementelle Builds und erzeugen Clean-Zyklen ohne eigentlichen Concurrency-Bug.
Warnungen werden geduldet, die Pipeline bleibt grün:Muster, die erst nach Anheben von SWIFT_STRICT_CONCURRENCY fatal werden, bleiben unbemerkt.
UI- und Unit-Tests laufen ohne Actor-Plan im selben Job:Simulatorlast und Flags überlagern sich; Flakes werden fälschlich der Concurrency-Migration zugeschrieben.
Keine Runbook-Zeile zu xcode-select oder TOOLCHAINS:Ein GUI-Wechsel des Xcode reicht, um Nachtjobs auf einem anderen Compiler laufen zu lassen.
Nur swift build unter Linux, iOS-Ziele ohne strikte Prüfung:Server- und UIKit-Ziele erzeugen verschiedene Diagnosemengen; Probleme werden verschoben statt aufgelöst.
Gemeinsamer Nenner: Der Compilerzustand wird am CI-Eingang nicht als Invariante behandelt. Dedizierte Remote-Macs erlauben, ihn per SSH wie Infrastruktur zu pinnen.
Ziel ist eine identische Diagnosemenge je Lauf. Je volatiler Parallelität und Cache-Politik, desto mehr schwankt das Strenge-Ergebnis.
| Dimension | Xcode Cloud | Gehosteter macOS-Runner | Dedizierter Remote-Mac (SSH) |
|---|---|---|---|
| Toolchain-Pinning | Folgt Managed-Updates | Abhängig von Image-Tags und Nachbarn | xcode-select und Layout vertraglich fixierbar |
| Reproduzierbarkeit | Hoch bei klar entworfenen Workflows | Oft durch Pool-Rivalität gestört | DerivedData pro Job leicht trennbar |
| xcodebuild-Freiheit | Manchmal Grenzen für Skripte | Ab Runner-Policy | -destination und -derivedDataPath stabil |
| Typische Fehler | Queues, Quoten, Schrittgrenzen | Fehlende Deps nur auf frischen Images | Sleep-Richtlinien, volle Platten |
| Ideal für | Standardisierte Store-Nähe | Viele kurze Smokes | Monorepos mit harten Gates |
Strict concurrency ist in der CI auch eine Frage der physischen Platzierung von Compiler und Cache.
Budget und Bandbreite sollten mit Mietverträgen und Abrechnung abgestimmt werden.
Jeder Schritt hinterlässt Prüfpfad; Branch-Schutzregeln sollten beim Eingang abbrechen.
Xcode-Profil einfrieren und xcode-select -p archivieren.
Immer xcodebuild -version, xcodebuild -showsdks, swift --version ausgeben.
SWIFT_STRICT_CONCURRENCY konsistent setzen; stufenweise Migration im Ticket dokumentieren.
Feste -scheme, -destination, per-Job--derivedDataPath; bei SwiftPM -clonedSourcePackagesDirPath trennen.
Testpyramide entkoppeln und parallele Slots vertraglich begrenzen.
Abnahmecheckliste signieren: Log-Snippets, Compilerversion, Stufen, Clean-Repro.
#!/usr/bin/env bash set -euo pipefail xcodebuild -version xcodebuild -showsdks swift --version export DERIVED_DATA="$(pwd)/.derivedData/$CI_JOB_ID" xcodebuild -scheme "App" \ -destination 'platform=iOS Simulator,name=iPhone 16' \ -derivedDataPath "$DERIVED_DATA" \ build
Hinweis:Third-Party-Module in Targeted-Modus belassen, bis ein Upgrade-Pfad dokumentiert ist.
Nacht-Batches und interaktive Tags sollten unterschiedliche Konten nutzen, um versehentliche Toolchain-Wechsel zu vermeiden.
Modulweise Checks entstehen aus Xcode-Settings plus Compilerflags; eine öffentliche Matrix je Ziel reduziert Review-Reibung.
Hinweis:Detailsemantik folgt den Apple- und Swift-Release-Notes. Enthielten Build-Logs personenbezogene Metadaten, klären Sie Speicherorte und Auftragsverarbeitung mit Legal im Sinne der DSGVO.
MainActor- und Datenrennen-Warnungen hängen auch von Simulatorlast ab; trennen Sie Performance- und Funktionslogs.
Erfüllen Sie die Punkte, gilt der Rollout als technisch abgeschlossen.
xcodebuild -version und swift --version.SWIFT_STRICT_CONCURRENCY.-derivedDataPath pro Job eindeutig.Geteilte Runner bekämpfen Toolchain-Drift und Festplatten-Rivalität nur begrenzt; Swift-6-Gates wirken dann zufällig. NodeMini-Dedicated-Mac-Mini-Miete passt, wenn SSH-Zugang, klare Plattenstufen und 24/7-iOS-Builds vertraglich festgelegt werden sollen. Spezifikationen und Mietpreise finden Sie in der Übersicht, Einrichtung über das Hilfezentrum Cloud-Mac.
Nach dem Go-Live sollten Verstöße wöchentlich aggregiert und mit Third-Party-Roadmaps verknüpft werden.
Diagnosen hängen stark an Compilerversion und Cache-Layout; exklusive Knoten stabilisieren beides. Preise: Mac-Mini-Mietpreise.
scheme, destination, derivedDataPath und einheitliche Concurrency-Stufe in den Settings. Details: Hilfezentrum.
Xcode-Buildnummer, xcode-select-Pfad, optional TOOLCHAINS, wiederholbare Eingangs-Kommandos. Pläne siehe Mietpreise.