Best Practices für CI/CD

Continuous Integration, Continuous Delivery und Continuous Deployment sind Softwareentwicklungsmethoden, die aus der DevOps-Bewegung hervorgegangen sind. Durch sie wird das Kompilieren, Testen und Veröffentlichen von Code effizienter, sodass Sie schneller als mit herkömmlichen Methoden funktionsfähige Produkte für Ihre Benutzergemeinde bereitstellen können. Mit einer gut aufgestellten Build-Pipeline können Teams schneller funktionsfähige Software bereitstellen und zeitnahes Feedback zu den jeweils neuesten Änderungen erhalten.

Der Aufbau einer CI/CD-Pipeline ist jedoch keine einmalige Aufgabe, die man nach Abschluss zu den Akten legt. Genau wie bei der Entwicklung der eigentlichen Software lohnt es sich, den CI/CD-Workflow iterativ anzugehen: Analysieren Sie fortlaufend Ihre Daten und berücksichtigen Sie das erhaltene Feedback, um Ihren CI/CD-Prozess zu optimieren. In diesem Artikel betrachten wir einige Best Practices für Continuous Integration/Continuous Delivery, deren Einsatz auch bei Ihrer Pipeline sinnvoll sein könnte.

Früh und häufig Commits durchführen

Ein wesentlicher erster Schritt bei der Implementierung von Continuous Integration besteht darin, den gesamten Quellcode, Konfigurationsdateien, Skripte, Bibliotheken und ausführbare Dateien in einer Quellcodeverwaltung zu speichern. So können Sie jede Änderung nachverfolgen.

Das richtige Tool zu haben reicht jedoch nicht aus – entscheidend ist, wie Sie es einsetzen. Continuous Integration soll die Integration von Änderungen aus mehreren Quellen vereinfachen, indem häufiger kleinere Updates durchgeführt werden.

Jeder Commit löst eine Reihe von automatisierten Tests aus, die umgehend Feedback zu der Änderung geben. Durch regelmäßige Commits wird sichergestellt, dass Ihr Team auf denselben Grundlagen aufbaut. Dadurch wird die Zusammenarbeit erleichtert, und im Vergleich zur Integration großer, komplexer Änderungen verringert sich die Wahrscheinlichkeit lästiger Merge-Konflikte.

Um die Vorteile der Continuous Integration nutzen zu können, ist es wichtig, dass alle Mitwirkenden einerseits ihre Änderungen durch Commits in den Hauptbranch (Master) mit den anderen teilen und andererseits ihre lokalen Arbeitskopien aktualisieren, um die Änderungen der anderen zu erhalten. Als allgemeine Faustregel sollte mindestens ein Commit pro Tag in den Hauptbranch angepeilt werden.

Für Teams, die langes Arbeiten in Nebenbranches gewöhnt sind, können sich häufige Commits in den Hauptbranch unangenehm anfühlen. Dies kann daran liegen, dass jemand die kritischen Blicke der anderen fürchtet, aber auch daran, dass die Aufgabe einfach zu groß ist, um an einem Tag abgeschlossen zu werden.

Es ist entscheidend, eine Teamkultur zu schaffen, die Zusammenarbeit statt Kritik in den Mittelpunkt stellt. Wie bei jeder Änderung der Arbeitsmethoden lohnt es sich dabei, sich darüber auszutauschen, wie die Arbeit im Team funktioniert. Wenn sich das Team gemeinsam darum bemüht, Aufgaben in kleinere, eigenständige Teile zu gliedern, kann dies die Akzeptanz der Methode fördern.

Wenn langfristige Branches für neue Features eingesetzt werden, die noch nicht zur Veröffentlichung bereit sind, besteht die Alternative in der Verwendung von Feature-Flags. Mit diesen können Sie die Sichtbarkeit einzelner Features in verschiedenen Umgebungen steuern, sodass die Codeänderungen in den Build aufgenommen werden können, ohne dass sie für Endbenutzer*innen verfügbar sind.

Builds grün halten

Durch das Erstellen eines Builds und das Ausführen von automatisierten Tests bei jedem Commit bietet eine CI/CD-Pipeline schnelles Feedback zu den Änderungen des Entwicklerteams.

Das Ziel besteht darin, das Aufbauen auf einer fehlerhaften Grundlage zu vermeiden und den Code ständig Release-bereit zu halten. Es ist einerseits viel effizienter, Probleme nach ihrem Auftreten zeitnah zu beheben, und andererseits kann dadurch bei einem Fehler im Produktionseinsatz schneller ein Fix bereitgestellt werden.

Wenn ein Build aus irgendeinem Grund fehlschlägt, sollte es die Priorität des gesamten Teams sein, ihn wieder zum Laufen zu bringen. Es ist verlockend, die Schuld bei der Person zu suchen, die die letzte Änderung durchgeführt hat, und die gesamte Fehlerbehebung ihr zu überlassen. Schuldzuweisungen führen jedoch selten zu einer konstruktiven Teamkultur, und außerdem behindern sie die Suche nach der Grundursache des Problems. Indem Sie das gesamte Team daran beteiligen, einen fehlerhaften Build zu beheben und die Fehlerursache zu finden, können Sie den gesamten CI/CD-Workflow verbessern. Wenn das Team unter Druck steht und die Spannungen hochkochen, ist dies natürlich leichter gesagt als getan – auch der Aufbau einer DevOps-Kultur ist eine Übung in kontinuierlicher Verbesserung!

Sicherlich kann es frustrierend sein, alles stehen und liegen zu lassen, um einen Buildfehler zu beheben, nur um am Ende festzustellen, dass er durch etwas Triviales verursacht wurde – einen Syntaxfehler etwa oder eine fehlende Abhängigkeit. Um dies zu vermeiden, ist es eine gute Idee, wenn die Teammitglieder erst einen lokalen Build erstellen und eine erste Reihe von Tests ausführen, bevor sie ihre Änderungen mit den anderen teilen. Dabei sollte im Idealfall jeder dieselben Skripte wie das CI/CD-System verwenden können, um Doppelarbeit zu vermeiden. Überlegen Sie auch, ob Sie ein CI/CD-Tool in Ihrem Unternehmen einsetzen wollen.

Nur einen Build erstellen

Ein häufiger Fehler besteht darin, für jede Phase einen neuen Build zu erstellen.

Wenn für verschiedene Umgebungen jeweils ein neuer Build erstellt wird, können sich Inkonsistenzen einschleichen, und so kann man sich nie sicher sein, dass alle vorherigen Tests bestanden wurden. Stattdessen sollte dasselbe Build-Artefakt durch die verschiedenen Phasen der Build-Pipeline geschleust und schließlich live geschaltet werden.

Um dies in die Praxis umzusetzen, muss der Build systemunabhängig sein. Alle Variablen, Authentifizierungsparameter, Konfigurationsdateien oder Skripts sollten vom Deployment-Skript aufgerufen statt in den Build integriert werden. Auf diese Weise kann derselbe Build für Tests in den verschiedenen Umgebungen bereitgestellt werden, wobei mit jeder bestandenen Phase das Vertrauen des Teams in dieses eine Build-Artefakt zunimmt.

Es hat sich bewährt, alle Informationen, einschließlich Build-Skript, Konfigurationsdateien und Deployment-Skripte, im selben Quellcodeverwaltungssystem zu speichern, in dem auch der Anwendungscode verwahrt wird. Dies gilt jedoch nicht für das Build-Artefakt selbst. Als ein Produkt, das aus diesen Inputs generiert wird, gehört der Build nicht in die Quellcodeverwaltung. Stattdessen sollte es versioniert und in einem zentralen Artefakt-Repository wie Nexus gespeichert werden. Von dort kann es dann abgerufen und für die einzelnen Instanzen bereitgestellt werden.

Tests optimieren

Obwohl CI/CD weitgehend auf automatisierte Tests setzt, um Vertrauen in die Softwarequalität zu schaffen, heißt das nicht, dass wir versuchen sollten, für jede Eventualität einen Test zu schreiben.

Schließlich liegt der Sinn von Continuous Integration darin, schnelles Feedback und eine im Vergleich zu traditionellen Methoden schnellere Bereitstellung nützlicher Produkte zu ermöglichen. Dies bedeutet, dass wir eine Balance zwischen Testabdeckung und Performance finden müssen. Wenn es zu lange dauert, bis Testergebnisse vorliegen, werden Rechtfertigungen und Möglichkeiten gesucht, um den Prozess zu umgehen.

Führen Sie die am schnellsten durchlaufenden Tests zuerst aus, um so früh wie möglich Feedback zu erhalten. Investitionen in längere Tests sind erst dann sinnvoll, wenn bereits ein gewisses Maß an Vertrauen in den Build vorhanden ist. Da manuelle Qualitätssicherung zeitaufwändig sind und zu ihrer Durchführung Ihr Team zur Verfügung stehen muss, empfiehlt es sich, diese Phase erst nach dem erfolgreichen Abschluss aller automatisierten Überprüfungen anzusetzen.

Die erste Ebene der automatisierten Tests besteht normalerweise aus Unit-Tests mit einer breiten Abdeckung. Sie sollen offensichtliche Probleme aufdecken, die durch die letzte Änderung verursacht wurden. Auf die Unit-Tests kann eine Ebene von automatisierten Integrations- oder Komponententests folgen, mit denen die Interaktionen zwischen verschiedenen Teilen des Codes getestet werden.

In einer nächsten Stufe können Sie in komplexere automatisierte Tests wie GUI-, Performance-, Last- oder Sicherheitstests investieren, bevor Sie schließlich den Zeitaufwand für manuelle Explorations- und/oder Abnahmetests auf sich nehmen. Um diese länger laufenden Tests – egal ob automatisch oder manuell durchgeführt – effizienter zu nutzen, konzentrieren Sie sich auf die Bereiche, die die größten Risiken für Ihr Produkt und Ihre Benutzer*innen darstellen.

Umgebungen bereinigen

Um das Optimum aus Ihrer QS-Suite herauszuholen, sollten Sie sich die Zeit nehmen, Ihre Vorproduktionsumgebungen zwischen den einzelnen Deployments zu bereinigen.

Wenn Umgebungen über einen längeren Zeitraum ausgeführt werden, wird es schwieriger, alle Konfigurationsänderungen und Aktualisierungen, die auf die einzelnen Umgebungen angewendet wurden, im Blick zu behalten.

Im Laufe der Zeit entfernen sich die Umgebungen dadurch vom ursprünglichen Setup und voneinander. Dies bedeutet, dass Tests, die in einer Umgebung positiv oder negativ ausfallen, in einer anderen Umgebung möglicherweise zu einem anderen Ergebnis führen würden. Die Pflege statischer Umgebungen ist zudem mit Wartungskosten verbunden, die den QA-Prozess verlangsamen und den Releaseprozess verzögern können.

Wenn zum Hosten von Umgebungen und zum Ausführen von Tests Container verwendet werden, erleichtert dies die Bereitstellung und Entsorgung von Umgebungen für jedes neue Deployment, da diese Schritte mit dem „Infrastruktur als Code“-Ansatz geskriptet werden können. Wenn jedes Mal ein neuer Container instanziiert wird, gewährleisten Sie dadurch die Konsistenz und können Umgebungen einfacher skalieren, sodass bei Bedarf mehrere Builds parallel getestet werden können.

Keine anderen Deployment-Methoden zulassen

Sobald Sie eine zuverlässige, schnelle und sichere CI/CD-Pipeline aufgebaut haben, die Ihnen Vertrauen in die Qualität Ihrer Builds gibt, sollten Sie diesen Erfolg nicht dadurch untergraben, dass Sie die Umgehung dieses Prozesses zulassen.

Als Begründung für eine Umgehung des Releaseprozesses wird in der Regel angeführt, dass die Änderung geringfügig und/oder dringend sei. Wer solchen Forderungen nachgibt, spart jedoch am falschen Ende.

Wenn automatisierte Phasen der Qualitätssicherungs übersprungen werden, können Probleme auftreten, die vermeidbar gewesen wären. Außerdem ist das Reproduzieren und Debuggen von Fehlern viel schwieriger, wenn der Build nicht sofort für den Einsatz in einer Testinstanz verfügbar ist.

Es ist sehr wahrscheinlich, dass Sie früher oder später mit der Bitte konfrontiert werden, den Prozess „nur dieses eine Mal“ zu umgehen. Diese Fragen kommen meist, wenn man mitten in einem Notfall ist – aber es lohnt sich, hinterher eine Retrospektive oder ein Post-mortem anzusetzen, um die Motivation dahinter zu verstehen. Kommt der Prozess den Mitwirkenden zu langsam vor? Möglicherweise müssen Performance-Verbesserungen oder andere Optimierungen vorgenommen werden. Liegt ein Missverständnis darüber vor, wann der Prozess verwendet werden sollte? Wenn man die Vorteile einer CI/CD-Pipeline kommuniziert, kann dies dazu beitragen, die Akzeptanz unter den Beteiligten zu erhöhen und solche Anfragen zu vermeiden, wenn es mal wieder brennt.

Pipeline-Daten überwachen

Im Rahmen der Einrichtung Ihrer CI/CD-Pipeline haben Sie wahrscheinlich eine Überwachung Ihrer Produktionsumgebung implementiert, um bei Anzeichen von Problemen so früh wie möglich gewarnt zu werden.

Genau wie das Produkt, an der Sie arbeiten, profitiert auch Ihre Build-Prozess von einer Feedback-Schleife.

Durch eine Analyse der von Ihrem CI/CD-Tool erfassten Messwerte können Sie potenzielle Probleme und Verbesserungsmöglichkeiten identifizieren.

  • Die nach Wochen, Tagen oder Stunden aufgeschlüsselte Betrachtung der Build-Zahlen bietet nützliche Informationen darüber, wie Ihre Pipeline-Infrastruktur verwendet wird, ob eine Skalierung nach oben oder unten erforderlich ist und wann die Spitzenzeiten sind.
  • Wenn Sie die Entwicklung der Deployment-Geschwindigkeit beobachten, werden Ihnen Verlangsamungstendenzen auffallen und Sie können bei Bedarf in Leistungsoptimierungen investieren.
  • Statistiken aus automatisierten Tests können dabei helfen, Bereiche zu bestimmen, die von einer Parallelisierung profitieren würden.
  • Wenn Sie bei einer Überprüfung der QS-Ergebnisse feststellen, dass bestimmte Ergebnisse routinemäßig ignoriert werden, kann dies ein Hinweis auf Verbesserungspotenzial hinsichtlich Ihrer QS-Abdeckung sein.

Das gesamte Team einbinden

Beim Aufbau eines effektiven CI/CD-Workflows ist die Team- und Organisationskultur genauso wichtig wie die verwendeten Prozesse und Tools.

Continuous Integration, Continuous Delivery und Continuous Deployment sind DevOps-Methoden. Sie setzen voraus, dass die traditionelle Trennung zwischen Entwicklung, QS und Operations aufgebrochen und die Zusammenarbeit zwischen den Disziplinen gefördert wird.

Durch Aufbrechen der Silo-Mentalität erhalten Teams einen besseren Einblick in den gesamten Workflow und die Möglichkeit, im Zuge der Zusammenarbeit vom Fachwissen der verschiedenen Disziplinen zu profitieren. Die Pipeline am Laufen zu halten sollte niemals die Aufgabe einer einzelnen Person sein. Die Einführung einer CI/CD-Plattform kann ebenfalls zur Verbesserung Ihrer betrieblichen Abläufe beitragen.

Wenn Sie es schaffen, ein Gefühl der gemeinsamen Verantwortung für die Bereitstellung Ihrer Software entstehen zu lassen, kann jedes Teammitglied seinen Beitrag leisten, indem sie Buildfehler beheben, Umgebungen containerisieren oder manuelle Aufgaben automatisieren, die nicht oft genug ausgeführt werden.

Eine Kultur des Vertrauens, in der Teammitglieder experimentieren und Ideen austauschen können, kommt nicht nur Ihren Mitarbeiterinnen und Mitarbeitern, sondern auch dem Unternehmen und der entwickelten Software zugute. Wenn etwas schief geht, suchen Sie nicht nach einem Schuldigen, sondern lernen Sie aus dem Vorfall. Finden Sie die Ursache des Fehlers heraus – und wie er in Zukunft vermieden werden kann.

Nutzen Sie die Gelegenheit, um Ihren CI/CD-Workflow robuster und effektiver zu gestalten. Wenn Ihr Team ohne Angst vor Diskriminierung experimentieren und an Innovationen arbeiten kann, entsteht ein positiver Kreislauf kontinuierlicher Verbesserungen.