Continuous Integration: Die kontinuierliche Integration erklärt
Wer in der Softwareentwicklung arbeitet, der kennt die Probleme von Integration: Neuer Code ist geschrieben, die eigentliche Aufgabe erledigt, nun muss der Quelltext nur noch in das große Projekt eingefügt werden – und dabei treten dann die Probleme auf. Damit nicht am Ende einer langen Entwicklungsphase eine Katastrophe passiert, weil nichts zusammenpasst, entscheiden sich viele Teams für Continuous Integration: Änderungen werden dadurch jeden Tag direkt in das Projekt eingefügt, im besten Fall sogar mehrmals täglich.
Continuous Integration ist – genau wie Continuous Delivery – vor allem im Umfeld von agiler Softwareentwicklung sehr beliebt. Ziel bei dieser modernen Herangehensweise ist es, kleinschrittiger zu arbeiten, um dadurch den Entwicklungsprozess selbst effektiver gestalten und auf Änderungen flexibler reagieren zu können. Das erste Mal erwähnt wurde Continuous Integration folglich in der Beschreibung der agilen Methode Extreme Programming von Kent Beck. Grundsätzlich existierte die Idee einer kontinuierlichen Integration aber schon zuvor. Sie spielt beispielsweise auch bei der Booch-Methode eine Rolle.
Was ist Continuous Integration?
Mit der kontinuierlichen Integration schafft man eine Lösung für Szenarien folgender Art: Das Unternehmen arbeitet an einem großen Projekt. Der Kunde soll eine umfangreiche, komplexe Software erhalten. Einzelne Teams erarbeiten nun Teilaspekte der Anwendung und die Entwickler programmieren wiederum einzelne Funktionen. Nach monatelanger, vielleicht jahrelanger Arbeit, muss alles zusammengefügt werden – und dabei treten dann Probleme auf. In einem solchen Fall kann es dann abermals Monate dauern, bis die Fehler aufgespürt und bereinigt und alle Code-Schnipsel zusammengefügt sind und man sich schließlich dem finalen Testing und dem Deployment nähert.
Bei der Continuous Integration erfolgt die Einbindung von neuem Code viel früher und nicht erst, wenn sämtliche Beteiligten ihren Teilbereich fertiggestellt haben. Die Entwickler fügen stattdessen ihren fertiggestellten Code einmal oder mehrmals am Tag in die Mainline ein – dem Quelltext, der allen Programmierern offensteht. Da es sich dabei immer nur um relativ kleine Code-Abschnitte handelt, fällt auch die Integration eher kurz aus. Nur wenige Minuten sollte ein Entwickler brauchen, um sein Arbeitsergebnis dem restlichen Team zur Verfügung zu stellen. Entdeckt man hierbei einen Fehler, kann dieser sofort aufgespürt und im besten Fall schnell behoben werden.
Continuous Integration (im Deutschen auch als „kontinuierliche Integration“ oder „permanente Integration“ bezeichnet) ist eine Technik der agilen Softwareentwicklung. Bei dieser Art der Integration fügen Entwickler fertige Code-Schnipsel regelmäßig – mitunter mehrfach am Tag – in die Anwendung ein, statt sie alle erst zum Abschluss des Projekts zu integrieren.
Vorgehen
In der Praxis läuft Continuous Integration meist so ab: Ein Entwickler hat den Auftrag, eine Funktion zu erstellen. Bevor dieser nun mit der Programmierarbeit beginnt, lädt er sich die aktuelle Version des kompletten Codes der Anwendung herunter, die sogenannte Mainline. In dieser Version, die sich nun auf seinem persönlichen Computer befindet (auch Working Copy genannt), kann er arbeiten. Hat er seine Aufgabe erledigt, testet er das Programm aus, beseitigt etwaige Fehler und kann nun die neue Version wieder in die Mainline stellen.
Allerdings arbeitet der Entwickler ja nicht allein an dem Programm. Während er seine Änderungen vorgenommen hat, haben seine Kollegen höchstwahrscheinlich andere Aufgaben erledigt und so hat jeder Entwickler des Teams nun eine unterschiedliche Fassung auf dem Arbeitsrechner. Auch die Fassung der Mainline dürfte sich inzwischen verändert haben und so muss der Programmierer alle Änderungen zunächst in seine Working Copy einfügen. Sollte nun ein Fehler auftreten, ist es an ihm, diesen zu beheben. Erst dann kann der Programmierer seine Änderungen der Mainline hinzufügen. Und dann testet er das Programm erneut. Erst wenn hierbei ebenfalls keine Fehler auftreten – was passieren kann, wenn er seine Working Copy nicht korrekt aktualisiert hat – ist der Vorgang tatsächlich abgeschlossen und der Entwickler kann sich der nächsten Aufgabe widmen.
Verhaltensweisen
Wenn man auf diese Weise arbeitet, muss man sich an einige Regeln halten: Meist orientieren Programmierer sich dabei an den Grundsätzen, die Martin Fowler (seines Zeichens selbst Softwareentwickler) einst für die erfolgreiche Continuous Integration erarbeitet hat. Sie stellen in erster Linie sicher, dass sich alle Beteiligten auf dem gleichen Level befinden und niemand durch abweichendes Vorgehen ein Chaos verursacht.
Nur eine Quelle
Es klingt selbstverständlich, ist aber einer der wichtigsten Faktoren: Alle Team-Mitglieder müssen dieselbe Quelle (dasselbe Repository) verwenden, wenn sie am Code arbeiten. Das gilt nicht nur für den Quelltext an sich. Denn für eine funktionierende Anwendung sind weitere Elemente, wie zum Beispiel Datenbanken, nötig. Auch diese müssen gesammelt an einem Ort gebündelt werden. Daher empfiehlt Martin Fowler, ein Repository so aufzubauen, dass auch ein Entwickler mit einem komplett neuen Arbeitscomputer mitarbeiten kann und sämtliche benötigten Dateien zentral an einem Ort versammelt findet.
Damit die Verwaltung einer solchen Quelle gut funktioniert, ist eine Versionsverwaltung sinnvoll. Mit einer geeigneten Software fällt es sehr viel leichter, auch bei vielen Mitarbeitern die Übersicht zu behalten.
Automatisierte Builds
Um aus dem Quelltext ein funktionierendes Programm zu gestalten, müssen sie diesen kompilieren, Datenbanken aktualisieren und Dateien an den richtigen Platz verschieben. Diesen Prozess kann man automatisieren. Es sollte idealerweise möglich sein, einen Build-Prozess mit nur einem Kommando auszuführen.
Selbsttestende Systeme
Von noch mehr Automatisierung und damit Beschleunigung der Continuous Integration profitiert ein Team, wenn es Testing-Mechanismen in den Build-Prozess eingliedert. Genau wie der Build-Prozess selbst müssen die Tests (am besten man implementiert eine ganze Riege verschiedener Prüfmechanismen) sich mit möglichst wenig Aufwand ausführen lassen.
Die agile Methode Test Driven Development (TDD) legt großen Wert auf Testing. Laut Martin Fowler ist es aber nicht notwendig, TDD tatsächlich komplett umzusetzen, um Continuous Integration einzusetzen.
Tägliche Integration
Kontinuierliche Integration kann nur funktionieren, wenn auch alle Team-Mitglieder das System mittragen. Sobald ein Kollege seinen Code nicht permanent in die Mainline integriert, gehen die Kollegen von falschen Prämissen aus. Alle nehmen an, dass sie an einem stabilen System arbeiten, aber sollte jemand zu lange (mehr als einen Tag) den Code zurückhalten, kann die anschließende Fehlersuche zu einem Problem werden. Wie so oft im Leben ist auch bei der Continuous Integration Kommunikation ein wichtiger Faktor: Wenn die Entwickler sich aber gegenseitig auf dem neuesten Stand halten, lassen sich kleinere Schwierigkeiten schnell klären.
Funktionstüchtige Mainline
Der Programmcode, den man in der Mainline findet, sollte immer getestet und funktionstüchtig sein. Deshalb darf jeder Entwickler seinen Code nur in diesen Hauptzweig integrieren und nicht in einem eigenen Nebenzweig arbeiten. In diesem Zusammenhang sollte auch jeder Entwickler Sorge tragen, dass sein eigener Beitrag funktionstüchtig ist. Nach der Integration muss er also den Code und den Build testen. Tritt ein Fehler auf, muss er diesen beheben. So ist sichergestellt, dass der Code immer fehlerfrei ist.
Sofortige Reparatur
Von oberster Wichtigkeit bei der Continuous Integration ist, dass niemals eine fehlerhafte Version in der Mainline bleibt. Das bedeutet für die Entwickler, dass man die Reparatur nicht aufschieben darf. Laut Martin Fowler ist es kein Problem, wenn Builds nicht funktionieren und der Code überarbeitet werden muss, aber das System der kontinuierlichen Integration verlangt, dass die Reparatur sofort geschieht. Denn alle Entwickler müssen davon ausgehen können, dass der Code in der Mainline funktioniert – ist das nicht der Fall, baut das ganze Team in instabilen Systemen und löst so eine Lawine an Fehlern aus.
Kurze Integrationszeit
Die eigentliche Integration des Codes (inklusive des Testings) sollte möglichst schnell erfolgen. Extreme Programming (XP) sieht hierfür nur 10 Minuten vor. Da ein Entwickler unter Umständen mehrmals am Tag integriert, würden lange Build-Zeiten zu hohen Arbeitszeitverlusten führen. Deshalb ist es notwendig, Mechanismen zu etablieren, die den Prozess beschleunigen. Um solche hohen Geschwindigkeiten zu ermöglichen, muss man auch in Kauf nehmen, nicht jeden denkbaren Test direkt durchzuführen. Stattdessen implementiert man ein zweistufiges System: In der ersten Phase, die bei der täglichen Arbeit auftritt, werden Tests so durchgeführt, dass man kurze Build-Zeiten erreichen kann. Die zweite Testphase dauert hingegen mehrere Stunden und umfasst auch tiefergehende Überprüfungen.
Kopierte Testumgebung
Es ist grundsätzlich sinnvoll, Tests in einer ausgelagerten und sicheren Umgebung durchzuführen. Es muss dabei allerdings gewährleistet sein, dass diese genau so konfiguriert ist wie die Produktionsumgebung. Das kann unter Umständen sehr kostspielig werden, denn die Maschine müsste exakt gleich aufgesetzt werden. Durch Virtualisierung kompletter Computer wird dieser Kostenfaktor aber immer kleiner.
Einfacher Zugriff
Alle Beteiligten sollten einen einfachen Zugriff auf den aktuellsten Stand haben und das Programm ausführen können. Dies umzusetzen ist relativ einfach: Da Continuous Integration es ohnehin erfordert, alle Dateien in einem Repository zu versammeln, muss dieser Ort nur allen bekannt sein. Dafür gibt es mehrere gute Gründe: Tester können so bereits zusätzliche Tests im laufenden Programmierprozess beginnen, Stakeholder ausführbare Dateien zu Demonstrationszwecken nutzen und Qualitätsmanager die Zahlen überprüfen.
Nachvollziehbare und klare Kommunikation
Es ist nicht nur wichtig, dass alle Beteiligten Zugriff auf den Quelltext und die ausführbare Datei haben, ebenso muss deutlich sein, welche Änderungen von wem durchgeführt wurden. Zur Kommunikation gehört auch, dass Entwickler sich gegenseitig verständigen, wenn sie in einem Build-Prozess sind. Dafür verwenden manche Teams gesonderte Displays oder visuelle Darstellungen, die zeigen, dass man gerade mit einer Integration beschäftigt ist.
Automatisierte Verteilung
Schließlich sollte man auch die Softwareverteilung automatisieren. Dateien müssen von einer Umgebung in eine andere überführt werden, was zeitaufwendig sein kann. Deshalb ist es sinnvoll, hierfür Skripte einzusetzen. Diese automatisieren und beschleunigen den Prozess.
Sie möchten Ihre Entwicklungsprozesse schlanker gestalten? Mit Deploy Now können Sie statische Websites ohne Umwege von GitHub auf IONOS georedundante, DDoS-geschützte Infrastruktur deployen. Legen Sie bequem Staging Deployments an um Änderungen vor dem Ausrollen live zu überprüfen und profitieren Sie von einer automatischen SSL-Provisionierung.
Vor- und Nachteile von Continuous Integration
Trotz ihrer positiven Merkmale zeigt sich im Arbeitsalltag oft, dass Continuous Integration nicht ausschließlich Vorteile hat. Zwar erspart man sich eine große und langwierige Integrationsphase zum Ende des Projekts und kann Probleme frühzeitig in Angriff nehmen, aber für eingespielte Teams kann eine Umstellung auf Continuous Integration sehr schwierig sein. In einem solchen Fall kann das Verfahren sogar mehr Zeit kosten, anstatt Zeit zu sparen.
Vorteile | Nachteile | |
---|---|---|
Frühzeitige Fehlersuche möglich | Umstellung von gewohnten Prozessen | |
Ständiges Feedback | Benötigt zusätzliche Server und Umgebungen | |
Keine Überforderung bei einzelner großer Integration zum Abschluss | Erarbeitung von geeigneten Test-Abläufen nötig | |
Genaue Aufzeichnung von Änderungen | Es kann zu Wartezeiten kommen, wenn mehrere Entwickler annähernd gleichzeitig ihren Code integrieren möchten | |
Stetige Verfügbarkeit einer funktionierenden, aktuellen Version | ||
Fördert granulares Arbeiten |
- Inklusive Wildcard-SSL-Zertifikat
- Inklusive Domain Lock
- Inklusive 2 GB E-Mail-Postfach
Vorgestellt: Nützliche Continuous-Integration-Tools
Prinzipiell kann man kontinuierliche Integration auch ohne extra dafür erstelle Werkzeuge managen, denn alle Arbeitsschritte lassen sich durchaus manuell erledigen. Das erfordert aber sehr viel Disziplin und noch mehr Aufwand. Man kann sich die Arbeit daher auch mit nützlichen Tools erleichtern. Diese stellen meist einen Server zur Verfügung und helfen beim Building und der Versionskontrolle.
- Jenkins: Bei dem sehr populären Java-Programm handelt es sich um einen Fork von Hudson, der inzwischen nicht mehr weiterentwickelt wird. Die Open-Source-Software arbeitet mit verschiedenen Build-Tools und Versionsverwaltungssystemen.
- Travis CI: Dieses Werkzeug zur kontinuierlichen Integration ist insbesondere deswegen so beliebt, weil es reibungslos mit GitHub zusammenarbeitet. Das Online-Repository informiert Travis über Änderungen am Code. Die Software gibt es für Open-Source-Projekte in einer kostenlosen und für alle anderen Vorhaben in einer kostenpflichtigen Version.
- Bamboo: Mit dem Server Bamboo können Entwickler Integration, Deployment und Release-Management erledigen. Der Hersteller Atlassian bietet die Software als Weboberfläche auf Basis von Java an. Bamboo unterstützt Entwickler durch Automatisierungen und arbeitet mit verschiedenen Build-Tools zusammen. Für Open-Source-Projekte steht das normalerweise kostenpflichtige Angebot auch kostenlos zur Verfügung.
- Gitlab CI: GitLab bietet ein eigenes Programm zur kontinuierlichen Integration an, das mit der bekannten Versionsverwaltung funktioniert. Die Pipeline lässt sich individuell gestalten und so an jedes Projekt anpassen. Zusätzlich unterstützt auch GitLab CI Docker.
- CircleCI: Von diesem Programm für die Continuous Integration gibt es zwei verschiedene Versionen. Entweder entscheidet man sich für eine Variante direkt in der Cloud des Anbieters oder man erstellt zur Nutzung einen eigenen lokalen Server.
- CruiseControl: Ursprünglich von ThoughtWorks (einer Firma rund um Martin Fowler) entwickelt, besteht CruiseControl inzwischen als eigenständiges Projekt. Die freie Software basiert auf Java und ist damit plattformunabhängig. Unter anderem bietet CruiseControl für Entwickler ein Dashboard – eine eigene Webseite – auf der man den Status der Builds erkennen kann.
- Codeship: Codeship versucht Entwicklern eine sehr einfache Möglichkeit zur Continuous Integration zu liefern. Auf der Basis der Container-Technologie lassen sich leicht Automatismen erstellen. Für diese Aufgabe bietet das Unternehmen zwei verschiedene Versionen an: Basic und Pro.
- TeamCity: Die kommerzielle Software TeamCity legt sehr viel Wert auf Interoperabilität mit anderen Werkzeugen. Viele Programme werden bereits in der Standardversion unterstützt, zusätzlich lässt sich das Spektrum aber auch noch durch Plug-ins erweitern. Eine Besonderheit findet man zudem im Pre-Tested Commit. TeamCity überprüft den neugeschriebenen Code bereits vor der Integration in die Mainline selbstständig und informiert den Entwickler bei Fehlern.
In unserem Vertiefungsartikel erfahren Sie mehr über die Vor- und Nachteile der unterschiedlichen Continuous-Integration-Tools.