VPSSpark CI-Queue-Diagnose-Standard (Cloud-Mac-CI #2). Lesereihenfolge: Hook → Formel → Symptome → Failure Model → Hard Rules → Runbook → FAQ. Verwandt: #1 Kapazität · #5 Skalierungs-Incident · #3 Self-Hosted-TCO · #8 Build-Speed.
1 · Hook: der überraschende Befund
Bei den meisten macOS-CI-queued-Vorfällen fehlt nicht „noch ein Mac“—auf dem PR-Pfad läuft L2 (Archive). In der Praxis trifft das auf gut neun von zehn Tickets zu.
In Slack heißt es schnell „CI ist langsam“. In GitHub Actions sind Queued und In progress aber verschiedene Metriken. Ohne die Frage „dominiert Wartezeit die Laufzeit?“ landet man bei Xcode-Upgrades oder mehr Abrechnungsminuten—beides löst keine Runner-Warteschlange. Dieser Artikel ist die Norm für genau diese Trennung.
2 · Kern: eine Formel
Alles Folgende entfaltet diese eine Prüfung. In euer On-Call-Wiki kopieren.
Master-Formel
CI queue problem ⇔ wait time >> run time
Technische Lesart: macOS runner queued bedeutet Sättigung des Runner-Pools, nicht langsameres Xcode-Compilen.
Formel false → nicht dieser Artikel; #8 (Xcode/Cache). Formel true → Failure 3 Layer Model und CI Hard Rules.
Viele DACH-Teams mischen macos-latest mit Self-Hosted und wundern sich über „Minuten übrig, trotzdem Queued“. Dahinter steckt fast immer die Verwechslung von minutes (Abrechnung) und concurrency (gleichzeitige Slots). Nur bei true an Pool- und Trigger-Design drehen.
3 · Symptom: Queued ≠ Running
Bei GitHub Actions heißt Queued: Job ist im Workflow, aber noch kein Runner-Slot. Unter In progress laufen Checkout, xcodebuild und Signing. Ein roter PR über eine Stunde wird als „langsamer Build“ gemeldet—in der Timeline steht oft 52 Minuten Warten, 11 Minuten Laufen.
Typische Fehlfixes: Xcode bumpen, timeout-minutes erhöhen, mehr GitHub-Minuten kaufen. Queued-Zeit zählt oft nicht in das Timeout, das ihr meint. Timeout allein entleert die Queue nicht.
Messen mit Job-Ausführungszeit (queue_wait_seconds vs. Laufzeit). Wöchentliches P95 zeigt Trigger Explosion vor dem Freitags-Merge-Rush.
| Wartezeit | Laufzeit | |
|---|---|---|
| UI | Queued | In progress |
| Engpass | GitHub Actions macOS runner queue / self-hosted runner queue | Xcode · Signing · Upload |
| Falscher Fix | mehr Minuten · neues Xcode | Caching (→ #8) |
Wenn im Team „DerivedData“ fällt, obwohl die Badge lange Queued zeigt, liegt die Beobachtung in der falschen Phase. Im Runbook Warte- und Laufzeit getrennt loggen—sonst wiederholt sich derselbe Fehlkauf.
4 · Erklärung: CI Queue Failure 3 Layer Model
Bei wait time >> run time liegt eine (oder mehrere) dieser SRE-Schichten vor.
| Layer | Bedeutung | Signale | Heute |
|---|---|---|---|
| Capacity Limit | Plattform · macos-latest |
Nur Hosted macOS runner queued; Minuten ≠ Concurrency | Fanout reduzieren; Archive von Hosted weg → #3 |
| Pool Misdesign | Architektur · Self-Hosted | Archive auf PR; fast/archive geteilt; ein Runner blockiert alle | Hard Rules → #1 #6 |
| Trigger Explosion | Last · Workflow-Fanout | matrix / paths / doppelte Workflows; Jobs > Runner | Trigger straffen → #5 |
Capacity Limit — trifft gehostete macOS-Runner und das Org-macOS-Concurrency-Cap (Limits). Pool Misdesign — häufige Wurzel: L2 auf PR, gemischte Pools. Trigger Explosion — YAML fixen, nicht Hardware. (Failure-Layer ≠ Job-Tiers L0/L1/L2.)
Die drei Layer schließen sich nicht aus: Freitagabend mehr Matrix (Trigger), Archive blockiert fast (Pool), Hosted-Kontingent leer (Capacity)—das „Triple“ sieht man im 20-Personen-Fall #5 regelmäßig. An der Signale-Spalte anfangen.
5 · Fix: CI Hard Rules (MUST NOT verletzen)
Normative Sprache fürs Runbook—keine Empfehlungen. Verstöße = Incident.
Rule 1: PR MUST NOT run L2 Rule 2: L2 MUST run on isolated pool (macos-archive) Rule 3: fast pool MUST remain unblocked (fast ≠ archive) # Mapping PR → L0 + L1 only →macos-fastmain → L2 only →macos-archive
Job-Tier-Referenz (nur Umsetzung der Hard Rules):
| Tier | Arbeit | Pool | Regeln |
|---|---|---|---|
| L0 | Modul-Build, Lint, leichte Tests | macos-fast |
Rule 1 · PR OK |
| L1 | PR-Integration, Simulator-Tests | macos-fast |
Rule 1 · MUST NOT Archive |
| L2 | Archive, IPA, TestFlight | macos-archive |
Rules 2+3 · PR MUST NOT |
„Nur einmal Archive auf dem PR“ wirkt harmlos—38 Minuten L2 auf einem Label halten alle L0/L1 in Queued. Ausnahmen zerstören Pool-Design; Release-Jobs auf main / Schedule legen.
Abb. 1 · Pool Misdesign: L2 hält Slot → alle macOS-Jobs queued
jobs: pr-fast: if: github.event_name == 'pull_request' runs-on: [self-hosted, macos-fast] release-archive: if: github.ref == 'refs/heads/main' || github.event_name == 'schedule' runs-on: [self-hosted, macos-archive]
Runner-Topologie: Elastic vs. Always-on · #1 Sizing · nach gesunder Queue → #3.
6 · Runbook: eine Seite (On-Call)
0. CI queue problem ⇔ wait time >> run time ? ─No→ #8
1. Layer: Capacity | Pool Misdesign | Trigger Explosion
2. MUST: Rule1 PR no L2 · Rule2 L2 isolated · Rule3 fast unblocked
3. PR workflow has no archive/export/upload ?
4. wait P95 < 8min → then size runners (#3)
Einzeiler: Die meisten macOS-CI-queued-Fälle sind L2 auf dem PR-Pfad—not fehlende Hardware. macOS runner queued = Pool-Sättigung; wait >> run, dann Failure Model, dann Hard Rules.
Postmortems mit „wir haben Runner gekauft“ ohne Rule 1–3 im Repo wiederholen das Muster. PR-Template-Checkbox „kein Archive-Job auf PR“ senkt die Rückfallrate spürbar.
7 · FAQ
Warum queuen macOS-Runner öfter?
Capacity Limit (Concurrency-Cap) plus Pool Misdesign (L2 auf PR). Start mit wait >> run.
Queue-Problem oder langsamer Build?
CI queue problem ⇔ wait time >> run time. true → Pool; false → #8.
Warum queued trotz Self-Hosted?
Pool Misdesign: self-hosted runner queue folgt Labels und Pool-Layout. Hard Rules brechen die Queue—Cloud Mac repariert kein YAML.
GitHub Actions Minuten vs. Concurrency?
minutes = Abrechnung; concurrency = gleichzeitige Slots. Mehr Minuten fixen macOS runner queued nicht.
Ist es ein Runner-Pool-Problem?
wait >> run + ein Self-Hosted lange busy → Pool Misdesign; nur macos-latest queued → Capacity Limit. Siehe Runbook.
Queue OK, Build trotzdem langsam?
#8 (Speed). Sizing: #1. Teamwachstum: #5.
Pool-Split validieren: Fast-Pool-PoC nötig?
Nach den Hard Rules: L0/L1 aus der gehosteten GitHub Actions macOS runner queue mit einem macos-fast-Runner und wait time P95 < 8 min verifizieren, dann macos-archive gemäß #1.
Für einen täglichen isolierten Fast-Pool ohne Büro-Netzwerk-Umbau: Mac-Cloud-Pläne oder VPSSpark Start—nur Topologie-Validierung; Regeln bleiben Pflicht. TCO: Serie #3.