Vom Anfänger zum CI/CD-Profi: unser 10-Jahres Résumé

9 September 2024

CI/CD ist ein vertrautes Thema für uns; wir haben es in Videos und Präsentationen beleuchtet. Als ich mich daran machte, diesen Beitrag zu schreiben, fragte ich mich also: Welche neuen Perspektiven können wir anbieten, die wir noch nicht behandelt haben?

Wie sich herausgestellt hat, haben wir noch einiges mehr mitzuteilen. In diesem Beitrag möchte ich auf einige der Erkenntnisse eingehen, die wir in einem Jahrzehnt der Arbeit mit CI/CD-Systemen gewonnen haben. Aber zuerst eine kurze Zusammenfassung:

CI/CD

CI/CD kann zwei Bedeutungen haben: Continuous Integration/Continuous Delivery und Continuous Integration/Continuous Deployment.

Bei der Continuous Integration wird die gesamte Arbeit, die alle Entwickler beim Schreiben von Code leisten, automatisch an einer Stelle gesammelt. Die Idee ist, dass die Entwickler ihre Änderungen in ein zentrales Repository einbringen, wo Builds und Tests durchgeführt werden, um sicherzustellen, dass diese Änderungen alle zusammen funktionieren. Durch die kontinuierliche Überprüfung, ob der neue Code mit dem vorhandenen Code harmoniert, können Probleme frühzeitig erkannt und behoben werden, wodurch das Endprodukt besser und der Prozess effizienter wird.

Continuous Delivery ist eine Praxis, bei der Teams Software in kurzen Zyklen produzieren, um sicherzustellen, dass die Software jederzeit zuverlässig releast werden kann. Auf diesem Weg müssen Sie nicht lange warten, um neue Funktionen Ihren Benutzern zur Verfügung zu stellen. Das bedeutet, dass das CD-System, nachdem die Entwickler die Entwicklung und das Testen ihrer Funktionen abgeschlossen haben, dafür sorgt, dass diese Änderungen automatisch vorbereitet werden und den Benutzern jederzeit zur Verfügung gestellt werden können. Es macht alles, außer den großen roten Knopf zu drücken.

Beim Continuous Deployment werden Softwarefunktionen häufig und durch Automatisierung deployed. Sobald ein Entwickler eine neue Funktion oder Korrektur fertiggestellt und getestet hat, wird sie automatisch und ohne manuelle Eingriffe für die Benutzer bereitgestellt. Mit anderen Worten, es wird der große rote Knopf gedrückt, ohne dass ein Mensch auf die Freigabe warten muss.

Unabhängig von der Definition handelt es sich um einen Prozess, der darauf abzielt, die Art und Weise zu verbessern, wie wir Software automatisiert den Benutzer zur Verfügung stellen. Kommen wir nun zu unseren gewonnenen Erkenntnissen;

Konfiguration

Halten Sie Ihre Workflows relativ klein

Anfangs wird die Pipeline eines neuen Projektes klein sein, aber sie wird stetig größer werden, wenn neue Funktionen hinzugefügt werden. Zu Beginn ist es in Ordnung, alles in der Konfigurationsdatei der Pipeline zu belassen, aber wenn sie wächst, werden Sie Teile aus der Pipeline-Datei herausnehmen wollen.

Wir raten Ihnen, separate Skripte zu erstellen, die einen Teil der Schritte ausführen, und diese Skripte dann in der Konfigurationsdatei aufzurufen. Ein guter Ansatz ist es, die Pipeline-Konfiguration als Teil der Codebasis zu betrachten, sodass alle Regeln, die Sie auf den Code anwenden, auch für die Konfigurationsdatei gelten. Wenn Ihre Konfigurationsdatei zu groß wird, sollten Sie diese refaktorisieren und einige Teile in separate Skripte auslagern.

Dies wird besonders wichtig, wenn man anfängt, bedingte Logik in die Pipeline einzubauen. Wenn man alles in einer Konfigurationsdatei belässt, wird diese schwer lesbar und pflegbar sein. Außerdem sind sehr große Konfigurationsdateien schwieriger zu migrieren, wenn Sie den CI/CD-Anbieter wechseln wollen – ein weiterer Grund, es zu vermeiden.

Dies ist nicht der Wilden Westen, benutzen Sie Container

Stelle sicher, dass die Umgebungen für die Entwicklung, die Tests und die Produktion identisch sind. Software wie Docker ist hier ein Geschenk des Himmels, denn es ermöglicht es, in allen Phasen dieselbe Umgebung zu verwenden.

Sie wollen nicht, dass ein Test in der Entwicklung erfolgreich durchläuft, aber in der Pipeline fehlschlägt, oder noch schlimmer, in der Pipeline fehlschlägt, aber lokal erfolgreich ist.

Seien Sie vorsichtig beim Continuous Deployment

Continuous Deployment von CI/CD kann ein zweischneidiges Schwert sein, wenn man nicht aufpasst. Es bedeutet, dass die Bereitstellung automatisiert ist. Wenn zum Beispiel etwas in einen Release-Branch übertragen wird, geht es automatisch in Betrieb. In der Theorie ist das gut, aber in der Praxis kann es zu Problemen führen. Vor allem, wenn man es mit ignorierten CI/CD-Pipeline-Warnungen und der menschlichen Neigung, Fehler zu machen, kombiniert, insbesondere wenn man unter Druck steht.

Eine Ausnahme von dieser Regel ist die kontinuierliche Bereitstellung auf nicht produktiven Systemen, z. B. auf einem Testserver, auf dem Benutzer spielen können. In diesem Fall ist es großartig und wir empfehlen es, denn selbst wenn etwas schiefgeht, ist der Schaden minimal.

Leistung

Warten nervt

Wenn man Software entwickelt, können lange Verzögerungen einen aus der Ruhe bringen und die Kreativität beeinträchtigen. Wenn man z. B. 30 Minuten auf einen Build auf dem Testserver warten müssen, verliert man die Konzentration, vor allem wenn man während der Wartezeit zu einer anderen Aufgabe übergeht.

Der Tipp lautet also, sich Zeit zu nehmen und darüber nachzudenken, wie die Pipeline optimiert werden kann. Dabei geht es nicht nur darum, dass die Tests so effizient wie möglich ablaufen, sondern auch darum, ob sie überhaupt ausgeführt werden.

Nicht alles, was ausgeführt werden kann, sollte auch ausgeführt werden. Einige Tests sollten beispielsweise nur beim Mergen in den Main-Branch ausgeführt werden, oder wenn ein Teil der Anwendung ordnungsgemäß isoliert ist, sollten die Tests nur ausgeführt werden, wenn es in diesem Teil eine Änderung gibt.

Allerdings gibt es eine Einschränkung: Geschwindigkeit ist nicht alles. Optimierungen, die nur ein paar Millisekunden einsparen, sind reine Zeitverschwendung; suchen Sie lieber nach Engpässen, die die Leistung um Größenordnungen steigern. Irgendwann ist der Nutzen so klein, dass sich der Optimierungsaufwand nicht lohnt oder in keinem annehmbaren Verhältnis zum Aufwand steht, und dann ist es besser, die Zeit für etwas anderes zu nutzen.

Kosten

Wir haben dies bereits im Video erwähnt, aber es lohnt sich, es zu wiederholen. Achten Sie auf die Kosten. Im Video haben wir gesagt, dass die Kosten für CI/CD-Lösung in Stunden, Euro oder beidem gemessen werden können. Das ist immer noch so, also muss man darauf achten, wie viel man tatsächlich an Zeit oder Geld ausgeben will.

CI/CD-Pipelines können sehr schnell ausgesprochen teuer werden, also sollte man sicherstellen, dass sie einem nicht die Haare vom Kopf fressen.

Der Tipp hier ist, darauf zu achten, wie viel man zahlt, in Euro oder in Zeit. Es ist einfacher, dies früher zu tun als später, vor allem, wenn mehrere Entwickler an dem Projekt arbeiten.

Ein weiterer Punkt, den man beachten sollte, ist das Zahlungsmodell, d. h. Bezahlung pro Nutzung oder begrenzte Parallelität. Beide Modelle haben Vor- und Nachteile, aber wenn ich sie zusammenfassen sollte, wäre es der Unterschied zwischen unbegrenzten Kosten und unbegrenzter Wartezeit. Analysieren Sie Ihre Nutzung und wählen Sie dann, was am besten für Sie funktioniert.

Tests, Warnungen und Fehler

Stellen Sie sicher, dass die Pipeline fehlschlägt

Ich weiß, das mag seltsam klingen, aber Pipelines sind ähnlich wie Unit-Tests: Sie müssen erfolgreich und laut scheitern. Eine Pipeline, die in jeder Situation erfolgreich ist, ist sinnlos. Die Tests müssen etwas testen, das schiefgehen kann. Wenn der Code nicht gelinted ist, muss die Pipeline fehlschlagen. Wenn ein Testfall fehlschlägt, muss die Pipeline fehlschlagen. Wenn ein Artefakt nach einem Build fehlt, muss die Pipeline fehlschlagen!

Stellen Sie sicher, dass die CI/CD fehlschlägt, wenn nötig. Es ist eine gute Idee anfangs zu testen, ob sie tatsächlich fehlschlägt, indem man sie mit verschiedenen Fehlerszenarien konfrontiert.

Ein weiterer Punkt, auf den man achten sollte, ist, wenn die Pipeline zufällig fehlschlägt. Dies ist ein Zeichen von Unbeständigkeit und sollte als kritischer Fehler behandelt und sofort behoben werden. Unbeständigkeit ist ein großes Problem, da sie zu Selbstgefälligkeit führt, die wiederum größere Probleme nach sich zieht. Wenn Sie aus diesem Beitrag nur etwas mitnehmen, dann hoffentlich, dass Sie die Unbeständigkeit nicht ignorieren.

Umgang mit Warnungen

Warnungen sind ein Zeichen dafür, dass etwas nicht ganz richtig ist. Natürlich kann man CI/CD-Warnungen ignorieren, aber daran gewöhnen sollte man sich nicht. Kümmern Sie sich um die Warnungen, sobald sie auftauchen. Wenn Sie sie beheben können, dann tun Sie es.

Wenn dies jedoch nicht möglich ist und es sich nicht um eine projektbedrohende Warnung handelt, dann schalte sie stumm. Ich schlage hier kein pauschales „Stummschalten“ vor, sondern einen eher chirurgischen Ansatz. Das mag umstritten erscheinen, aber es gibt einen guten Grund dafür.

CI/CD-Protokolle werden zum Debuggen von Problemen verwendet. Unnötige Warnungen verunreinigen die Logs und lenken von diesem Ziel ab. Im besten Fall verlangsamen sie die Arbeit, im schlimmsten Fall sind sie eine Ablenkung, bei der man stundenlang auf der falschen Fährte ist.

Wenn Sie also die Möglichkeit haben, beheben Sie die Warnungen, wenn nicht und sie optional sind, dann schalten Sie diese aus.

Unnötige Tests vermeiden

Ein nutzloser Test ist ein Test zu viel. Das soll nicht heißen, dass der Test selbst nicht wert ist betrachtet zu werden, sondern vielmehr, wie dieser gehandhabt wird. Man kann zum Beispiel einen Test haben, der die Software-Paketgröße testet. Das ist ein guter Test, um sicherzustellen, dass Software-Pakete nicht zu groß werden. Wenn ein Entwickler aber jedes Mal, wenn er auf ein Software-Paketproblem stößt, einfach das Limit erhöht, anstatt daran zu arbeiten, die Größe zu verringern, dann ist es sinnlos.

Wenn Sie die Tests nicht einhalten wollen, dann lassen Sie diese einfach weg. Ein weiteres Beispiel ist ein Test, der die Abdeckung prüft, aber anstatt Tests hinzuzufügen, um die Abdeckung zu erhöhen, reduzieren die Entwickler die Anforderungen.

Mit anderen Worten...

Nehmen Sie die CI/CD ernst

Ignorieren Sie sie nicht, setzen Sie sie nicht außer Kraft. Wenn etwas kaputtgeht, setzen Sie sie nicht außer Kraft und merge dann trotzdem. Das ist ein schneller Weg zu einem fehlerhaften Produkt.

Fehler-Suche und -Behebung

„Catch the Cache“

Beim Build-Vorgang einer Pipeline speichert der Anbieter aus Effizienzgründen in der Regel einige Anfragen im Cache. So führt man nicht jedes Mal, wenn ein Build startet, all diese Anfragen aus. Wenn man das täte, wäre die Internetrechnung der Anbieter unangemessen hoch. Daher werden einige dieser Anfragen zwischengespeichert und nur bei Bedarf neu abgerufen.

Wenn die Schnittstelle gut ist, kann man selbst festlegen, welche Anfragen ausgeführt werden sollen und was die Bedingungen für die Aktualisierung sind. Zum Beispiel wird yarn install oder npm install nur ausgeführt, wenn sich die package.json ändert.

Das hört sich großartig an, bis man auf ein Problem stößt, bei dem das Problem ein alter Cache ist, der nicht aktualisiert wurde.

Dies ist keine Abrechnung mit dem Caching, sondern eher das Gegenteil. Wir lieben Caching und empfehlen, es großzügig einzusetzen, aber seien Sie auch immer bewusst, dass Sie cachen. Wenn etwas ohne Grund kaputtgeht, sollte man zuerst im Cache nachsehen.

Lernen Sie die Automatik lieben

Es kommt vor, dass eine ordnungsgemäß eingerichtete Pipeline erfolgreich durchläuft, der Produktions-Build jedoch fehlschlägt, oder dass sie zwar erfolgreich ist, das Live-System jedoch wie durch Zauberhand nicht läuft. Dies könnte zum Beispiel daran liegen, dass man vergessen hat, einige manuelle Schritte durchzuführen, die im Prozess erforderlich sind, wie das Erstellen von Migrationen in Django oder das Aktualisieren der API, die das Frontend zur Generierung seiner Schnittstelle verwendet.

Die Ursache ist irrelevant, aber wichtig ist, dass in diesen Fällen, wenn es einmal passiert ist, die Wahrscheinlichkeit groß ist, dass es wieder passieren wird. Der erste Impuls könnte sein, das Problem zu beheben und es zu vergessen, schließlich dauert es ja nur 5 Minuten, um es zu beheben, oder?

Das ist ein schlechter Impuls, den man rücksichtslos unterdrücken sollte.

Der Tipp hier ist, dass man diesen Schritt entweder automatisieren oder eine Kontrolle dafür einrichten muss, damit er nie wieder auftritt. Das mag übertrieben erscheinen, aber bedenke, dass, wenn Sie das Problem hatten, auch andere darauf stoßen werden. Das Hinzufügen zur Pipeline dient als Dokumentation für den nächsten Entwickler oder für Sie selbst, Monate später.

Fazit

Die Erkenntnisse, die wir in diesem Beitrag geteilt haben, sind nur ein Bruchteil des Wissens, das wir gewonnen haben. Aber wenn wir versuchen würden, alles auf einmal zu schreiben, würden wir ein Buch schreiben und nicht einen Blogbeitrag. Da sich die Technologien weiterentwickeln, werden auch unsere Ansätze und Strategien sich weiterentwickeln, sodass wir in Zukunft sicherlich einen zweiten Blogbeitrag schreiben werden.

Wollen Sie Ihre CI/CD auf die nächste Stufe heben? Rufen Sie uns an, um zu besprechen, wie wir Sie auf Ihrer eigenen CI/CD-Reise unterstützen können. Schließlich ist der Weg leichter zu gehen, wenn Sie von jemandem geführt werden, der ihn bereits gegangen ist.

djangsters GmbH

Vogelsanger Straße 187
50825 Köln

Sortlist