Wenn PRs warten, obwohl mehrere Mac Runner online sind: Die Kapazität nach Spitzenlast, Laufzeit und Zielwartezeit berechnen – nicht nach der Zahl der Entwickler.
Die schnellste Lösung ist eine getrennte Kapazitätsplanung für PR-Builds, Simulator-Tests, Veröffentlichungen und Reserve. Kurzfristige Spitzen decken Sie zunächst mit zusätzlichen Remote Macs ab, statt dauerhaft nach dem Jahresmaximum zu dimensionieren.
Für wen diese Kapazitätsplanung gedacht ist
Dieser Beitrag richtet sich an DevOps-Ingenieure, die selbstgehostete macOS Runner für GitHub Actions betreiben und den richtigen Erweiterungszeitpunkt suchen.
Er ist ebenso für mobile Entwicklungsleiter mit mehreren iOS-Projekten sowie für technische Einkäufer gedacht, die vor einer Miete eines Remote Mac die notwendige Knotenzahl und Laufzeit bestimmen müssen.
Die belastbare Ausgangslage
Die Zahl der online angezeigten Runner ist keine verlässliche Angabe für die tatsächlich nutzbare Parallelität. Ein selbstgehosteter Runner wird von GitHub Actions einem passenden Job zugewiesen; während dieser Ausführung steht derselbe Runner nicht für einen zweiten unabhängigen Job bereit. Das Routing erfolgt über Labels und Runner Groups, nicht über eine pauschale Zusage, dass jeder Mac beliebig viele Workflows gleichzeitig verarbeitet. Die Dokumentation zu selbstgehosteten Runnern beschreibt dieses Verhalten und die Zuordnung zu Jobs.
Für Ihre Rechnung benötigen Sie je Workflow mindestens:
- Zeitpunkt der Auftragserstellung,
- Beginn der tatsächlichen Ausführung,
- gesamte Laufzeit,
- Abbruch- und Wiederholungsstatus,
- verwendete Labels und Runner Group,
- Ergebnis der Aufgabe,
- Ressourcenstatus des Mac während der Ausführung.
Aus diesen Werten entstehen vier Größen:
- Ankunftsrate: Wie viele Jobs treffen in einem definierten Zeitfenster ein?
- Ausführungszeit: Wie lange belegt ein Job einen Runner?
- Wartezeit: Wie lange bleibt er in der Warteschlange?
- Reservebedarf: Wie viele Kapazitäten bleiben bei einem Ausfall oder einer langsamen Ausführung verfügbar?
Eine einfache Näherung lautet:
benötigte Grundparallelität ≈ Auftragsankunft pro Zeitspanne × typische Laufzeit; anschließend müssen Spitzenlast, akzeptierte Wartezeit und Ausfallreserve separat ergänzt werden.
Das ist keine offizielle GitHub-Kapazitätsformel. Es ist ein Planungsmodell, das Sie mit den Laufhistorien Ihres Projekts überprüfen müssen. Der Mittelwert allein reicht nicht aus. Ein einzelner Release-Tag, viele gleichzeitige PRs oder eine ungewöhnlich langsame Archivierung können die reale Warteschlange deutlich stärker bestimmen als der Durchschnitt.
Die GitHub-Metriken und Hinweise zur Selbstüberwachung helfen Ihnen, Wartezeiten, Ausführungen und Fehler nicht nur aus dem Bauchgefühl heraus zu bewerten.
PR-Builds als Grundlast
PR-Builds bilden normalerweise den Sockel Ihrer Mac-Runner-Kapazität. Linting, Code-Prüfung, Unit-Tests und inkrementelle Xcode-Builds treffen über den Arbeitstag verteilt ein. Für die Architekturentscheidung ist nicht die Zahl der Entwickler entscheidend, sondern die Kombination aus Auftragseingang und belegter Runner-Zeit.
Ermitteln Sie zuerst für jeden PR-Workflow:
- Wie häufig neue Jobs eintreffen,
- wie lange ein typischer inkrementeller Build läuft,
- wie stark die Laufzeit bei großen Änderungen schwankt,
- wie lange Entwickler auf ein Ergebnis warten können,
- wie viele Jobs bei neuen Commits noch relevant sind.
Alte PR-Aufträge sind ein häufiger versteckter Kapazitätsverbraucher. Wenn ein neuer Commit denselben Prüfpfad ersetzt, kann eine passende Concurrency-Regel frühere Ausführungen abbrechen. GitHub beschreibt dafür Concurrency-Gruppen und das Abbrechen laufender Ausführungen. Prüfen Sie vor dem Ausbau, ob überholte Jobs noch wertvolle Mac-Zeit belegen.
Auch die Pipeline selbst kann den Bedarf künstlich erhöhen. Verschieben Sie Schritte ohne macOS-Abhängigkeit auf einen passenden nicht-macOS Runner. Fassen Sie kompatible Prüfungen zusammen, wenn dadurch kein verwertbares Feedback verloren geht. Ein Job, der nur einen kurzen macOS-spezifischen Schritt benötigt, sollte nicht mehrere lange Vorprüfungen auf demselben Mac blockieren.
Für Xcode CI ist außerdem wichtig, zwischen „Build beendet“ und „Entwickler kann handeln“ zu unterscheiden. Die Apple-Dokumentation zu Build Timing erklärt, wie Build-Zeiten untersucht werden können. Erfassen Sie dort die langsamen Build-Abschnitte, statt nur die gesamte Workflow-Dauer zu betrachten.
Entscheidung für die Grundkapazität
- Wenn PR-Jobs regelmäßig warten und die Mac-Ressourcen während der Ausführung nicht vollständig ausgelastet sind, dann prüfen Sie zuerst Workflow-Aufteilung, Abbruchregeln und unnötige macOS-Schritte.
- Wenn die Jobs trotz bereinigter Workflows die akzeptierte Wartezeit überschreiten, dann erhöhen Sie den Grundpool.
- Wenn die Warteschlange nur während eines vorhersehbaren Zeitfensters entsteht, dann testen Sie zunächst temporäre Kapazität statt dauerhaft weiterer Knoten.
- Wenn ein einzelner Workflow die Warteschlange dominiert, dann behandeln Sie ihn als eigenes Lastprofil und nicht als Beweis für eine allgemeine Unterversorgung.
Simulator- und UI-Testkapazität
Simulator-Tests gehören nicht automatisch in denselben Kapazitätstopf wie Kompilierung. Ein UI-Test-Job kann mehrere Simulator-Instanzen, Test-Worker und zusätzliche Prozesse starten. Diese interne Parallelität erzeugt aber nicht dieselbe Kapazität wie mehrere unabhängige Mac Runner.
Ein einzelner Mac kann durch zusätzliche Worker schneller fertig werden. Er kann aber ebenso durch Prozessor-, Arbeitsspeicher-, Speicher- oder Simulator-Konkurrenz langsamer und instabiler werden. Die Zahl der Workflow-Jobs und die Zahl der Test-Worker dürfen daher nicht einfach addiert werden.
Apple dokumentiert in den Xcode-Versionshinweisen die Optionen für parallele Tests. Nutzen Sie diese Angaben zur Prüfung, welche xcodebuild-Optionen Ihre Xcode-Version unterstützt. Die endgültige Entscheidung muss jedoch aus Ihrem Projekt stammen.
Messen Sie bei einem kontrollierten Testlauf:
- Zeit bis zum ersten Testergebnis,
- gesamte effektive Testdauer,
- CPU- und Arbeitsspeicherdruck,
- Simulator-Abstürze und Startfehler,
- Wiederholungen wegen Infrastrukturfehlern,
- Zeit für Aufräumen und Neustart.
Der relevante Wert ist die effektive Abschlusszeit. Wenn mehr Worker zwar gleichzeitig starten, der gesamte Job aber länger dauert oder häufiger wiederholt werden muss, ist die zusätzliche Parallelität keine echte Kapazität.
Isolationsregeln für UI-Tests
- Wenn zusätzliche Worker die Laufzeit verkürzen und die Fehlerquote stabil bleibt, dann kann die interne Parallelität begrenzt eingesetzt werden.
- Wenn die Laufzeit ab einem Punkt steigt oder Simulatoren instabil werden, dann reduzieren Sie die Worker-Zahl und ergänzen unabhängige Testknoten.
- Wenn UI-Tests regelmäßig PR-Builds verdrängen, dann routen Sie sie über eigene Labels oder eine eigene Runner Group.
- Wenn Tests nur nachts oder vor Releases laufen, dann planen Sie ein eigenes Zeitfenster und temporäre Kapazität.
Die GitHub-Anleitung zur Verwendung von Labels und Runner Groups zeigt, wie Jobs gezielt an geeignete Runner geleitet werden. Eine Runner Group kann dabei eine organisatorische Grenze bilden; sie ersetzt aber keine Messung der realen Mac-Auslastung.
Signierung und Veröffentlichung
Archivierung, Signierung und Veröffentlichung sind oft seltene Aufgaben. Gerade deshalb wäre es riskant, ihre Kapazität ausschließlich aus der täglichen Durchschnittslast abzuleiten.
Ein Release-Job kann auf Schlüsselbund, Zertifikate, Provisioning-Profile, Arbeitsverzeichnisse und besondere Umgebungsvariablen zugreifen. Ein gemeinsam genutzter Runner kann nach einem fehlgeschlagenen Job einen veränderten Zustand hinterlassen. Das Problem ist dann nicht nur die belegte Zeit, sondern die Wiederherstellung und die Frage, ob ein blockierter Veröffentlichungsprozess den Liefertermin gefährdet.
Trennen Sie daher normale PR-Knoten und kontrollierte Veröffentlichungs-Knoten mindestens logisch. Nutzen Sie dafür eindeutige Labels und, wenn die Berechtigungsgrenzen es verlangen, eine eigene Runner Group. Die GitHub-Referenz zu Runner Groups beschreibt diese Steuerung.
Führen Sie anschließend einen vollständigen Archivierungs- und Signierungslauf über genau die vorgesehene Route aus. Messen Sie:
- Wartezeit bis zur Zuweisung,
- Archivierungsdauer,
- Signierungsfehler,
- Wiederherstellungszeit nach einem Abbruch,
- Verfügbarkeit des reservierten Knotens im Veröffentlichungsfenster.
Wenn ein Release-Job nur bei einem festen Termin erscheint, aber bei Blockierung hohe Folgekosten verursacht, dann reservieren Sie dafür Kapazität. Wenn Signierung und Veröffentlichungen unkritisch und vollständig reproduzierbar sind, dann kann ein begrenztes Teilen mit PR-Aufgaben vertretbar sein. Das muss durch einen Wiederherstellungstest belegt werden.
Für sensible Zertifikate sollten Sie zusätzlich die Zugriffsrechte, Protokollierung und Aufbewahrung prüfen. Ein Remote Mac mit Root-Zugriff ist technisch flexibel, verlangt aber klare Geheimnisverwaltung und eine zur DSGVO passende organisatorische Kontrolle. Der Runner sollte nicht mehr Zugriff auf Repositorys und Signaturmaterial erhalten, als der jeweilige Workflow benötigt.
Nachtlast und Release-Spitzen
Nächtliche Regressionstests und Versionsveröffentlichungen erzeugen eine andere Last als kontinuierliche PRs. Eine Pipeline kann im Alltag ausreichend wirken und dennoch zu einem bestimmten Termin eine lange Warteschlange aufbauen.
Ordnen Sie Ihre Aufgaben drei Gruppen zu:
- Sofortiges Feedback: PR-Builds und Prüfungen, deren Wartezeit direkt die Entwicklung bremst.
- Planbare Hintergrundlast: Regressionstests, vollständige Testmatrizen und periodische Qualitätsprüfungen.
- Zeitkritische Spitzenlast: Release-Kandidaten, Archivierung und Veröffentlichungen mit einem festen Termin.
Planbare Aufgaben können Sie in ein Zeitfenster verschieben oder über eine eigene Concurrency-Regel begrenzen. Zeitkritische Aufgaben benötigen dagegen eine Kapazitätszusage im betreffenden Fenster. Die GitHub-Dokumentation zur Workflow-Syntax ist die passende Referenz, um Filter, Bedingungen und Workflow-Regeln nachvollziehbar zu konfigurieren.
Auswahl zwischen festen und temporären Knoten
- Wenn die zusätzliche Last an jedem Arbeitstag auftritt und die Zielwartezeit dauerhaft verfehlt wird, dann spricht das für langfristig zusätzliche Mac Runner.
- Wenn die Last nur bei nächtlichen Regressionen auftritt, dann prüfen Sie zuerst Zeitplanung und parallele Testfenster.
- Wenn die Nachfrage an Releases gebunden ist, dann sind kurzfristig gemietete Remote Macs eine geeignete Testoption.
- Wenn ein Ausfall eines einzelnen Knotens den Veröffentlichungsprozess stoppt, dann benötigen Sie eine separate Reserve, auch wenn die mittlere Auslastung niedrig ist.
- Wenn Aufgaben keinen festen Termin haben, dann darf die Warteschlange länger sein als bei PR- oder Release-Aufgaben.
Die KVMNODE-Übersicht für Remote-Mac-Zugänge kann als Ausgangspunkt dienen, wenn Sie kurzfristige macOS-Kapazität gegen eine eigene Hardwarebeschaffung abgrenzen möchten. Entscheidend ist nicht ein pauschaler Mietzeitraum, sondern ob die zusätzliche Kapazität exakt in Ihr gemessenes Lastfenster passt.
Entscheidungswerkzeug für die Knotenzahl
Verwenden Sie diese Checkliste nach einer vollständigen Messperiode. Markieren Sie jeden Punkt, der auf Ihre Umgebung zutrifft. Die jeweils eingerückte Konsequenz ist die nächste konkrete Maßnahme.
[ ] PR-Wartezeit bleibt innerhalb des vereinbarten Zielwerts, und ein Runner-Ausfall gefährdet keine zeitkritische Veröffentlichung.
Entscheidung: Bestand zunächst beibehalten und die Entwicklung weiter beobachten.[ ] Überholte PR-Jobs, doppelte Prüfungen oder nicht notwendige macOS-Schritte belegen einen relevanten Teil der Runner-Zeit.
Entscheidung: Workflow-Optimierung vor einer Erweiterung durchführen. Nutzen Sie Concurrency-Regeln und verschieben Sie plattformunabhängige Schritte.[ ] PR-Jobs überschreiten auch nach der Bereinigung wiederholt die akzeptierte Wartezeit.
Entscheidung: Den Grundpool langfristig erweitern, weil die Unterversorgung nicht nur durch einzelne Fehlkonfigurationen entsteht.[ ] UI-Tests erhöhen bei mehr Test-Workern die effektive Laufzeit oder die Fehlerquote.
Entscheidung: Interne Parallelität begrenzen und unabhängige Testknoten vorsehen. Worker sind kein Ersatz für zusätzliche Runner.[ ] UI-Tests verdrängen PR-Builds, treten aber nur nachts oder vor Releases auf.
Entscheidung: Testaufgaben über eigene Labels oder eine Runner Group trennen und zunächst kurzfristige Kapazität für das betroffene Zeitfenster testen.[ ] Signierung, Schlüsselbundzustand oder Wiederherstellung sind auf einem gemeinsam genutzten Runner nicht nachgewiesen.
Entscheidung: Eine geschützte Release-Reserve einrichten und die Route mit einem vollständigen Archivierungslauf prüfen.[ ] Die Unterversorgung tritt ausschließlich bei einem planbaren Release- oder Regressionstermin auf.
Entscheidung: Kurzfristig zusätzliche Remote-Mac-Kapazität für diesen Zeitraum mieten, statt den gesamten Grundpool dauerhaft nach dem Spitzenwert zu dimensionieren.[ ] Ein Ausfalltest zeigt, dass kein passender Runner den kritischen Auftrag rechtzeitig übernehmen kann.
Entscheidung: Ausfallreserve ergänzen, auch wenn diese im Normalbetrieb selten genutzt wird.[ ] Die bereinigte Last bleibt über mehrere vergleichbare Zeitfenster hoch und verfehlt dauerhaft die Zielwartezeit.
Entscheidung: Langfristig weitere Grundknoten einplanen. Eine reine Terminverschiebung löst dann den strukturellen Engpass nicht.
Diese Liste trennt vier Entscheidungen: Grundkapazität, Testkapazität, Release-Schutz und Ausfallreserve. Sie verhindert damit, dass interne Test-Worker fälschlich als vollwertige zusätzliche Runner gezählt werden.
Kapazitätstest in kontrollierten Schritten
Bevor Sie eine langfristige Entscheidung treffen, bauen Sie einen kleinen Versuch mit realen Workflows auf. Verwenden Sie keine synthetische Build-Aufgabe, wenn die Engpässe in Signierung, Simulatorstart oder Abhängigkeiten liegen.
- Workflows gruppieren: Trennen Sie PR-Builds, UI-Tests, vollständige Regression, Archivierung und Veröffentlichung.
- Historie erfassen: Exportieren oder protokollieren Sie Ankunftszeit, Wartezeit, Laufzeit, Ergebnis und Wiederholungen je Gruppe.
- Ressourcen beobachten: Erfassen Sie während der Jobs Prozessorlast, Arbeitsspeicherdruck, freien Speicher und Simulatorfehler.
- Routing prüfen: Vergeben Sie eindeutige Labels für Build-, Test- und Release-Aufgaben und kontrollieren Sie die tatsächliche Runner-Zuweisung.
- Parallelität schrittweise erhöhen: Verändern Sie nur eine Kapazitätsvariable gleichzeitig. So erkennen Sie, ob ein zweiter Runner oder ein zusätzlicher Test-Worker den Effekt verursacht.
- Fehlerwiederherstellung testen: Stoppen Sie einen Test- oder Build-Knoten kontrolliert und messen Sie, wann ein anderer Knoten den Auftrag übernehmen kann.
- Spitzenfenster auswerten: Vergleichen Sie normale Arbeitszeiten mit konzentrierten PR-Phasen, nächtlichen Testläufen und Veröffentlichungen.
- Entscheidung dokumentieren: Halten Sie Grundknoten, Testknoten, Release-Reserve und Ausfallreserve getrennt fest.
Als Ergebnis sollten Sie vier Rollen ausweisen:
- Grundknoten: kontinuierliche PR- und macOS-spezifische Prüfungen.
- Testknoten: Simulator- und UI-Testlast mit kontrollierter interner Parallelität.
- Release-Reserve: geschützte Kapazität für Archivierung und Signierung.
- Ausfallreserve: ein Ersatzpfad für einen nicht verfügbaren oder verschmutzten Runner.
Nicht jede Rolle benötigt zwingend einen eigenen physischen Mac. PR-Builds und leichte Prüfungen können sich einen Pool teilen, wenn Labels, Laufzeiten und Berechtigungen passen. UI-Tests sollten nur dann mit normalen Builds konkurrieren, wenn die Messung keine relevante Beeinträchtigung zeigt. Release-Aufgaben verdienen eine getrennte Route, sobald Schlüsselbundzustand, Wiederherstellung oder Liefertermine kritisch sind.
Die passende Mac-Strategie
Ein eigener Mac mini kann für eine konstante, langfristige Grundlast sinnvoll sein. Die Beschaffung bindet jedoch Kapital, benötigt Wartung und lässt sich bei einem kurzfristigen Release-Peak nicht schnell anpassen. Ein lokaler Mac als einziger Runner ist außerdem ein einzelner Ausfallpunkt, wenn keine Ersatzroute eingerichtet ist. Einen Überblick über eine mögliche Mac-mini-Beschaffung für Entwicklungsaufgaben können Sie getrennt von der CI-Kapazitätsplanung prüfen.
Ein Linux- oder Windows-Runner bleibt für plattformunabhängige Schritte nützlich, ersetzt aber keinen macOS-Knoten für Xcode, Signierung und Simulator-Tests. Virtuelle oder nicht unterstützte macOS-Konstruktionen bringen zusätzliche Stabilitäts-, Wartungs- und Compliance-Fragen mit sich. Sie sind daher keine belastbare Standardlösung für einen langfristig kritischen Veröffentlichungsweg.
Wenn Ihr aktueller Bestand nur bei Spitzenlasten versagt, zugleich aber die täglichen PRs ausreichend verarbeitet, ist ein dauerhaft größerer Pool wahrscheinlich überdimensioniert. KVMNODE ermöglicht in diesem Fall, einen Remote Mac zunächst für das gemessene Fenster zu mieten und die Wirkung anhand derselben Wartezeit-, Laufzeit- und Fehlerdaten zu prüfen. Das ist gegenüber einer sofortigen Hardwarebindung besonders dann sinnvoll, wenn die Release-Frequenz oder Teamlast noch schwankt.
Beginnen Sie mit einer echten Aufzeichnung von PR-, UI-Test- und Veröffentlichungsfenstern. Zeigt die Auswertung eine wiederkehrende Unterversorgung, erweitern Sie gezielt den betroffenen Pool; zeigt sie nur eine kurze Spitze, testen Sie zusätzliche Remote-Mac-Kapazität für diesen Zeitraum und entscheiden erst danach über eine langfristige Knotenanzahl.