Softwareentwicklung im Team – Teil 6 – Nightly Builds

Zeit ist ein knappes Gut. Da kann man noch so gute Vorsätze haben, aber manchmal vergisst man einfach sich daran zu halten. Was jetzt auch als Entschuldigung gelten könnte, dass der letzte Artikel dieser Serie bereits neun Monate zurück liegt, so zielt meine Einleitung aber doch eher auf Unit-Test und das einchecken von Sourcen ab.
Zu den Unit-Tests: Im hektischen Alltag werden eh meist zu wenige geschrieben und die die existieren werden von den Entwicklern auch eher nur sporadisch ausgeführt. Das hat unter anderem zur Folge, dass Unit-Test mit der Zeit veralten, weil sie beim refactorn gerne vergessen werden. Anstatt sie dann anzupassen, werden dann auf Grund mangelnder Zeit die fehlgeschlagenen Tests einfach gelöscht oder auskommentiert.
Das man Unit-Test nicht mit jedem Compile-Vorgang ausführt, kann ich nachvollziehen. Insbesondere wenn das Ausführen der Tests extrem lange dauert. Das Vorsätze, wie die Tests zumindest vor jedem Checkin ausführen zu lassen, sind zwar löblich, werden aber aus diversen Gründen auch nicht immer eingehalten.
Zum einchecken: ein regelmäßiges ein- und auschecken sollte eigentlich selbstverständlich sein. Wenn sich dieser Vorgang im Alltag aber als Tortur herausstellt, weil dabei ständig etwas schief geht und man einen Großteil seiner Arbeitszeit damit verbringt, seinen Build wieder zum Laufen zu bekommen, wird der Kontakt mit dem Versionskontrollsystem auf das Nötigste reduziert und so lange es geht vermieden. Kein Entwickler will sich damit aufhalten, bei Kollegen (die am besten gerade im Meeting oder gar Urlaub sind) darum bitten zu müssen, vergessene Dateien einzuchecken, die für den aktuellen Build nötig sind oder irgendwelche Versionskonflikte aufzulösen (am besten in extrem vielen Dateien und/oder extrem großen Dateien, wo die Änderungen von mehreren Wochen gemergt wurden).

Beide Probleme lassen sich durch sogenannte Nightly Builds lösen. Dafür wird auf einem Server ein Programm installiert, welches sich in definierten Zeitabständen (zum Beispiel immer um Punkt Mitternacht) sich den aktuellen Stand der Sourcen aus dem Versionskontrollsystem holt und dann das Projekt kompiliert (und ggf. noch weitere Aufgaben ausführt), um am Ende einen Report zu erstellen, ob der Build erfolgreich mit dem aktuellen Stand ausgeführt werden kann oder nicht. Beispiele für diese sogenannten Continuous Integration Server (oder CI-Server) finden sich unter http://en.wikipedia.org/wiki/Continuous_integration#Software oder http://confluence.public.thoughtworks.org/display/CC/CI+Feature+Matrix

Hier der ursprüngliche Text dazu:

5a. Problem / Beispiel
Nightly Builds
Den Build nachts automatisch durchlaufen lassen. Sobald ein unabhängiger Buildprozess etabliert ist, sollte das kein Problem darstellen. Dadurch wird vermieden, dass man eine Version aus dem SVN holt, die nicht mehr lauffähig ist (z.B. weil vergessen wurde, etwas einzuchecken).
Darüber hinaus können gleichzeitig automatisch weitere Tools ausgeführt werden, die zur Code verbesserung beitragen können.

Lösungsvorschlag
Hudson (https://hudson.dev.java.net/) erneut aufsetzen und die aktiven Projekte einpflegen.
Darüber hinaus würde es sich anbieten gleichzeitig Checkstyle (http://checkstyle.sourceforge.net/) durchlaufen zu lassen, um zu überprüfen, ob wirklich die JavaDocs vorhanden sind.
Weitere Tools, die automatisiert ablaufen könnten ( / sollten): PMD, Findbugs, Unit-Tests, JavaNCSS

Vorteile
– keine “broken builds” mehr auf den lokalen Rechnern, nach einem SVN-Update
– Überprüfung, ob Kommentierung vorhanden ist
– statische Codeanalyse (z.B. wird unbenutzter Code wird erkannt, Auffinden von Code-Dupletten, etc.)
– nettes Gimmick: automatische Metriken über den Code (z.B. Anzahl der Zeilen, etc.)

Nachteile / Probleme
– Entwickler sollten die Seite regelmäßig besuchen, um entsprechende Reporte zu lesen/überfliegen

Aufwand
– ist ein unabhängiger Buildprozess etabliert, lässt sich das innerhalb kürzester Zeit (< 3 Stunden) aufsetzen

Rückblickend gesehen…
Wir haben damals einen Hudson aufgesetzt, der auch immer noch im Einsatz ist. Während ich vor dieser Zeit ohne CI-Server in einigen Wochen bis zu 20% meiner Arbeitszeit aufgewendet habe, um den Build wieder zum laufen zu bekommen, so ist dieser Anteil nach der Einführung von Hudson nahezu gegen 0 gegegangen. Vor dem auschecken langte früh morgens ein Blick in die Mails, um zu sehen, ob Hudson wegen eines fehlgeschlagenen Builds ein Warnung rausgeschickt hat und falls das der Fall war, bat man den Kollegen, der den Fehler verursacht hatte, diesen zu beheben und man arbeitete in der Zwischenzeit an seiner (immer noch funktionierenden) lokalen Kopie des Projektes weiter.
Alles in allem war man sich einig, dass Hudson durchaus sinnvoll sei und wurde durchaus positiv aufgenommen. Allerdings war die Involvierung der Mitarbeiter respektive die Intesität der Nutzung von Hudson durchaus unterschiedlich. Einige schienen sich darauf zu beschränken, den Build funktional zu halten und Hudsons Dienste nur dann in Anspruch zu nehmen, wenn der Nightly-Build mal wieder fehlschlug. Die erzeugte Reporte von Checkstyle, PMD, Findbugs und CPD wurden von einigen vielleicht zur Kentniss genommen, aber weitestgehend ignoriert.
Auch wenn der einzige Nachteil, den ich damals aufgelistet habe, durchaus seine Berechtigung hatte, überwiegten dennoch die Vorteile, so dass sich der Aufwand auf jeden Fall gelohnt hatte.

In ein paar Probleme sind wir allerdings auch gelaufen. Während alle Entwickler auf Windows arbeiteten, lief unser CI-Server auf einem Linux-System. Das brachte ein paar Probleme mit sich (allen voran Berechtigungsprobleme, wenn ich mich recht erinnere), die aber nicht weiter gravierend waren.
Ein viel größeres Problem, kann die immense Flut an Mails werden, wenn der oder die Build(s) über längeren Zeitraum nicht stabil sind und/oder fehlschlagen. Wenn man jeden morgen 8 Mails von Hudson in seinem Postfach hat und das über mehrere Wochen hinweg, so wird man diese irgendwann einfach ignorieren. Eine Warnung heißt ja nicht zwangsläufig, dass der Build fehl schlägt. Vielmehr können die anderen Tools, wie z.B. Checkstyle durch das überschreiten eines gewissen Grenzwertes an Regelverletzungen eine Warnung auslösen und den Build als “instabil” kennzeichnen. Zwar könnte man die Grenzwerte für das auslösen einer Warnung hochsetzen, aber dann kann man genauso gut die Mails ignorieren, die Hudson einem schickt.

Eine kleine Anekdote noch dazu. Als ich die ersten Projekte in Hudson eingerichtet hatte und am darauffolgenden Tag ins Büro kam, war unser technischer Leiter ein wenig getresst, weil die Backups in der Nacht nicht richtig gezogen  worden konnten oder weil das SVN zerschossen war und ein Backup wieder eingespielt werden musste. So genau weiß ich das nicht mehr. Auf jeden Fall kollidierten die Zeiten des Hudson-Builds mit denen des Backups, so dass es dort krachte. Als wir die Zeiten aufeinander abgestimmt hatten, gab es keine weiteren Probleme mehr.

Mit Hudson haben wir auch ein weiteres Problem gelöst, welches wir hatten:

5b. Problem / Beispiel
Änderungen sind für Nicht-Entwickler nicht sofort sichtbar / verfügbar
Sobald ein Entwickler Änderungen ins SVN eincheckt, sind diese zwar für die anderen Entwickler nach einem SVN-Update verfügbar, nicht aber für die anderen Mitarbeiter. Diese müssen darauf warten, dass eine neue Version entsprechend auf dem Test-Server deployt wird.
Unschön ist dies insbesondere dann, wenn ein Entwickler im Bugtracking-System einen Fehler als behoben markiert, dieser aber wieder neu geöffnet wird, weil die Änderung auf dem Testserver noch nicht nachvollzogen werden kann. Resultat ist ein unnötig erhöhter Zeitverbrauch (Bugtracker-Einträge müssen mehrfach überprüft werden, Entwickler müssen Feedback geben, warum die Änderung noch nicht verfügbar ist, etc.)

Lösungsvorschlag
Man kann den erfolgreichen Nightly-Build automatisch auf einen Test-Server deployen.

Vorteile
– Änderungen sind mit höchsten 24 Stunden Verzögerung für alle sichtbar

Nachteile / Probleme
– PermGen-Space-Problematik. Ggf. kann der Tomcat vor dem deployen automatisch neu gestartet werden.

Aufwand
– ?

Der Aufwand war relativ gering. Mittels Cron-Job haben wir nachts den Server einmal gestartet, weil sonst der Speicher voll gelaufen wäre, aber das war’s auch schon. Und wie erwartet nahm die Fragerei deutlich ab.

Zusammenfassung

Wie dem Text unschwer zu entnehmen ist, halte ich einen CI-Server für unverzichtbar. Auch für meine privaten Projekte, wo ich alleine dran sitze, verwende ich Hudson. Und ich wurde bereits mehr als einmal darauf hingewiesen, dass meine Unit-Test fehlgeschlagen sind ;-)

4 Gedanken zu „Softwareentwicklung im Team – Teil 6 – Nightly Builds“

  1. Hallo,
    ich habe gerade Euer Blog gefunden und finde es sehr gut. Freue mich schon auf weitere Artikel.
    Viele Grüsse,
    Mo

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>