01

Die Entscheidung für diese Woche

Ein workflow_job durchläuft in GitHub Actions mindestens die drei für die Kapazitätsplanung relevanten Zustände queued, in_progress und completed. Das ist in der offiziellen Webhook-Dokumentation beschrieben: GitHub dokumentiert die workflow_job-Zustände.

Unsere Empfehlung für diese Woche: Zählen Sie nicht Ihre Entwickler, sondern die gleichzeitig wartenden Jobs. Starten Sie bei einem selten ausgelasteten Einzelprojekt mit einem Mac. Wenn Build, Test und Archive regelmäßig dieselbe Maschine blockieren, planen Sie zwei Macs oder eine zeitweise zusätzliche Umgebung ein. Bei mehreren Apps entscheiden Sie anhand realer Spitzenwerte, akzeptabler Wartezeit und der notwendigen Trennung von Veröffentlichungen.

Eine niedrige durchschnittliche Runner-Auslastung beweist nicht, dass eine Maschine ausreicht. Ein Release-Fenster kann trotzdem eine Warteschlange erzeugen. Für GitHub Actions iOS Parallel-Builds zählen deshalb vier Werte: Spitzenzahl gleichzeitig aktiver Jobs, belegte Runner-Zeit, akzeptable Wartezeit und Sicherheitsanforderungen für Signierung und Veröffentlichung.

Für wen dieser Leitfaden gedacht ist

Dieser Beitrag richtet sich an Sie, wenn Sie eine iOS-App allein pflegen und bereits einen GitHub-Actions-self-hosted runner eingerichtet haben, aber die Kapazität eines einzelnen Remote Mac nicht sicher einschätzen können.

Er passt ebenfalls zu kleinen Teams, die Pull-Request-Tests parallel zu TestFlight-Veröffentlichungen ausführen möchten. Auch Projektverantwortliche mit deutlichen Release-Spitzen erhalten eine Entscheidungshilfe für eine wochen- oder monatsweise Mac-Miete statt für dauerhaft ungenutzte Hardware.

02

Erst die Last messen, dann Macs zählen

Ein Workflow ist die Beschreibung des Ablaufs. Ein Job ist eine einzelne ausführbare Einheit innerhalb dieses Workflows. Ein Runner nimmt einen Job an. Der Mac ist die physische oder gemietete Arbeitsumgebung. Diese Begriffe dürfen in der Kapazitätsrechnung nicht vermischt werden.

Ein Workflow mit fünf Jobs benötigt nicht automatisch fünf Macs. Wenn die Jobs voneinander abhängen, können sie nacheinander laufen. Wenn sie unabhängige Matrix-Einträge bilden und passende Runner verfügbar sind, können sie gleichzeitig starten. Zusätzlich kann Xcode interne Aufgaben parallel ausführen, ohne dass dadurch mehrere GitHub-Actions-Jobs entstehen.

Die erste Messung sollte deshalb je Job erfolgen:

  • Zeitpunkt der Einreihung in die Warteschlange.
  • Beginn der Ausführung auf dem Runner.
  • Ende des eigentlichen Builds oder Tests.
  • Zeit für Archive, Signierung und Upload.
  • Fehler und Wiederholungen.
  • Wartezeiten, die nicht auf dem Mac entstehen.

App Store Connect kann nach dem Upload serverseitig weiterarbeiten. Diese Zeit blockiert nicht zwingend den Runner. Sie darf daher nicht als Mac-Kapazität verbucht werden, sofern der Workflow den Runner währenddessen freigibt. Die offiziellen Hinweise zum Upload von Builds zu App Store Connect helfen bei der Abgrenzung.

Für jede Job-Klasse führen Sie eine eigene Zeile in Ihrer internen Aufzeichnung:

  • Pull-Request-Build.
  • Schnelle Unit- oder UI-Prüfung.
  • Simulator-Test mit mehreren Konfigurationen.
  • Archive für TestFlight.
  • Signierung und Upload.
  • Wiederholung nach einem fehlerhaften Lauf.

GitHub stellt Hinweise zu Ausführungs- und Wartungsmetriken bereit. Nutzen Sie dafür die Dokumentation zu Actions-Metriken. Fehlen Ihnen Organisationsmetriken, reicht für ein Einzelprojekt zunächst eine exportierte Aufzeichnung aus Workflow-Historie und Job-Logs. Ergänzen Sie für jeden Lauf die Einreihungszeit und den tatsächlichen Startzeitpunkt.

Wie lässt sich aus der Wartezeit die Runner-Anzahl ableiten?
Nehmen Sie das höchste gleichzeitige Job-Aufkommen innerhalb Ihres gewünschten Beobachtungsfensters. Prüfen Sie anschließend, wie viele Jobs während dieser Spitze bereits laufen und wie viele warten. Wenn die Wartezeit nur entsteht, weil ein Release-Job den einzigen Runner lange belegt, ist die Ursache nicht automatisch eine zu schwache Maschine. Sie kann auch in einer falschen Job-Reihenfolge oder fehlenden Isolation liegen.

Eine einfache Kapazitätsgleichung lautet:

Benötigte Runner-Kapazität = parallele Spitzenjobs × belegte Zeit je Job, bewertet gegen das erlaubte Wartefenster.

Das ist kein allgemeiner Performancewert. Die Job-Zeit stammt aus Ihrem Projekt. Auch das Wartefenster müssen Sie selbst festlegen. Für einen Pull-Request kann eine längere Wartezeit akzeptabel sein als für einen geplanten Release-Job.

03

Einzelprojekt mit niedriger Frequenz: Ein Mac bleibt die richtige Basis

Für eine einzelne App mit wenigen parallelen Branches und kleinen Testmatrizen ist ein Mac meistens der sinnvollste Ausgangspunkt. Das gilt besonders, wenn TestFlight-Archive außerhalb der normalen Entwicklungszeiten erstellt werden können.

Die Entscheidung für einen Mac bleibt plausibel, wenn:

  • Pull-Request-Prüfungen nicht regelmäßig mit Releases kollidieren.
  • Die Testmatrix klein genug ist, um nacheinander zu laufen.
  • Ein Release bei Bedarf Vorrang erhält.
  • Ein kurzfristiger Ausfall nicht sofort eine zugesagte Veröffentlichung verhindert.
  • Wiederholte Jobs nicht durch unnötige Abhängigkeitsschritte verlängert werden.

Ordnen Sie Workflows nach ihrer Funktion. Ein schneller Quellcode- und Kompiliercheck sollte nicht dieselbe Priorität wie ein signiertes Release-Archive erhalten. GitHub Actions unterstützt Regeln für Abbruch und Gruppierung von parallelen Abläufen; die Dokumentation zur Workflow-Concurrency beschreibt diese Steuerung.

Besonders häufig entsteht eine scheinbare Kapazitätslücke durch veraltete Jobs. Wenn bei jedem neuen Commit eine vollständige Prüfung für denselben Branch weiterläuft, konkurrieren überholte Ergebnisse mit dem aktuellen Stand. Prüfen Sie zuerst:

  • Werden ältere Pull-Request-Läufe bei einem neuen Commit abgebrochen?
  • Werden Abhängigkeiten bei jedem Job vollständig neu geladen?
  • Werden Tests doppelt ausgeführt?
  • Läuft ein Archive-Job parallel zu einer unnötigen Testmatrix?
  • Bleibt der Runner nach einem Fehler durch einen Prozess oder ein geöffnetes Fenster blockiert?

Kann ein einzelner self-hosted runner mehrere iOS-Jobs gleichzeitig ausführen?
Ja, aber nicht automatisch und nicht ohne Nebenwirkungen. Mehrere Jobs können nur dann parallel laufen, wenn mehrere Ausführungskapazitäten verfügbar sind und die Konfiguration dies zulässt. Ein einzelner Mac kann dabei mehrere Prozesse ausführen, doch CPU, Arbeitsspeicher, Simulatoren, Derived Data, Schlüsselbund und temporäre Dateien werden gemeinsam genutzt. Für reproduzierbare Archive sollten Sie konkurrierende signierte Veröffentlichungen nicht einfach auf dieselbe Arbeitsumgebung legen.

Die offiziellen Regeln zur Auswahl und Zuordnung eines Runners sind deshalb wichtiger als eine pauschale Mac-Anzahl. Prüfen Sie Labels und Gruppen so, dass ein Release nicht versehentlich auf einem Runner mit ungeeigneter Xcode-Version landet.

04

Einzelentwickler mit hoher Frequenz: Zwei Wege statt reflexartig zwei Macs

Bei häufigen Branch-Builds, regelmäßigen Simulator-Tests und mehreren TestFlight-Archiven entsteht die Kapazitätsfrage anders. Hier zählt nicht der Tagesdurchschnitt. Entscheidend ist, ob sich die Jobs innerhalb eines kurzen Zeitfensters stapeln.

Für diese Last prüfen wir in dieser Reihenfolge:

  1. Veraltete Jobs abbrechen.
  2. Schnelle Pull-Request-Prüfungen von vollständigen Tests trennen.
  3. Test-, Archive- und Upload-Schritte einzeln messen.
  4. Release-Jobs auf einen eigenen Labelbereich routen.
  5. Erst danach eine zweite Umgebung bestellen oder dauerhaft einplanen.

Ein zweiter Mac verbessert hauptsächlich die Parallelität und die Wiederherstellung bei Ausfällen. Er macht nicht automatisch einen einzelnen Job schneller. Wenn ein Build intern durch eine fehlerhafte Abhängigkeit oder eine ineffiziente Xcode-Konfiguration gebremst wird, verschiebt ein zusätzlicher Runner nur die Warteschlange.

Xcode stellt Werkzeuge zur Analyse von Build-Zeiten bereit. Nutzen Sie die Apple-Dokumentation zu Build-Timing und inkrementellen Builds, bevor Sie Hardware als Lösung festlegen. Ein vollständig bereinigter Build und ein inkrementeller Build sind nicht dieselbe Messung.

Reicht ein Remote Mac für eine unabhängige iOS-Entwicklung aus?
Ja, wenn die Jobs überwiegend nacheinander laufen dürfen, die Release-Zeit nicht streng begrenzt ist und ein vorübergehender Ausfall akzeptabel bleibt. Zwei Macs sind sinnvoller, wenn ein Pull-Request-Test während eines Archive-Laufs nicht warten darf oder wenn der zweite Runner als Rückfallumgebung benötigt wird. Entscheidend ist nicht die Bezeichnung „Remote Mac“, sondern die gemessene Überschneidung Ihrer Jobs.

05

Kleine Teams: Feedbackzeit gegen Produktionsisolation abwägen

Bei mehreren Entwicklern steigt nicht zwingend die benötigte Mac-Anzahl im gleichen Verhältnis zur Personenzahl. Zwei Personen können mit wenigen Jobs problemlos eine Maschine nutzen. Ein kleines Team kann aber auch mit wenigen Mitarbeitern regelmäßig eine Warteschlange erzeugen, wenn jeder Pull Request eine Simulator-Matrix startet.

Definieren Sie deshalb zwei getrennte Ziele:

  • Wie lange darf eine schnelle Pull-Request-Prüfung maximal warten?
  • Darf ein Release-Job durch normale Entwicklungsarbeit blockiert werden?

Für ein kleines Team ist eine zweite Umgebung häufig dann sinnvoll, wenn der zusätzliche Runner nicht nur die durchschnittliche Auslastung senkt, sondern einen konkreten Engpass beseitigt. Weisen Sie Runner über Labels oder Gruppen zu. GitHub beschreibt das Anwenden von Runner-Labels; verwenden Sie dabei keine projektinternen Namen, Zugangsdaten oder Team-IDs in öffentlich sichtbaren Beispielen.

Eine mögliche Trennung ist:

  • validation: schnelle Builds und ausgewählte Tests.
  • simulator: aufwendige Simulator- und UI-Testläufe.
  • release: Archive, Signierung und Upload.

Die Namen sind nur Beispiele. Entscheidend ist, dass der Release-Bereich nicht von beliebigen Entwicklungsjobs beansprucht wird. Signaturmaterial, Schlüsselbund, Zertifikate, Provisioning Profiles und App-Store-Zugänge müssen getrennt verwaltet werden. Ein zweiter Mac ohne Credential-Isolation löst kein Sicherheitsproblem.

Apple dokumentiert die Interpretation von Testergebnissen in den Hinweisen zu Xcode-Testläufen und Testergebnissen. Prüfen Sie nach einer Aufteilung, ob die Testberichte weiterhin vollständig gesammelt, archiviert und dem richtigen Commit zugeordnet werden.

06

Mehrere Apps: Basis- und Release-Kapazität getrennt planen

Wenn mehrere Repositories dieselben Macs verwenden, reicht eine gemeinsame Runner-Zahl nicht als Planungseinheit. Ein nächtlicher Build, ein Pull Request und ein Produktions-Archive haben unterschiedliche Dringlichkeit, Sicherheitsanforderungen und Werkzeugketten.

Für mehrere Apps empfehlen wir drei Modelle:

Konstante Basiskapazität:
Eine feste Zahl an Runnern deckt normale Pull-Request- und Testlast ab. Release-Jobs verwenden eine gesonderte Gruppe. Dieses Modell passt, wenn die Auslastung relativ gleichmäßig ist und die Xcode-Versionen selten wechseln.

Temporäre Erweiterung zum Release:
Die Basis bleibt klein. Während eines vorhersehbaren Test- oder Veröffentlichungsfensters kommt ein zusätzlicher Remote Mac hinzu. Dieses Modell passt, wenn die Kapazität nur an bestimmten Tagen benötigt wird und die Einrichtung reproduzierbar ist.

Vollständig unabhängige Veröffentlichungsumgebung:
Produktion erhält eigene Hardware, eigene Credentials und einen eigenen Wiederanlaufplan. Dieses Modell ist angemessen, wenn mehrere Apps gleichzeitig veröffentlicht werden oder ein fehlgeleiteter Entwicklungsjob ein unvertretbares Risiko darstellt.

Für jedes Modell brauchen Sie eine Abbruchbedingung. Optimieren Sie weiter, solange die Warteschlange durch unnötige Wiederholungen oder falsche Workflow-Abhängigkeiten entsteht. Bestellen Sie zusätzliche Kapazität, wenn die Jobs bereits sinnvoll getrennt sind und die gleiche Spitze wiederholt auftritt. Reduzieren Sie die temporäre Umgebung, sobald das Release-Fenster vorbei ist und die gemessene Last dauerhaft zurückgeht.

07

Die Kapazitätsprüfung in fünf ausführbaren Schritten

1. Jobs statt Workflows exportieren

Notieren Sie für einen repräsentativen Zeitraum jeden relevanten Job. Erfassen Sie Start der Warteschlange, Runner-Start, Ende, Fehlerstatus und Wiederholung. Trennen Sie Build, Test, Archive, Signierung und Upload.

2. Warteschlange und Ausführung auseinanderhalten

Berechnen Sie die Wartezeit aus „queued“ bis „in_progress“. Berechnen Sie die Runner-Belegung aus dem tatsächlichen Start bis zur Freigabe. Serverseitige Verarbeitung nach dem Upload gehört nicht in die Mac-Belegungszeit, wenn der Job bereits beendet ist.

3. Spitzen statt Mittelwerte markieren

Markieren Sie die Zeitfenster, in denen mehrere Jobs gleichzeitig aktiv oder wartend waren. Ein Durchschnitt über den gesamten Tag darf diese Spitze nicht verdecken. Wiederholen Sie die Auswertung getrennt für normale Entwicklung und Release-Tage.

4. Routing und Credentials prüfen

Kontrollieren Sie Labels, Runner-Gruppen, Xcode-Version, Zertifikate, Schlüsselbund und Dateipfade. Entfernen Sie Repository-, Account-, Bundle-ID-, Team-ID- und Log-Daten aus Beispielen und Ausgaben. Eine falsch geroutete Job-Ausführung ist ein Konfigurationsfehler, kein Beweis für fehlende Hardware.

5. Wiederherstellung testen

Trennen Sie den Runner kontrolliert vom Netzwerk. Starten Sie den Mac neu. Prüfen Sie, ob der Runner wieder registriert wird, keine alten Prozesse hängen bleiben und ein Release-Job auf die richtige Umgebung gelangt. Ein Zwei-Mac-Plan ist erst belastbar, wenn Routing und Credential-Isolation nach einem Ausfall funktionieren.

08

Checkliste für die Entscheidung

  • [ ] Für jeden wichtigen Job sind Warteschlangen- und Ausführungszeiten dokumentiert.
  • [ ] Build, Test, Archive, Signierung, Upload und serverseitige Verarbeitung sind getrennt erfasst.
  • [ ] Die größte gleichzeitige Job-Spitze ist aus Workflow-Historie oder Logs nachvollziehbar.
  • [ ] Veraltete Pull-Request-Jobs werden bei neuen Commits beendet, sofern sie nicht benötigt werden.
  • [ ] Ein einzelner Mac wurde nach Netzwerkunterbrechung und Neustart erfolgreich wiederhergestellt.
  • [ ] Release-Jobs besitzen eigene Labels oder eine eigene Runner-Gruppe.
  • [ ] Zertifikate, Schlüsselbund und Provisioning Profiles sind nicht unkontrolliert für normale Testjobs verfügbar.
  • [ ] Die gewählte Xcode-Version ist auf jedem Ziel-Runner eindeutig geprüft.
  • [ ] Bei zwei Macs wurde getestet, ob ein Job wirklich auf die vorgesehene Umgebung gelangt.
  • [ ] Für eine temporäre Erweiterung sind Lieferzeit, Werkzeugketten-Abgleich und Rückbau dokumentiert.
  • [ ] Die Entscheidung wird nach neuen Messdaten erneut geprüft, nicht nach der Entwicklerzahl.
09

Einzel-Mac, zwei Macs oder zeitweise Erweiterung

Wählen Sie einen Mac, wenn die Spitzenjobs nacheinander laufen dürfen, die Wartezeit akzeptabel bleibt und ein Release bei Bedarf priorisiert werden kann. Das ist der normale Startpunkt für ein einzelnes, selten veröffentlichtes Projekt.

Wählen Sie zwei Macs, wenn Build und Test regelmäßig mit Archive oder TestFlight kollidieren, wenn ein zweiter Runner als Rückfall benötigt wird oder wenn die Sicherheitsgrenze zwischen Validierung und Veröffentlichung nicht zuverlässig auf einer Umgebung abbildbar ist.

Wählen Sie eine zeitweise Erweiterung, wenn die zusätzliche Last klar auf Release-Tage, Testkampagnen oder geplante Migrationsfenster begrenzt ist. Das verhindert, dass Sie dauerhaft Hardware bezahlen, die außerhalb dieser Spitzen überwiegend wartet.

Bei einer Entscheidung für eigene Hardware sollten Sie nicht nur den Kaufpreis betrachten. Stromversorgung, Wartung, Ersatzgerät, physischer Standort, Netzwerkzugang und Ausfallzeit gehören ebenfalls in die Rechnung. Eine Übersicht zu Mac-mini-Kaufoptionen kann als Vergleichspunkt für die Alternative „eigene Maschine“ dienen.

Für eine temporäre Lücke ist ein gemieteter Remote Mac oft leichter zu begründen: Sie erhalten eine zusätzliche macOS-Umgebung für den Zeitraum, in dem die Messung tatsächlich eine zweite Kapazität verlangt. Bei MESHLAUNCH sollten Sie vor der Buchung insbesondere Mietzeitraum, Lieferweg, Xcode-Kompatibilität, Root-Zugriff, Neustartverhalten und die geplante Runner-Registrierung prüfen. Einen Einstieg in die verfügbaren Remote-Mac-Optionen von MESHLAUNCH finden Sie auf der entsprechenden Übersichtsseite.

Der Vergleich bleibt trotzdem nüchtern. Ein selbst verwalteter Mac bietet langfristig eine konstante Umgebung und ist bei dauerhaft hoher Last oft einfacher zu amortisieren. Eine gemietete Umgebung ist weniger geeignet, wenn Sie dauerhaft maximale Auslastung benötigen, spezielle physische Anschlüsse voraussetzen oder sensible Hardware lokal kontrollieren müssen. Ihre Entscheidung sollte aus der gemessenen Warteschlange entstehen, nicht aus einer pauschalen Annahme über „Cloud“ oder „lokal“.

Wenn die aktuelle Lösung nur einen Mac besitzt, führt eine gemeinsame Queue zu drei realen Nachteilen: Release-Jobs blockieren Pull-Request-Feedback, ein einzelner Ausfall stoppt sowohl Tests als auch Veröffentlichungen, und Signaturmaterial liegt leichter in derselben Arbeitsumgebung wie normale Validierungsjobs. Eine zusätzliche MESHLAUNCH-Mac-Umgebung kann diese Engpässe während eines definierten Zeitraums trennen und zugleich die Rückfallprüfung ermöglichen, ohne sofort ungenutzte Kaufhardware zu binden.

Beginnen Sie mit der Kapazitätskarte: Spitzenjobs, Wartezeit, belegte Zeit, Isolation und Wiederherstellung. Wenn nur die Release-Woche die Lücke erzeugt, mieten Sie die zusätzliche Umgebung für genau diesen Zeitraum und testen Sie Routing, Signierung und Rückbau. Wenn die Warteschlange jeden Arbeitstag entsteht, ist eine dauerhafte Zwei-Mac-Architektur oder eine weitere Workflow-Optimierung die ehrlichere Entscheidung.