Ein Buildserver ist praktisch im Alltag. Doch was macht ihn aus und welche Vorteile werden geboten? In diesem Artikel gebe ich einen ersten Einblick.

Einleitung zu Buildservern

Ein Buildserver ist, wie der Name schon sagt, ein Server, welcher dazu da ist, etwas zu bauen. In der Regel wird unter „bauen“ das Erstellen bzw. Kompilieren von Programmcode verstanden. Das Ergebnis kann anschließend weiterverarbeitet werden.

In der einfachsten Variante besteht ein Buildserver aus einem Skript, das regelmäßig ausgeführt wird. Dieses Skript enthält Befehle, um Code aus einem Versionierungssystem auszuchecken, zu kompilieren, Tests auszuführen usw.
Im Kern automatisieren sie die Abläufe, welche der Entwickler oder Endanwender per Hand durchführt.

Buildserver werden als Open Source und als kommerzielle Lösung angeboten. Meistens beinhalten Sie Komfortfunktionen und die Möglichkeit durch Plugins die Funktionen zu erweitern.

Der Mehrwert

Ein Buildserver kann, je nach Verwendungszweck, verschiedene Mehrwerte bieten. Die typischen sind meiner Meinung nach:

  • Maschinenunabhängigkeit
  • Automatische Testausführung
  • Continuous Integration
  • Automatische Veröffentlichungen
  • Kompilieren in verschiedenen Umgebungen
  • Konfiguration im Repository

Maschinenunabhängigkeit

Jeder Entwickler hat bestimmt den folgenden Satz gehört oder ausgesprochen: „Bei mir funktioniert alles ohne Probleme.“

Leider habe ich schon sehr oft die Erfahrung machen müssen, dass ein einfaches git clone und anschließendes Kompilieren nicht funktioniert. Warum? Dafür kann es viele Gründe geben.
Abhängigkeiten wurden nicht gefunden. Es müssen bestimmte Programme installiert werden (was nicht dokumentiert ist). Irgendwelche DLLs wurden aus irgendwelchem Verzeichnissen kopiert und verwendet.

Der Buildserver deckt solche Fehler auf. Je nach Fehler, reicht ein einfaches Skript, um beispielsweise Bibliotheken zu kopieren. Dabei sollten die verwendeten Bibliotheken im Repository zur Verfügung stehen. In komplexeren Fällen muss eine Dokumentation erstellt und auf die Installation bestimmte Programme hingewiesen werden. Ohne einen zweiten Computer (vergleichbar mit dem 4-Augen Prinzip) fallen solche Fehler gerne unter den Tisch.

Automatische Testausführung

Die Softwaretests werden regelmäßig ausgeführt. So kann im laufenden Betrieb schnell erkannt werden, ob der aktuelle Quellcode funktioniert oder potentielle Fehler beinhaltet.

Unit Tests sind gut und werden aufgrund der kurzen Ausführungszeit (hoffentlich) regelmäßig vom Entwickler ausgeführt. Es kann aber auch Tests geben, die eine längere Ausführungszeit haben. Der Server kann so den Entwickler entlasten, indem diese Tests beispielsweise abends ausgeführt werden. Dadurch werden Fehler im laufenden Betrieb gefunden.

Continuous Integration

Ein Buildserver ermöglicht Continuous Integration. Das bedeutet, dass Software kontinuierlich kompiliert, ausgeführt, getestet und veröffentlicht wird. Der aktuelle Programmcode inkl. Bugfixes und Neuerungen wird so laufend in der produktiven Umgebung bereitgestellt.

Meistens werden Buildserver auch CI-Server genannt. Bei dieser Methode wird der Quellcode nach jedem check-in (Speichern des aktuellen Codes im Versionierungssystem) geladen und das Skript (kompilieren, test, veröffentlichen) ausgeführt.

Meist können verschiedene Bereiche definiert werden. Die erste Veröffentlichung erfolgt beispielsweise immer in eine Testumgebung. Wenn die Tests in Ordnung sind, wird das Programm in einer Integrationsumgebung getestet. Sobald dieser Status ebenfalls in Ordnung ist, veröffentlicht der Server die Anwendung in den produktiven Betrieb.

Automatische Veröffentlichungen

Bei erfolgreichem build kann der Server das Ergebnis direkt bereitstellen. Dies kann beispielsweise eine Click-Once Installation oder eine Webseite sein. Hier liegt der große Vorteil darin, dass auch Neulinge in einem Projekt nichts falsch machen können, da es nur einen Weg gibt.

Beispielsweise sind auch automatische Veröffentlichung auf Nuget möglich. Neue Versionen können so direkt kompiliert, getestet und auf einem Nuget-Server für alle Beteiligten veröffentlicht werden.

Kompilieren in verschiedenen Umgebungen

Buildserver bieten i.d.R. die Möglichkeit Remote-Worker oder Agents einzurichten. Dadurch kann ein Projekt beispielsweise auf verschiedenen Betriebssystemen kompiliert und getestet werden.

Als Beispiel wird eine Anwendung für Windows, Linux und Mac kompiliert. Der Buildserver organisiert die Agents, sodass das Script auf drei Computern ausgeführt wird. Das Ergebnis wird anschließend weiterverarbeitet.

Konfiguration im Repository

Zu guter Letzt, kann die Konfiguration als Datei im Projekt selbst gespeichert werden. Somit sind Änderungen an der Konfiguration transparent nachvollziehbar. Falls Änderungen notwendig sind, können diese ohne direkten Zugriff auf den Bildserver durchgeführt werden.

Welchen Nachteil bieten Buildserver

Neben den ganzen Positiven Aspekten möchte ich die Nachteile nicht vernachlässigen. Aus meiner bisherigen Erfahrung sind nur wenige zu nennen:

  • Hoher Konfigurationsaufwand
  • Überladung durch Plugins
  • Längere Ausführungsdauer als lokal
  • Zwang zu Disziplin

Hoher Konfigurationsaufwand

Vor allem Anfangs gibt’s einen hohen Konfigurationsaufwand. Ggf. muss der Server eingerichtet und notwendige Frameworks und Programme installiert werden. Für neue Projekte bietet es sich an, eine Vorlage zu entwickeln. Diese wird dann nur noch projektspezifisch angepasst.

Im laufenden Betrieb wird der Konfigurationsaufwand sinken, anfangs kann es durchaus ein paar Tage dauern bis alles rund läuft.

Überladung durch Plugins

Plugins erweitern den Funktionsumfang. Zu viele Plugins können die Laufzeit des Servers oder Buildvorgänge negativ beeinflussen. Es kann Kompatibilitätsprobleme zwischen Plugins geben oder auch Sicherheitslücken, welche den Server angreifbar machen.

Längere Ausführungsdauer als lokal

Meistens dauert der Prozess länger, als die lokale Ausführung. Dafür findet die Arbeit parallel statt und der Entwickler erhält Sicherheiten und Komfortfunktionen.

Zudem können weitere Aktionen wie Analysen und Trends durchgeführt werden, was lokal meist nicht geschieht.

Zwang zu Disziplin

Der Server verlangt eine gewisse Disziplin. Tests sollten so schnell wie möglich korrigiert werden. Zudem gibt der Prozess einen gewissen Weg vor, wie gearbeitet (bzw. veröffentlich) wird.

Alle Entwickler eines Projekts müssen sich daran halten. Es wird mühselig für den Entwickler wenn ständig Scripte angepasst oder erweitert werden müssen. Der klare Vorteil liegt aber darin, dass im Projekt alle relevanten Dateien eingebunden werden, sodass der Code überall ausführbar ist.

Was kann schief laufen?

Aus eigener Erfahrung gibt es meist drei Hauptprobleme:

  • Die Scripte oder Konfiguration des Buildservers werden ständig verändert
  • Software wird ständig de-/installiert oder geändert
  • Programmpfade oder Systemvariablen wie PATH werden geändert

Diese lassen sich nach meinem Verständnis unter einem Begriff zusammenfassen: Spielwiese. Daher das Wort „ständig“. Ich habe es leider bereits erleben müssen, dass das Ergebnis eines Build reiner Zufall war.

Was war der Grund dafür?

Meistens konnten externe Abhängigkeiten z.B. zu `dotnet`, `msbuild`, `npm` oder `nuget` plötzlich nicht mehr gefunden werden konnten. Es hatten sich PATH-Variablen geändert oder es wurden neue Versionen installiert, wodurch sich die Syntax änderte.

Es ist schwierig einen Buildserver ernsthaft zu verwenden, wenn das Umfeld ständigem Wandel unterliegt. Ein Computer vom Entwickler kann durchaus stärkerem Wandel unterliegen, aufgrund von Frameworks, Updates, neuen IDE-Versionen etc. Ein Buildserver hingegen soll eine stabile Umgebung darstellen.

Ich habe es sogar einmal erlebt, dass ein Build plötzlich nicht mehr funktionierte, weil die Codeanalyse nicht ausgeführt werden konnte. Ohne Änderungen meinerseits oder an der Projektkonfiguration wurden manche Projekte grundlos rot.

Wie kann man Probleme umgehen

Da ich das Hauptproblem an der „Spielwiese“ sehe, lässt sich dies nur durch klare Regeln und Disziplin lösen. Je nachdem, wer der Server verwaltet oder wie groß das Team ist, müssen Änderungen am Buildserver immer mit den betroffenen Personen rechtzeitig abgesprochen werden.

Vor allem bei Updates von Programmen oder Frameworks ist die Absprache sehr wichtig. Je nach Anwendung oder Framework können alle Builds davon betroffen sein.

Die größte Herausforderung besteht aus meiner Sicht in der Kommunikation. Sofern Versionen aktualisiert oder die Konfiguration eines Projektes geändert wird, sollte es kurz mit dem Team abgesprochen werden.

Fazit

In diesem Artikel habe ich euch Buildserver vorgestellt. Wir haben die Vor- und Nachteile beleuchtet und potentielle Probleme besprochen. Mittlerweile arbeite ich gerne mit Buildservern, sofern diese stabil laufen. Wie ist eure Erfahrung mit Buildservern? Kompiliert ihr damit nur eure Anwendungen oder habt ihr ausgefallenere Szenarien?


Bildnachweis: Pixabay.com

Bekannte Buildserver:

  • Jenkins (Open Source)
  • Bamboo (Atlassian)
  • Travis CI (Travis CI GmbH)
  • Appveyor (AppVeyor Systems Inc.)
  • TeamCity (JetBrains)
  • Azure Pipelines (Microsoft)