Mein neuer Butler

JenkinsSo einen Butler zu haben ist gar nicht schlecht. Er kocht, wäscht, macht den Haushalt, serviert Abends den Whisky, und sorgt so nebenbei auch für ständige Integration. Vielleicht so eine Mischung aus dem unnachahmlichen Jeeves und Lurch Adams, nur mit etwas besseren Manieren als letzterer. Aber das kann man sich nicht immer aussuchen. Oder doch?

Jenkins ist irgendwie anders. Er werkelt stumm im Hintergrund, erledigt zuverlässig seine Arbeit, und wann immer ich ihn frage, wie es denn um meinen Haushalt bestellt ist, gibt er bereitwillig Auskunft. Er kann viele Aufgaben erledigen, behält stets den Überblick, und kostet fast nichts. Ihr ahnt es schon: Jenkins ist kein menschlicher Butler. Er ist ein Continuous Integration Server.

Am Anfang war der “Make”

Wer über einen längeren Zeitraum ein Programm entwickelt oder auch nur pflegt, ist eigentlich immer mit dem Wunsch konfrontiert, hier und da mal eine neue Version herauszugeben. Insbesondere wenn eine Testabteilung existiert, legen die Kollegen Wert darauf, jeweils den neuesten Code zum Testen zu bekommen. Das ist verständlich, bereitet uns aber in der Regel zusätzliche Arbeit. Daher wird sich der eine oder andere bereits überlegt haben wie man das automatisieren kann, denn schließlich sind wir Programmierer und damit … stinkfaul!

Die Notwendigkeit, einen Compiler anzuwerfen und die Objectfiles danach dem Linker zu übergeben, besteht heute wohl nicht mehr. Gerade in integrierten Entwicklungsumgebungen wie Visual Studio ist das Erzeugen einer ausführbaren Datei nur ein paar Mausklicks entfernt. Mit etwas Glück wird auch die Build-Nummer automatisch hochgesetzt (und landet dann unweigerlich irgendwann in der Quellcodeverwaltung).  Wenn auch noch ein Setup gebaut werden muss, kommt das nächste Tool dran. Und auch wenn dieses ebenfalls nur wenige Klicks erfordert, ist die Kette noch nicht zu ende, denn wir müssen das fertige Setup danach an eine Stelle im Netzwerk legen, wo die Tester es finden. Nervig, oder? Da kann man schon mal etwas vergessen, und sei es nur die anfänglich erwähnte Buildnummer. Dann geht alles wieder von vorn los.

Das ist mir nicht nur einmal passiert. Daher habe ich mich vor längerem bereits mit dem Tool “Make” beschäftigt. Damit kann man kurz gesagt ein Regelsystem aufbauen, das den Buildprozess intelligent steuert. Das bedeutet in diesem Fall, dass nur das übersetzt werden muss, was notwendig ist. Das Makefile bekommt dazu mehrere Tripletts der folgenden Form mitgeteilt:

ziel: quelle(n)
    bauanleitung

Das Ziel ist eine generierbare Datei (z.B. eine EXE), die Quelle (oder die Quellen) ist oder sind die Dateien, von denen das Ziel direkt abhängig ist, und die Bauanleitung besteht aus einer oder mehreren Anweisungen, die ausgeführt werden müssen, um das Ziel zu erstellen. Make überprüft nun die Ziele und Quellen der Reihe nach. Immer dann, wenn ein Ziel älter ist als eine der zugeordneten Quellen (oder gar nicht existiert), werden die Befehle der Bauanleitung ausgeführt. Jeder der Quellen kann dabei selbst ein Ziel sein, wodurch der Prozess dann in mehreren Schritten abläuft. Wenn eines der Kommandos einen Returncode ungleich 0 zurück gibt, bricht der Makeprozess ab.

Abgesehen vom anfänglichen Erstellen eines solchen Makefiles reduziert sich damit der Aufwand auf das Starten dieses Prozesses, das Warten auf das Ergebnis und das Überprüfen desselben. Ein guter erster Schritt.

Hätten wir nun einen Butler, der auch das noch für uns übernimmt, dann könnten wir uns wieder völlig auf das konzentrieren, was uns am meisten Spaß macht: Das Programmieren. Und hier betritt Jenkins die Bühne.

Continuous Integration

Jenkins (und andere ähnliche Programme) kümmern sich um die Abarbeitung solcher Schritte wie vorstehend beschrieben. Ein Makefile ist nicht zwingend erforderlich, aber wenn es ohnehin schon existiert, kann man davon profitieren. Das Ergebnis wird dann schön übersichtlich auf einer Website präsentiert, und im Fehlerfalle gibt es Informationen, wie es zu dem Fehler kommen konnte. EMails, RSS-Feeds und andere Benachrichtigungsformen runden das Angebot ab. Dadurch arbeitet Jenkins, wie anfänglich beschrieben, vollständig im Hintergrund und nimmt uns diese lästige Routinearbeit ab.

Doch woher weiß Jenkins, dass es wieder Arbeit für ihn gibt? Schließlich rührt ein Koch auch nur dann die Suppe um, wenn auch welche im Topf ist. Jenkins kennt gewisse Regeln, mit denen er entscheiden kann, ob ein neuer Build erforderlich ist. Es ist zum Beispiel möglich, mit dem Mercurial-Plugin ein bestimmtes Repository anzurufen. Nur dann, wenn sich hier etwas verändert hat (also z.B. der “tip” einen anderen Hashwert aufweist), wird der eingerichtete Buildprozess angestoßen. Ist das nicht der Fall, legt sich Jenkins wieder schlafen oder kümmert sich um seine anderen Aufgaben. Das alles muss nicht auf seinem eigenen Server geschehen. Durch einen Slave-Prozess kann die Kommunikation über das Netzwerk auch mit anderen Rechnern aufrechterhalten werden, auf denen die entsprechenden Compiler laufen. Jenkins und seine Sklaven sind in Java geschrieben, laufen also auf allen gängigen Plattformen.

Ähnliche Artikel:

1 Ping

  1. […] zu konzentrieren: Die Entwicklung. Wenn ich dann noch ein Continuous-Integration-System wie z.B. Jenkins oder Bitbuckets „Pipelines“ (leider nicht für Windows) zur Verfügung habe, spare ich […]

Schreibe einen Kommentar

Deine Email-Adresse wird nicht veröffentlicht.

13 − eins =