Software-Entwicklung erfolgt meist im Team. Die Zusammenarbeit bringt Impulse für das Projekt – sie kann es aber auch gefährden, wenn sich Qualitätsprobleme einschleichen. Ein Weg aus der Misere ist die Continuous Integration, Hudson das passende Tool.
Es bedarf großer Umsicht, wenn viele Software-Entwickler gemeinsam an einem Projekt arbeiten. Führt einer von ihnen einen Bug an einer selten genutzten Stelle im Code ein, den Anwender oder Tester erst etliche Revisionen später entdecken, gestaltet sich das Bugfixing besonders schwierig.
Build-Umgebungen helfen, um aus dem Quelltext lauffähige Programme zu erzeugen, Source-Code-Managementsysteme (SCM), um den Programmtext zu versionieren und zu verteilen, Test-Frameworks, um das Projekt auf syntaktische, statische, logische und funktionale Fehler zu prüfen. In jedem Bereich gibt es eine Handvoll Werkzeuge, um Code für C, C++, Java oder PHP zu verwalten.
Die einzelnen Werkzeuge kitten Entwickler gerne mit Shellskripten und Wrappern zusammen – doch das gerät schnell aufwändig. Die im Kasten “Continuous Integration (CI)” erläuterte junge Disziplin macht sich diese Koordination zur Aufgabe. Es existiert inzwischen eine ganze Reihe fertiger Werkzeuge für Continuous Integration. Wer das hier vorgestellte und im Java-Kontext bei Sun entstandene Hudson [1] nicht verwenden möchte, findet Alternativen bei Cruise Control [2] oder Apache Gump [3] .
|
Continous Integration |
|---|
|
Teamarbeit ist in der modernen Software-Entwicklung verbreitet. Die wenigsten Projekte zieht ein einzelner, einsamer Hacker durch, selbst kleine Projekte kommen mit einem Team von drei bis zehn Personen besser voran. Das liegt nicht nur an der simplen Verteilung der Arbeitslast. Diskussionen im Team über das Wohin und Wie sind genauso wertvoll wie das Nutzen unterschiedlicher Fähigkeiten der Teammitglieder vom Software-Entwurf bis hin zur Icon-Gestaltung. Aufwand durch TeamkoordinationDoch Teamarbeit gibt es nicht umsonst, neben den typischen Problemen menschlicher Zusammenarbeit ist auch eine Reihe technischer Hürden zu bewältigen. Denn auch bei klarer Aufgabenteilung kann eine kleine Änderung die Stabilität der gesamten Software gefährden. Besonders kritisch wird es, wenn das Problem nicht zeitnah entdeckt wird. Die Ursache für ein Problem zu entdecken gerät überproportional aufwändiger, je mehr Änderungen seither erfolgt sind. Dieser Zustand ist für das Projekt sehr gefährlich, denn es demotiviert alle Mitarbeiter extrem. Freiwillige Teammitglieder bei offener Software springen dann leicht ab, von den finanziellen Folgen bei kommerziellen Projekten gar nicht zu reden. Mit CI regelmäßig auf VollständigkeitprüfenContinous Integration (CI) hält die Entwicklung in ruhigen Bahnen. Dahinter steckt die Idee, die ganze Software nach jeder Änderung oder wenigstens sehr regelmäßig zu kompilieren und zu testen. Hiermit lassen sich Qualitätsprobleme zeitnah entdecken und die Ursachen sofort abstellen. Die populäre Idee stammt aus dem Umfeld der agilen Software-Entwicklung. Im Idealfall startet das CI-Tool nach jedem Einchecken einen Durchlauf, spätestens jedoch einmal täglich (Nightly Build). Fällt der neue Stand beim Kompilieren, Linken oder Testen durch, ist der Fehler wesentlich einfacher zu finden, als wenn die Arbeit von mehreren Entwicklern nur alle Jubeljahre zusammengefahren wird. Zwei Punkte sind dafür wesentlich: Das Buildsystem (Make, Ant) muss das Kompilieren ohne manuellen Eingriff ermöglichen und die Tests müssen die Software möglichst gut abdecken. Der Arbeitsaufwand in einem Durchlauf unterscheidet sich von Projekt zu Projekt. Einfache Projekte sind mit Kompilieren und Testen auf einem Rechner in den Griff zu bekommen. Schwierig wird es, wenn ein Projekt aus mehreren Teilen – etwa Bibliotheken – besteht oder gar plattformübergreifend arbeitet. Hier sind die Schritte parallel auf mehreren Plattform (Hardware, Linux-Distributionen, Kompilerversion) zu testen. Und schließlich helfen neben dem Unit-Test auch Werkzeuge zur statischen Codeanalyse dabei, rechtzeitig problematische Stellen zu finden. Automatisierung schafft definierte AbläufeKaum ein Entwickler wird diese Schritte mehr als zwei- oder dreimal per Hand durchlaufen wollen. Auf Dauer ist Automatisierung nötig. Dabei helfen spezielle Werkzeuge zur Continous Integration, die den Ablauf immer wieder kontrolliert durchlaufen, die Ergebnisse aufheben, Teammitglieder informieren und weitere Aufgaben automatisieren. Die eigentliche Automatisierung hört sich zuerst nur nach wenigen Shellskripten an. Mit verschiedenen Schnittstellen in die Sourcecode-Verwaltung, zum Buildmanagement, Testsystem und E-Mail-Versand kommt aber schnell einiges zusammen. |
Anstoß
Als Kohsuke Kawaguchi bei Sun an Javas XML-Schnittstellen arbeitete, war er mit den existierenden Werkzeugen nicht zufrieden und schrieb Hudson – zuerst für den Eigenbedarf. Dank seiner Plugin-Struktur und guter Community-Arbeit verbreitete sich das Tool schnell in Suns eigenen Projekten wie Java, Netbeans oder Glassfish, aber auch außerhalb von Sun. Dabei taugt Hudson nicht nur für Java-Programme, wegen seines modularen Aufbaus setzen es auch Entwickler für andere Sprachen wie C, C++, Mono oder PHP ein. Im Zuge des Aufkaufs von Sun durch Oracle verließ Kawaguchi inzwischen das Unternehmen und bietet seither auch kommerziellen Support für das von ihm entwickelte Tool an.
Hudson ist so einfach zu bedienen, dass vom Download bis zum ersten Testlauf weniger als eine Viertelstunde vergeht. Fast alle Aufgaben lassen sich mit dem intuitiven Web-GUI lösen. Wer etwas vermisst, darf auf XML-Konfigurationsdateien zugreifen oder Hudson über das Plugin-System erweitern. Weit über 300 von ihnen kennt das Werkzeug in der getesteten Version 1.355.
Kawaguchi schrieb Hudson in Java und stellt die Software als Webarchive im WAR-Format bereit. Sie lässt sich direkt mit »java -jar hudson.war« auf der Kommandozeile starten. Sie legt ihre Daten und Projekte im Ordner ».hudson« des Homeverzeichnisses des aufrufenden Hudson-Verwalters an und offeriert sein Web-GUI per HTTP auf Port 8080. Alternativ startet das Programm per
java -DHUDSON_HOME=/tmp/hudson -jar hudson.war --httpPort=4242
mit anderen Verzeichnissen und Ports. Im Browser öffnen Anwender dann die URL »http://Server:4242/«. Hudson empfiehlt, dazu den richtigen Hostnamen an Stelle von »localhost« zu verwenden, damit auch andere Anwender erzeugte URLs nutzen können, etwa zu Fehlerreports oder Statistiken.
Ruhiger Spielaufbau
Zunächst konfiguriert der Verwalter unter »Hudson verwalten | System konfigurieren« einige Grundlagen zum Dienst, darunter Pfade zu Werkzeugen wie Shell, CVS, Java-Compiler und zum E-Mail-Server. Wer statt des ehrwürdigen CVS neuere SCM wie Git oder Subversion nutzt, der installiert oder aktualisiert unter »Hudson verwalten | Plugins verwalten« die passenden Plugins aus dem zentralen Repository oder aus lokalen Dateien. Nach einem Klick auf den Neustart-Knopf stehen sie zur Verfügung.
Hudson verwaltet auf Wunsch mehrere Benutzer, die alle individuelle Build- und Testläufe festlegen und planen dürfen. Dazu greift es über die Verwaltung des Servletcontainers auf Verzeichnisdienste wie LDAP oder Active Directory zu [4]. Dann ist jedoch ein Servletcontainer wie Tomcat, Jboss oder Glassfish angesagt. Erste Jobs lassen sich aber auch prima mit dem leichtgewichtigen Winstone-Servletcontainer über den Aufruf von »java -jar« anlegen und testen [5].
Als erster Schritt eines Anwenders ist über den Menüpunkt »Neuen Job anlegen« festzulegen, wo der Quellcode herkommt und wie sich prüfen lässt, ob er sich in einem stabilen Zustand befindet. Das nennt Hudson Job und kennt mehrere Profile, die sich besonders für Java-Anwendungen, etwa mit Maven, eignen. Die meisten Jobs sind jedoch vom Typ »Free Style«. Mit ihm lassen sich Jobs für echte Continuous Integration oder zeitgesteuerte Nightly Builds anlegen.
Rollenverteilung
Auf der nächsten GUI-Seite beschreiben Entwickler ihren Job, wählen das SCM und stellen eine Reihe von Details ein, deren Vorgaben zunächst ausreichen. Nützlich sind kleine Hilfe-Knöpfe, die erklären, welchen Zweck die Optionen haben und wie das Format von Angaben ist. Lokale Projekte ohne SCM verwaltet Hudson ebenfalls, erwartet sie dann jedoch im Pfad ».hudson/jobs/Jobname/workspace«. Eine Quelltextverwaltung einzusetzen ist in jedem Fall eine sinnvolle Entscheidung. Dazu benötigt die Software je nach Verfahren einen Zugangspfad und gegebenenfalls die Credentials des Repository.
Unter »Build-Auslöser« legt der Programmierer fest, wann Hudson ein Projekt bauen soll. Bei echter Continuous Integration löst eine Änderung im SCM den Prozess aus. Dazu überprüft Hudson es regelmäßig auf Änderungen. Zeitangeben für Überprüfungsintervalle macht der Verwalter über die Syntax, die auch Crontabs nutzen. Der Eintrag
*/10 * * * *
sorgt dafür, alle zehn Minuten nachzuschauen, ob Änderungen im SCM vorliegen. Für Nightly Builds gibt er hingegen feste Zeiten an – mit der Konfiguration »30 0 * * *« startet jede Nacht mitten in der Geisterstunde ein neuer Job.
In der Abteilung »Build Verfahren« gibt der Anwender die für einen Job auszuführenden Schritte an (Abbildung 1). Die Software erlaubt eine beliebige Mischung aus Shellbefehlen, Ant-Targets oder Maven-Zielen. Für ein C- oder C++-Projekt sind dies üblicherweise die Aufrufe »configure« und »make all«, Java-Projekte mit Ant haben meist die Targets »jar«, »test« und »javadoc«. Die genauen Schritte zum Bauen und Testen der Software sind natürlich abhängig vom Projekt und bedürfen einer passenden Konfiguration.

Abbildung 1: Hudson kommt bei kleinen Projekten auch ohne Sourcecodeverwaltung zurecht. Hier lädt es einen Tarball herunter und kompiliert ihn. Für größere Projekte kennt das Werkzeug Plugins für viele SCM.
Will der Anwender nach dem Bauen und Testen weitere Schritte anstoßen, etwa einen Testlauf oder das Signieren von Paketen, trägt er diese unter »Post-Build Aktion« ein. Aktiviert er den Punkt »Artefakte archivieren«, stellt Hudson die erzeugten Dateien im Web-GUI zum Download bereit. Anwendungen und Bibliotheken stehen damit immer in der neuesten Version zum Testen und Verwenden bereit. Die Ausgaben bestimmter Werkzeuge wie Checkstyle, Javadoc oder Junit bindet Hudson auf Wunsch sogar direkt ins Web-GUI ein. Ebenso kann eine Benachrichtigung per E-Mail an das Team gehen, wenn der Build erfolgreich war oder auf einen Fehler gelaufen ist.
Im Trainingslager
Nach der Konfiguration wagt der Anwender einen Testlauf, indem er den Punkt »Jetzt bauen« anklickt. Im Idealfall läuft das Projekt sauber durch und zeigt wie in Abbildung 2 lauter erfolgreiche Builds. Gerade am Anfang hakt es jedoch, zum Beispiel wegen fehlender Umgebungsvariablen oder mangelhafterAnt- oder Make-Files. Um Fehler zu finden, kann man jederzeit die Ausgabe der Buildwerkzeuge unter Konsolenausgabe anschauen. Bei einigen Konfigurationsfehlern – etwa dem falschen Dateimuster in Abbildung 3 – bietet die Benutzeroberfläche sogar gleich einen Verbesserungsvorschlag an.

Abbildung 2: Auf der Job-Seite sehen Projektverwalter neben dem Status die erzeugten Dateien, Testergebnisse und Java-Dokumentation. Ein Trend zeigt an, wie viele der letzten Builds mit Fehlern abbrachen.

Abbildung 3: Hudsons Web-GUI bietet nicht nur eine Hilfefunktion, es zeigt bei falscher Konfiguration sogar Vorschläge an. Hier hatte ein Anwender einen falschen Pfad zu einer Testspezifikation angegeben.
Lohn der Mühe ist der perfekte Überblick der angelegten Jobs (siehe Abbildung 4). Die Ansicht zeigt sie mit ihrem Status und einem Trend auf Basis der letzten Builds. Für jeden Job verlinkt die Anwendung die erzeugten Dateien, Testdaten sowie erzeugte Dokumentation. Hudson wird damit zum zentralen Werkzeug, um den aktuellen Stand der Entwicklung auf einen Schlag zu erfassen.

Abbildung 4: Die Einstiegsseite von Hudson bietet einen schnellen Überblick über die Jobs und ihre Entwicklungstendenzen. Ein Klick auf eines der »Play«-Symbole rechts in der Jobzeile plant einen neuen Build.
Pass in die Tiefe
Läuft das erste Projekt durch, dürfen Anwender einen Blick auf Hudsons Plugin-Sammlung werfen. Sie enthält Konnektoren an weitere SCM wie Git, Bazaar oder Bitkeeper. Dank der Plugins versteht das Werkzeug auch andere Buildsysteme wie C-Make und N-Ant sowie Testausgaben aus CPP-Unit ebensogut wie solche aus Ant und J-Unit. Um erreichte Ziele zu dokumentieren und zu publizieren, legt der Admin nach erfolgreichen Läufen Tags im SCM an und die Ergebnisse per FTP auf einem Server ab.
Damit der Server bei vielen Jobs nicht in die Knie geht, ist die Last auf mehrere Hudson-Instanzen aufteilbar. Dabei hat ein Masterserver das Sagen und weist die einzelnen Aufträge Hudson-Slaves zu. Unter Linux & Co. geht das besonders einfach, da der Master die Slaves direkt per SSH auf anderen Rechnern startet. Aber auch Kombinationen mit Hudson-Instanzen auf Windows sind möglich. Das Ganze ist die Basis für die Kür der CI-Systeme: plattformübergreifende Projekte. Das hilft die Software gleichzeitig auf verschiedenen Prozessorarchitekturen, Betriebssystemen oder auch nur Linux-Distributionen zu testen.
Noch ein anderer Aspekt ist die Integration von Hudson in die bestehende Entwicklungslandschaft. Wer jederzeit über den Projektfortschritt auf dem Laufenden bleiben möchte, verbindet sich mit dem RSS-Feed, erfährt die Ergebnisse im IRC oder findet sie in seinem Google-Kalender wieder. Andersrum lässt sich Hudson auch von außen steuern, denn neben Plugins für die IDEs Netbeans und Eclipse gibt es auch Clients für die Kommandozeile oder Android.
Solide Mannschaftsleistung
Continuous Integration ist ein probates Mittel, um die Qualität bei der Software-Entwicklung zu verbessern. Mit Hudson hält sich der Aufwand zur Umsetzung im Rahmen, es unterstütz alle typischen Schritte vom Auschecken über das Bauen und Testen bis hin zur Dokumentation und Qualitätskontrolle. Dank des gut gemachten Web-GUI ist die Lernkurve erstaunlich flach, aber auch bei komplexeren Projekten geht Hudson nicht gleich die Puste aus.
Unterstützung bieten dabei neben der integrierten Dokumentation auch die aktive Anwendergemeinde. Sie hilft nicht nur in der Mailingliste, sondern steht auch hinter der eindrucksvolle Liste verfügbarer Plugins. Die präsentieren fertige Lösungen auch für Sonderprobleme wie automatisierte Screenshots oder Benachrichtigung per Twitter. Mit dieser Schaltstelle gewinnen Entwickler mehr Sicht auf das Wesentliche. (mg)
|
Infos |
|---|
|
[1] Hudson: [https://hudson.dev.java.net] [2] Cruise Control: [http://cruisecontrol.sf.net] [3] Apache Gump: [http://gump.apache.org] [4] Carsten Zerbst, “Web-Zentrale: LDAP-Benutzerauthentifizierung für Apache 2 und Tomcat”: Linux-Magazin 05/05, S. 44 [5] Winstone-Servletcontainer:[http://winstone.sourceforge.net] |
|
Der Autor |
|---|
|
Carsten Zerbst entwickelt Individual-Software im CAD- und PDM-Umfeld für die Luft- und Raumfahrtindustrie und den Schiffbau. |






