← Zurück zum Tech-Blog

Warum ist GitHub Actions iOS CI auf dem Mac so langsam? Self-hosted Runner sind der echte Turbo

GitHub Actions iOS CI: Mac mini self-hosted Runner mit persistentem DerivedData
Gehostete macOS-Runner starten kalt; dedizierter Mac mini hält DerivedData über Jobs hinweg.

Kurz vorweg: Wenn iOS-CI in GitHub Actions langsam wirkt, liegt es selten an eurem Code und fast immer an der Build-Umgebung. Der eigentliche Flaschenhals sitzt in der macOS-Kette (Pods, Xcode, Signing, Upload). Genau deshalb ist ein self-hosted Runner auf einem dedizierten Mac die realistische Geschwindigkeits- und Stabilitätslösung. Wenn du tiefer einsteigen willst: TCO des Runner-Setups, Flutter iOS CI, Xcode Build-Lags und der größere Infrastrukturkontext in KI-Compute-Infrastruktur.

1) Warum ist GitHub Actions iOS CI oft langsam?

iOS-Builds brauchen echte macOS-Toolchains. Hosted Runner starten häufig mit frischen Zuständen, Caches greifen nur begrenzt, und die Laufzeit schwankt stark. Ergebnis: dieselbe Pipeline heute 15 Minuten, morgen 27 Minuten. Das Problem ist nicht YAML, sondern fehlende Persistenz.

Merksatz: Hosted Runner liefern „läuft irgendwie“, self-hosted liefert „läuft reproduzierbar schnell“.

2) Wo geht die Zeit verloren?

SchrittTypische DauerWarum hosted oft bremst
pod install4–12 MinPods/Specs werden häufig neu geladen
xcodebuild archive8–20 MinDerivedData ist nicht stabil wiederverwendbar
Signing / Export2–8 MinKeychain/Provisioning wird immer neu initialisiert
Upload2–10 MinNetzpfad und Queue-Latenz variieren stark

3) Zielarchitektur: Linux für Tests, Mac für iOS Release

Empfohlene GitHub Actions iOS CI Architektur

Developer Push / PR
GitHub Actions (ubuntu-latest)
lint · tests · Android
Self-hosted macOS Runner (Mac mini M4)
pod install → xcodebuild archive → export
TestFlight / App Store Connect

Persistente Cache-Ebenen auf dem Runner

  • CocoaPods Cache + Pods
  • DerivedData
  • Ruby/Bundler Tooling

4) Runner-Setup, das in der Praxis schnell bleibt

  1. Feste Maschine, feste Pfade: nur so treffen Caches zuverlässig.
  2. Versionen pinnen: Xcode, CocoaPods, Ruby bewusst fixieren.
  3. Parallelität begrenzen: auf einem Mac meist 1–2 iOS Jobs.
  4. Schwere Updates entkoppeln: z. B. pod repo update separat planen.
  5. Disk-Hygiene: Archives/DerivedData regelmäßig aufräumen.

Dazu passen die offiziellen Referenzen: GitHub self-hosted Runner Doku und Apple Xcode Release Notes.

5) Before/After: Hosted vs self-hosted

Umgebung1. Build (kalt)2. Build (warm)Vorhersagbarkeit
GitHub hosted macOS16–24 Min14–20 MinMittel
Mac mini M4 self-hosted14–22 Min5–9 MinHoch
Wichtig: Der eigentliche Hebel zeigt sich ab dem zweiten Build. Genau dort spart ihr pro Woche die meiste Wartezeit.

6) Workflow-Snippet für iOS Release

name: release-ios
on:
  push:
    branches: [main]
    tags: ['v*']

jobs:
  ios:
    runs-on: [self-hosted, macos, ios]
    steps:
      - uses: actions/checkout@v4
      - name: Install
        run: |
          bundle install
          cd ios && pod install && cd ..
      - name: Archive
        run: xcodebuild -workspace App.xcworkspace -scheme App -configuration Release archive
      - name: Export IPA
        run: xcodebuild -exportArchive -archivePath build/App.xcarchive -exportOptionsPlist ios/ExportOptions.plist -exportPath build

Wenn ihr Flutter fahrt, bleibt das Prinzip identisch: Test-Last auf Linux, iOS-Paket auf dem Mac Runner. Praxisbeispiel: Flutter iOS CI Setup.

7) Betriebs-Checkliste für stabile Geschwindigkeit

  • Signing zentralisieren: Zertifikate/Profile sauber verwalten.
  • Runner-User trennen: keine manuellen Eingriffe im Build-User.
  • Gezielt retryen: nur Netz-/Upload-Schritte wiederholen.
  • TCO vollständig rechnen: Hardware, Betrieb, Zeitkosten zusammen.

Für die Kostenentscheidung: TCO-Analyse plus Mac mini Preise.

8) Ab wann lohnt der Wechsel auf self-hosted?

Team-SituationEmpfehlungBegründung
≤ 1 iOS Release/MonatHosted behaltenUmstellungsaufwand evtl. zu hoch
2–4 Releases/Monat, CI nervt1 self-hosted PilotROI schnell messbar
Wöchentlich Releases / mehrere AppsSelf-hosted priorisierenmaximaler Zeitgewinn
Verteilte TeamsRegion nah am Repo wählenweniger Latenz bei Pull/Upload

Strategischer Kontext für Infrastrukturentscheidungen: KI-Compute-Infrastruktur-Krieg.

9) FAQ (8 Fragen aus dem Alltag)

Q1: Brauche ich self-hosted schon bei einem App-Projekt?
Nicht zwingend sofort. Aber sobald CI-Wartezeit die Releases bremst, lohnt ein Pilot fast immer.

Q2: Was sollte ich zuerst optimieren?
Pods + DerivedData Caching. Das bringt normalerweise den größten Soforteffekt.

Q3: Ist der Betrieb kompliziert?
Das Initial-Setup kostet etwas Zeit, danach ist es mit klaren Versionen gut beherrschbar.

Q4: Warum scheitert Build manchmal mit Code 65?
Oft Versionsdrift oder kaputtes DerivedData. Erst Versionen prüfen, dann Cache bereinigen.

Q5: Muss Fastlane zwingend sein?
Nein. Stabiler Build + sauberer Upload reichen als erster Schritt.

Q6: Office-Mac oder Cloud-Mac?
Für verteilte Teams und 24/7 Betrieb ist Cloud meist wartungsärmer.

Q7: Was ist mit Security?
Minimalrechte, separater Runner-User, Secret-Management und Audit-Logs sind Pflicht.

Q8: Wie starte ich pragmatisch?
Eine Pipeline eine Woche A/B testen (hosted vs self-hosted) und echte Wartezeit messen.

Preise