DevOps-Tech: Continuous Integration

Softwaresysteme sind komplex und eine scheinbar einfache, eigenständige Änderung an einer einzelnen Datei kann unbeabsichtigte Auswirkungen auf das Gesamtsystem haben. Wenn eine große Zahl von Entwicklern an ähnlichen Systemen arbeitet, ist die Koordinierung von Code-Updates ein schwieriges Problem und Änderungen von verschiedenen Entwicklern können inkompatibel sein.

Zur Lösung dieser Probleme wurde die Continuous Integration (CI) entwickelt. CI folgt dem Prinzip, dass etwas, das viel Zeit und Energie in Anspruch nimmt, häufiger durchgeführt werden muss, damit der Druck entsteht, es besser zu machen. Durch schnelle Feedback-Loops und dadurch, dass eine Aufgabenteilung zwischen Entwicklern gewährleistet ist, ermöglicht CI den Teams, hochwertige Software zu erstellen, die Kosten für laufende Softwareentwicklung und -wartung zu senken und die Produktivität der Teams zu steigern.

CI implementieren

Wenn Ihre Organisation CI anwendet, binden Ihre Entwickler ihre gesamte Arbeit regelmäßig in die Hauptversion der Codebasis (Hauptentwicklungszweig, Hauptversion oder Mainline genannt) ein. Studien von DevOps Research and Assessment (DORA) (PDF) zeigen, dass Teams eine bessere Leistung erzielen, wenn Entwickler ihre Arbeit mindestens einmal täglich im Hauptentwicklungszweig zusammenführen. Vor und nach der Zusammenführung wird eine Reihe automatisierter Tests ausgeführt, um zu prüfen, ob die Änderungen keine Regressionsfehler verursachen. Wenn diese automatisierten Tests fehlschlagen, unterbricht das Team seine Arbeit, um das Problem sofort zu beheben.

Durch CI ist die Software immer in einem funktionsfähigen Zustand und Entwicklerzweige weichen nicht wesentlich vom Hauptentwicklungszweig ab. Die Vorteile von CI sind erheblich: Studien (PDF) zeigen, dass es zu einer höheren Bereitstellungshäufigkeit, stabileren Systemen und höherwertiger Software führt.

Die Schlüsselelemente für die erfolgreiche Implementierung von Continuous Integration sind:

  • Jedes Commit sollte einen Build der Software auslösen.
  • Jedes Commit sollte eine Reihe automatisierter Tests auslösen, die innerhalb weniger Minuten Feedback geben.

Zur Implementierung dieser Elemente benötigen Sie Folgendes:

  • Einen automatisierten Build-Prozess. Der erste Schritt in CI besteht in einem automatisierten Skript, das Pakete erstellt, die in jeder Umgebung bereitgestellt werden können. Die vom CI-Build erstellten Pakete sollten autoritativ sein und von allen nachgelagerten Prozessen verwendet werden. Diese Builds sollten nummeriert und wiederholbar sein. Sie sollten Ihren Build-Prozess mindestens einmal täglich erfolgreich ausführen.
  • Eine Reihe automatisierter Tests. Falls noch keine vorhanden sind, schreiben Sie zuerst einige Einheiten- und Akzeptanztests (PDF), die diejenigen Funktionen Ihres Systems abdecken, die für die Wertschöpfung zentral sind. Die Tests müssen zuverlässig sein. Auf diese Weise verfügen Sie bei Auftreten eines Fehlers über das Wissen, dass ein echtes Problem vorliegt. Umgekehrt können Sie, wenn die Tests erfolgreich sind, sicher sein, dass es keine ernsthaften Probleme mit dem System gibt. Sorgen Sie dann dafür, dass alle neuen Funktionen durch Tests abgedeckt sind. Diese Tests sollten schnell ausgeführt werden, damit Entwickler so schnell wie möglich Feedback erhalten. Ihre Tests sollten mindestens einmal täglich erfolgreich ausgeführt werden. Bei Leistungs- und Akzeptanztests sollten die Entwickler durch die Tests täglich Feedback erhalten.
  • Ein CI-System, das die Build-Tests und automatisierten Tests bei jedem Check-in ausführt. Das System sollte den Status auch für das Team sichtbar machen. Sie können das System unterhaltsam gestalten und beispielsweise Hupen oder Ampeln verwenden, um einen fehlerhaften Build anzuzeigen. Verwenden Sie keine E-Mail-Benachrichtigungen. Viele Nutzer ignorieren E-Mail-Benachrichtigungen oder erstellen einen Filter zum Ausblenden von Benachrichtigungen. Benachrichtigungen in einem Chatsystem sind hierfür eine bessere und beliebtere Methode.

Continuous Integration gemäß der Definition von Kent Beck und der Extreme Programming-Community, von der der Begriff stammt, umfasst zwei weitere Vorgehensweisen, die es ebenfalls wahrscheinlicher machen, dass die Leistung bei der Softwarebereitstellung zunimmt:

CI erfordert automatisierte Einheitentests. Diese Tests sollten umfassend genug sein, dass Sie sicher sein können, dass die Software wie erwartet funktioniert. Die Tests müssen in wenigen Minuten ausgeführt werden. Wenn die automatisierten Einheitentests länger dauern, neigen Entwickler dazu, sie nicht häufig auszuführen. Wenn die Tests selten ausgeführt werden, kann ein Testfehler aus vielen verschiedenen Änderungen resultieren, was das Debuggen erschwert. Tests, die selten ausgeführt werden, lassen sich nur schwer verwalten.

Die Erstellung verwaltbarer Reihen automatisierter Einheitentests ist komplex. Eine gute Möglichkeit, dieses Problem zu lösen, ist die testgetriebene Entwicklung (Test-Driven Development, TDD), bei der Entwickler automatisierte Tests schreiben, die erst einmal fehlschlagen, bevor sie den Code implementieren, der die Tests besteht. TDD hat mehrere Vorteile. Einer ist, dass Entwickler modularen und einfach zu testenden Code schreiben können, wodurch die Wartungskosten der resultierenden automatisierten Testreihen reduziert werden. Viele Organisationen haben keine verwaltbaren Reihen automatisierter Einheitentests und wenden trotzdem keine TDD an.

Einwände gegen CI

Wie bereits erwähnt, wird CI manchmal als kontroverses Verfahren betrachtet. CI erfordert, dass Ihre Entwickler umfangreiche Features und andere Änderungen in kleinere inkrementelle Schritte aufteilen, die häufig in den Hauptentwicklungszweig integriert werden können. Für Entwickler, die diese Arbeitsweise nicht gewohnt sind, bedeutet dies eine Umstellung. Wenn Teams zu kleinen Schritten wechseln, kann es außerdem länger dauern, bis umfangreiche Features abgeschlossen sind. Im Allgemeinen sollten Sie jedoch nicht versuchen, die Entwicklungsarbeit auf die Geschwindigkeit hin zu optimieren, mit der Entwickler ein umfangreiches Feature in einem Zweig für abgeschlossen erklären können. Ihr Ziel sollte vielmehr sein, Änderungen so schnell wie möglich zu prüfen, zu integrieren, zu testen und bereitzustellen. Dieser Prozess führt zu einer Softwareentwicklung und -bereitstellung, die schneller und stabiler (PDF) ist, wenn die Änderungen klein und unabhängig sind und die Zweige, in denen sie gespeichert sind, nur kurzlebig sind. Durch aufgeteilte Arbeit erhalten Entwickler außerdem von anderen Entwicklern, Testern und Kunden sowie von automatisierten Leistungs- und Sicherheitstests regelmäßig Feedback zu den Auswirkungen ihrer Arbeit auf das System als Ganzes. Dadurch lassen sich Probleme einfacher und schneller erkennen und beheben.

Trotz dieser Einwände sollte die Unterstützung von Softwareentwicklungsteams bei der Implementierung von Continuous Integration die oberste Priorität für jede Organisation sein, die den Weg zu Continuous Delivery beginnen möchte.

Häufige Stolperfallen

Einige häufige Probleme, die eine breite Akzeptanz von CI verhindern, sind:

  • Nicht alles wird im Code-Repository gespeichert. Alles, was zum Erstellen und Konfigurieren der Anwendung und des Systems erforderlich ist, sollte sich in Ihrem Repository befinden. Dies mag außerhalb des Bereichs von CI erscheinen, ist aber eine wichtige Grundlage.
  • Der Build-Prozess wird nicht automatisiert. Bei manuellen Schritten können Fehler auftreten und die Schritte nicht dokumentiert werden.
  • Nicht bei jeder Änderung werden Schnelltests ausgelöst. Es sind vollständige End-to-End-Tests erforderlich, aber auch Schnelltests (normalerweise Einheitentests) sind wichtig, um schnelles Feedback zu ermöglichen.
  • Fehlerhafte Builds werden nicht sofort behoben. Ein Hauptziel von CI ist ein stabiler Build, aus dem jeder die Entwicklungsarbeit fortsetzen kann. Wenn der Fehler im Build nicht innerhalb weniger Minuten behoben werden kann, sollte die Änderung identifiziert und zurückgesetzt werden.
  • Tests, deren Ausführung zu lange dauert. Die Tests sollten nicht länger als ein paar Minuten dauern. Die Obergrenze beträgt laut der Studie von DORA (PDF) etwa zehn Minuten. Wenn Ihr Build länger dauert, sollten Sie die Effizienz Ihrer Tests verbessern, zusätzliche Rechenressourcen hinzufügen, damit Sie sie parallel ausführen können, oder längere Tests mithilfe des Deployment-Pipeline-Musters unterteilen.
  • Zu seltene Zusammenführung im Hauptentwicklungszweig. Viele Organisationen verfügen über automatisierte Tests und Builds, achten aber auf keine tägliche Zusammenführung im Hauptentwicklungszweig. Dies führt zu langlebigen Zweigen, die viel schwieriger zu integrieren sind, und zu langen Feedback-Loops für die Entwickler.

Möglichkeiten zur Messung von CI

Die oben erläuterten CI-Konzepte beschreiben Möglichkeiten zur Messung der Effektivität von CI in Ihren Systemen und Ihrer Entwicklungsumgebung, wie in der folgenden Tabelle dargestellt. Durch die Erfassung dieser Messwerte können Sie Ihre Prozesse und Tools dafür optimieren. Dies führt zu besseren CI-Verfahren und kürzeren Feedback Loops für Ihre Entwickler.

Faktor zum Testen Geeignete Messwerte
Code-Commits lösen einen Build der Software aus. Der Prozentsatz der Code-Commits, die zu einem Software-Build ohne manuelles Eingreifen führen.
Code-Commits lösen eine Reihe automatisierter Tests aus. Der Prozentsatz der Code-Commits, die dazu führen, dass eine Reihe automatisierter Tests ohne manuelles Eingreifen ausgeführt wird.
Automatisierte Builds und Tests werden täglich erfolgreich ausgeführt. Der Prozentsatz der automatisierten Builds und der Prozentsatz der automatisierten Tests, die täglich erfolgreich ausgeführt werden.
Aktuelle Builds stehen Testern für explorative Tests zur Verfügung. Die Verfügbarkeit von Builds für Tester oder das Gegenteil, nämlich die Nichtverfügbarkeit von Builds für Tester.
Entwickler erhalten täglich Feedback zu den Akzeptanz- und Leistungstests. Die Verfügbarkeit von Feedback für Entwickler zu Akzeptanz- und Leistungstests, d. h. der Prozentsatz der Tests, die den Entwicklern innerhalb eines Tages zur Verfügung stehen.
Fehlerhafte Builds werden sofort behoben. Die Zeit, die zwischen dem Auftreten und dem Beheben des Build-Fehlers erforderlich ist, entweder mit einem Check-in, der das Problem behebt, oder durch die funktionsgefährdende Änderung.

Nächste Schritte