Sich wiederholende Aufgaben sind mühselig und fehleranfällig, wenn sie von Hand ausgeführt werden. Im August befasst sich IT-Administrator deshalb mit dem ... (mehr)

Skript-Umgebung festlegen

Die Auswahl des sogenannten Executors entscheidet über die Umgebung, in der der Runner später ausgeführt wird. Gitlab unterstützt sechs Technologien zum Ausführen der Skripte: Shell, Docker, Parallels, VirtualBox, SSH und Kubernetes. Am einfachsten ist es, den Runner als Shell-Executor direkt auf dem System laufen zu lassen oder per SSH-Executor auf einem entfernten System. Der Executor selbst läuft dann als normaler Prozess. Im Gegensatz zu den anderen Executor-Typen lassen sich Abhängigkeiten einmal zu Beginn auflösen und das System entsprechend konfigurieren. Wichtig hierbei ist aber zu beachten, dass alle Befehle innerhalb dieses Containers als Benutzer root ausgeführt werden.

Leider lässt sich mit den beiden Runnern immer nur auf die bereits existierende Build-Umgebung zugreifen. Ein sauber definierter Zustand der Maschine lässt sich durch Bordmittel in diesem Szenario nicht gewährleisten und muss durch die ausgeführten Skripte selbst sichergestellt werden. Alte Einträge in einer Datenbank, die durch einen Abbruch eines vorherigen Durchlaufs nicht entfernt wurden, können dann beispielsweise die fehlerfreie Ausführung dauerhaft verhindern.

Die übrigen Executor-Typen stellen zu Beginn einer jeden Ausführung den vorher definierten Ausgangszustand der Umgebung her. Der Docker-Executor lädt in der Standard-Konfiguration sogar jedes Mal den gesamten Container von dem angegebenen Docker-Repository. Um Bandbreite zu reduzieren oder Zeit zu sparen, lässt sich dieses Verhalten jedoch in der Runner-Konfiguration ändern. Docker, ebenso wie Kubernetes, erlaubt die Angabe des Basis-Images und der verwendeten Services. Damit können Sie fast beliebige Setups der Umgebung allein durch die spezifische Konfiguration innerhalb eines Repositories verwenden.

Die Auswahl von VirtualBox oder Parallels startet für jeden Durchlauf einen gespeicherten Zustand (Snapshot) der virtuellen Maschine, was in einigen Situationen vorteilhaft sein kann. Dieser Snapshot kann auf jedem System vorbereitet werden. Beachten Sie, dass Sie die Wahl des Betriebssystems auch auf die verfügbaren Kommandos der CI-Skripte festlegt. Während Sie Bash-Befehle unter Windows, macOS, Linux und BSD verwenden können, werden Windows-Batch oder PowerShell-Skripte nur unter Windows ausgeführt.

Kommen wir zurück zur laufenden Konfiguration des Gitlab-Runners: Da wir bereits den Docker-Container für den Runner selbst nutzen, greifen wir auf die einfachste Möglichkeit des Shell-Executors zurück. Dieser erlaubt auch einfaches Debugging, falls Probleme innerhalb der Umgebung auftauchen, und eignet sich daher sehr zum Kennenlernen der CI-Möglichkeiten. Der fertig konfigurierte Runner wird anschließend auf der Projektwebseite wie in Bild 2 dargestellt.

Bild 2: Aktive Runner für das ausgewählte Projekt.

Installieren Sie die benötigten Abhängigkeiten für das Beispiel, indem Sie den folgenden Befehl an Docker übergeben:

$ docker exec -it gitlab-runner /bin/bash -c "apt-get update && apt-get install -y build-essential autoconf automake libtool"

CI-Pipeline eines Projekts

Die übliche Pipeline umfasst die Stufen "build", "test" und "deploy". Im Falle eines einfachen Software-Projekts sind die Stufen im Grunde selbsterklärend. Nehmen wir als Beispiel ein einfaches C++ Projekt, das test-driven mit Googles Testframework [3] entwickelt wird. Jede erfolgreich getestete Revision soll dann im Quelltext und als fertig kompiliertes Programm per SFTP auf dem Webserver zur Verfügung gestellt werden. Die Pipeline-Stufen werden sukzessive ausgeführt und auch nur dann, wenn die vorherige Stufe erfolgreich abgeschlossen wurde. Scheitert also schon die Kompilierung der Quellen, lässt sich natürlich gar kein Test des Programms durchführen. Die Bereitstellung auf der Webseite wird durch die vorherigen Tests abgesichert, sodass nur die Programm-Versionen veröffentlicht werden, die auch fehlerfrei getestet sind.

Für die Tests haben wir ein kleines Projekt für Sie vorbereitet, das Sie unter [4] herunterladen können. Als Abhängigkeiten installieren Sie aktuelle Pakete von gcc, make, autoconf, automake und libtool. Nun extrahieren Sie die Archiv-Datei in das zuvor mit »git clone« vom Server heruntergeladene leere Repository. Bevor Sie weitere Veränderungen vornehmen, fügen Sie alle Dateien zum Repository hinzu. Dazu führen Sie die folgenden Befehle der Reihe nach durch:

$ git add *
$ git commit -m ''Erster Commit des Testprojekts''
$ git push origin master

Nun muss noch das verwendete Googletest-Framework bereitgestellt werden. Dafür wird es als submodule zum Git-Repository und der Unterordner der Datei ".gitignore" hinzugefügt:

$ git submodule add https://github.com/google/googletest.git lib/googletest
$ echo "lib/googletest" > .gitignore
$ git commit -m ''Hinzufügen von googletest als Submodule''
$ git push

Jetzt können Sie das Projekt lokal vorbereiten, kompilieren und testen. Dazu verwenden Sie die folgenden Befehle und sollten die Ausgabe wie in Bild 3 erhalten:

$ autoreconf -i
$ ./configure
$ make
$ make check
Bild 3: Erfolgreiche Ausführung der Tests.

Wenn das geklappt hat »(make install« ist allein für diesen Test nicht notwendig), lassen sich die Vorbereitungen für die automatische Verarbeitung mittels Gitlab-CI treffen. Dafür räumen Sie das aktuelle Verzeichnis erst einmal wieder etwas auf, indem Sie mit dem folgenden Befehl alle nicht zum Repository gehörenden Dateien entfernen:

$ git clean -f -d

Benennen Sie nun vor dem Öffnen die bereits vorbereitete Datei .gitlab-ci.yml. dist in .gitlab-ci.yml um:

$ git mv .gitlab-ci.yml.dist .gitlab-ci.yml

Bei einem Blick in die Datei erkennen Sie die oben beschriebenen Stufen der Continuous Integration wieder. Bevor diese aber ausgeführt werden, kommen die Befehle der Stufe »before_script« zum Einsatz. Diese bereitet die Build-Umgebung auf dem Runner-System vor. Die Befehle sind im Grunde dieselben, die Sie weiter oben bereits für die lokalen Tests durchgeführt haben. Den Ordner "m4" legen wir nun explizit an, da »autoreconf -i« als letztes Kommando der Stufe sonst mit einem von 0 verschiedenen Rückgabewert beendet wird, weil der Ordner nicht existiert und eine Warnung ausgegeben wird.

Dem oben skizzierten Ablauf der Entwicklungs-Stufen folgend definiert die Datei die drei Stufen "build", "check" und "deploy". Die Reihenfolge bei der Angabe definiert auch die Reihenfolge der Ausführung und damit die Abhängigkeit der Stufen untereinander. Darunter werden die einzelnen Jobs definiert. Die Angabe der Tags in den Job-Definitionen dient der Auswahl geeigneter Runner für diesen Job. In der Vorbereitung haben Sie die Tags gcc und gtest für den Runner vergeben. Daher verwenden wir diese Tags nun auch für die Jobs. Die Kommandos zum Kompilieren und Testen kennen Sie bereits, »make dist« erstellt zum Abschluss ein Archiv zur Verteilung der Software.

Üblicherweise würde nach dem Befehl noch der Upload des erstellten Archivs auf den Webserver folgen. Dafür können Sie beispielsweise »curl« nutzen und damit entweder per FTP oder auch über ein HTML-Formular die Daten hochladen. Gitlab bietet aber auch an, während der Jobs erstellte Artefakte, wie eben das Software-Archiv, direkt im Gitlab als Download anzubieten. Diese Möglichkeit können Sie mit den Voreinstellungen direkt ausprobieren.

Besuchen Sie nun die Pipeline-Übersicht Ihres Projekts in der Gitlab-Oberfläche. Sie finden die Artefakt-Downloads auf der rechten Seite. Wählen Sie nun die Pipeline für den letzten Commit aus und überprüfen Sie den Status der einzelnen Stufen. Wenn alles ohne Fehler durchgelaufen ist, zeigt Ihr Browser den Erfolg an.

Das erste Beispiel ist damit erfolgreich abgeschlossen. Nehmen Sie sich die Zeit, auch die anderen Executor-Typen einmal auszuprobieren. Je nachdem, welche Anforderungen Sie an eine CI haben, erlauben vor allem die Container-basierten Typen eine optimale Skalierung, vor allem hoch frequentierter Gitlab-Systeme. Falls Sie den Docker-Container nun beenden möchten, können Sie dies mit dem folgenden Befehl tun: Wenn Sie das zweite Beispiel mit dem Testsystem ausprobieren möchten, führen Sie ihn einfach zum Abschluss ihrer Tests aus (alle Daten in dem Gitlab werden dann gelöscht):

$ docker stop gitlab && docker rm gitlab

Ähnliche Artikel

comments powered by Disqus
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Konfigurationsmanagement

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit CFengine
  • mit dem Nix-System
  • mit Containern
  • mit anderer Konfigurationsmanagement-Software

Ausgabe /2023