Text size
Ausprobiert & getestet6 Min. Lesezeit

Schnellere CI-Pipelines: von 40 Minuten bis 8 Minuten

Die Caching- und Split-Tricks, die den größten Unterschied machen.

Faster CI pipelines: from 40 minutes to 8
KI-generierte Illustration

Eine langsame Pipeline kostet mehr als Rechenzeit. Entwickler wechseln während des Warten zu etwas anderem, verlieren den Fokus, stapeln Änderungen, um nicht wieder zu warten, und beginnen sich mit "es wird wahrscheinlich vorbei gehen" zu verschmelzen. Eine 40-minütige Pipeline macht alles ruhig schlimmer: größere Änderungen, langsamere Überprüfungen, mehr Risiko.

Die meisten Projekte können ihre Pipeline-Zeit von etwa vierzig Minuten auf weniger als zehn Minuten verkürzen. Hier sind die Techniken, die den größten Unterschied machen, in der Reihenfolge, in der ich sie ausprobieren würde.

Die langsamen Teile finden

Optimieren Sie nicht blind. Erstens:

  • Schau dir die Dauer der einzelnen Aufgaben und Schritte in den letzten Wochen. GitHub Actions, GitLab und die meisten CI-Tools zeigen das.
  • Finden Sie die kritischer Pfad: die Kette der Arbeitsplätze, die die Gesamtzeit bestimmt. Eine Arbeit, die parallel zu einer langsameren läuft, zu beschleunigen, ändert nichts.
  • Überprüfen Sie, wie viel Zeit in Einrichtung: Installation von Tools, Herunterladen von Abhängigkeiten, Abrufen von Bildern. Es ist oft ein überraschend großer Anteil.

Normalerweise dauert es die meiste Zeit drei oder vier Schritte. Konzentriere dich dort.

Cache alles, was Cache werden kann

Der größte Gewinn für die meisten Pipelines.

Abhängigkeits-Cache. Paket-Downloads (npm, pip, Maven, Go-Module) sollten nicht bei jedem Lauf von Grund auf neu erfolgen. Die meisten Setup-Aktionen haben eine eingebaute Cache-Option, die in der Schließdatei eingegeben ist:

- uses: actions/setup-node@<sha> # v4
  with:
    node-version: 22
    cache: npm

Caching der Docker-Schicht. Mit BuildKit, Cache-Schichten zwischen Ausführungen, im Cache des CI-Anbieters oder in einer Registrierung:

- uses: docker/build-push-action@<sha> # v6
  with:
    cache-from: type=registry,ref=ghcr.io/my-org/shop-api:buildcache
    cache-to: type=registry,ref=ghcr.io/my-org/shop-api:buildcache,mode=max

In Kombination mit einer gut geordneten Dockerfile (Dependenzen zuerst, Code zuletzt) fallen Bildbauten oft von vielen Minuten auf gut unter einen.

Bauen Sie Cache. Tools wie Gradle, Bazel, Nx und Turborepo können Builds speichern und Test-Ausgänge aus der Ferne durchführen, so dass unveränderte Module überhaupt nicht neu aufgebaut oder erneut getestet werden.

Die schnellste Arbeit ist die Arbeit, die Ihre Pipeline nicht wieder tun muss.

Parallel laufen

Viele Rohrleitungen laufen aus Gewohnheit aus Schritte nach Schritt. Suchen Sie nach selbständiger Arbeit:

  • Lint, Einheitstests und Sicherheitsscans können normalerweise ausgeführt werden gleichzeitig.
  • Verwenden Sie eine Matrix mehrere Versionen oder Komponenten parallel zu testen.
  • Starten Sie den Bildbau, während langsamere Tests noch laufen, wenn Ihr Prozess es zulässt.

Spaltungen und Quarantäne von Schuppenteilen

Tests sind oft der längste Schritt. Zwei Techniken:

Testspaltung. Teilen Sie die Testsuite auf mehrere parallele Aufgaben auf, idealerweise basierend auf historischem Timing, so dass jeder Job ungefähr die gleiche Zeit in Anspruch nimmt. Viele Test-Frameworks und CI-Tools unterstützen dies entweder nativ oder mit kleinen Hilfswerkzeugen.

Flakey-Test-Quarantäne. Ein Versuch, der fehlschlägt, zwingt zufällig, die ganze Pipeline zu wiederholen. Das ist reiner Abfall. Verfolgen Sie schlaffe Tests, verschieben Sie sie zu einem separaten nicht-blockenden Job und beheben Sie sie mit einer Frist. Man muss nie einfach automatische Wiederholungen hinzufügen und es vergessen.

Frag auch: Muss jeder Test auf jedem Commit ausgeführt werden? Lange End-to-End-Suiten können auf merge to main oder nightly ausgeführt werden, während Pull-Anfragen eine fokussierte Untermenge ausführen.

Nur das laufen, was sich geändert hat

In Monorepos ist der größte Abfall, wenn man alles umbaut und erneut testet, um eine einseitige Veränderung zu erreichen:

  • Filter für die Bahn Auslöser für Jobs nur, wenn sich relevante Ordner ändern.
  • Nur betroffene Bauten mit Nx, Turborepo, Bazel oder Pants verwenden Sie das Abhängigkeitsdiagramm, um genau zu ermitteln, welche Projekte eine Änderung berührt.

Bessere Läufer

Manchmal ist die Maschine der Engpass:

  • Größere Läufer Die Kosten für die Erstellung von Daten mit mehr CPU und Speicher können insgesamt günstiger sein, wenn sie die Zeit erheblich verkürzen. Messen Sie die Kosten pro Pipeline, nicht die Kosten pro Minute.
  • Selbst gehostete ephemere Läufer, zum Beispiel mit Aktionen Runner Controller Auf Kubernetes, geben Sie Kontrolle über die Maschinengröße und halten Cache in der Nähe der Läufer. Sie sollen kurzlebig sein, ein Job pro Läufer, zur Sicherheit.
  • Schnellere Dienstleistungen für Drittanbieter Die meisten der neuen Systeme sind in der Regel mit einer besseren Caching-Einrichtung ausgestattet.

Kleine Gewinne, die sich summieren

  • Shallow Git-Klone (fetch-depth: 1Es sei denn, Sie brauchen eine Geschichte.
  • Vorgefertigte CI-Bilder mit Ihren Tools bereits installiert.
  • Abbrechen veralteter Laufzeiten, wenn ein neuer Commit auf denselben Branch geschoben wird (concurrency mit cancel-in-progress).
  • Man entfernt Schritte, die niemand mehr anschaut.

Was ist ein gutes Ziel?

Unter zehn Minuten von einem Push bis zu einem grünen Check für eine Pull-Anfrage ist ein gutes Ziel für die meisten Dienste. Unter fünf ist fantastisch. Beginnen Sie mit Messungen, fügen Sie Caching hinzu, parallelisieren, behandeln Sie schmalen Tests, und Sie werden überrascht sein, wie viel Zeit verschwindet.

Meine Meinung: Die Pipeline-Geschwindigkeit als Merkmal. Jede Minute, die Sie sparen, wird von jedem Entwickler bei jedem Commit wieder gespeichert.

Desly