GitLab CI/CD ============ Einführung ---------- Ziel dieses Projkets ist es eine CI/CD für den DVA-Bericht aufzusetzen. Heutige Projekte werden immer größer und komplexer, weswegen Entwickler möglichst wenig Zeit mit automatisierbaren Prozessen verschwenden wollen. Das Kompilieren und Hochladen von Dateien ist ein typisches Beispiel für eine Aufgabe, die immer wieder mit derselben Befehlsfolge durchgeführt werden muss und recht zeitaufwendig sein kann. Aus diesem Grund ist die Implementierung einer CI/CD-Pipeline eine praktische Lösung, die nicht nur Zeit spart, sondern auch Fehler minimiert und eine konsistente Qualität der Ergebnisse gewährleistet. Da wir im Rahmen des DVA-Praktikums alle zwei Wochen einen mit Sphinx erzeugten Bericht auf unserer RZ-Website erweitern sollen, haben wir uns entschieden, diesen Prozess als erstes Projekt in GitLab zu automatisieren. Demnach soll also nach jedem Push auf den Main-Branch automatisch eine Pipeline getriggert werden, die zuerst ein HTML-File mit Sphinx erstellt und dieses dann auf den RZ-Server lädt. Unsere Pipeline --------------- .. image:: /img/pipeline-overview.png :alt: Pipeline Overview *Abb. 1:* Unsere (erfolgreiche) Pipeline in der GitLab-Übersicht unter dem Menüpunkt **CI/CD - Pipelines**, mit folgenden Eigenschaften: - Status: Metainformationen über die getriggerte Pipeline (Status (passed/failed/canceled/pending), Dauer, Zeitpunkt des Triggers) - Pipeline: Die Commitnachricht, welche die Pipeline angestoßen hat, zusammen mit der Pipeline-ID, dem Target-Branch, der Commit-ID und zusätzlichen (optionalen) Tags, wie z.B. *latest* oder *stuck* - Triggerer: Der GitLab-Benutzer, der verantwortlich für das Auslösen der Pipeline zuständig war - Stages: Die verschiedenen Abschnitte der Pipeline .. image:: /img/pipeline-detail.png :alt: Pipeline Detail *Abb. 2:* Durch Drücken auf die Pipeline-ID öffnet sich eine Detailansicht der jeweiligen Pipeline. Hier gibts es auch wieder verschiedene Möglichkeiten: - Oben werden nochmal die verschiedenen Pipeline-Informationen angezeigt, wie in der Übersicht - Pipeline: Bietet eine Übersicht über die unterschiedlichen Stages mitsamt deren Status an. In unserem Fall gibt es zweierlei Stages: *build* mit dem Job *sphinx-documentation* (inzwischen *make html*) und *deploy* mit dem Job *upload_html*. Eine Stage kann hier auch mehr als nur einen Job haben - Needs: Hier kann man sog. Needs definieren, welche die Geschwindigkeit der Pipeline erhöhen sollen. Dies war bei unseren Anforderungen und der geringen Komplexität der Pipeline nicht notwendig. - Jobs: Zeigt alle Jobs einer Pipeline an, einschließlich ihres Status unnd der Ausführungszeit. Hier kann man auch den Job-Log betrachten - Tests: Dort werden die Testergebnisse für die Pipeline-Jobs festgehalten, bei fehlgeschlagenen Tests kann man diese im Detail anschauen und den Grund des Scheiterns diagnostizieren .. image:: /img/pipeline-log.png :alt: Pipeline Log *Abb. 3:* Das komplette Log der (erfolgreichen) Stage **sphinx-documentation**, woraufhin die Sphinx HTML-Datei innerhalb _build/html gebaut wird. Das Zielverzeichnis wird im Makefile konfiguriert. Vorgehen -------- Zu Beginn des CI/CD-Projekts stießen wir auf das Problem des GitLab-Runners, welcher für das Triggern der Pipeline verantwortlich ist, wie im Tutorial (:numref:quellen) erwähnt wurde. Hierfür gibt es zwei Möglichkeiten, damit umzugehen: Jeder kann seinen eigenen Runner lokal einrichten und hochladen, oder man hostet *einen* Runner auf *einem* Server, der von allen benutzt werden kann. Obwohl die Lösung über einen zentralen Server attraktiver ist, traten bei dessen Umsetzung einige Probleme auf: 1. Es ist nicht möglich, von einem eigenen Server auf https://gitlab.informatik.hs-augsburg.de/ zuzugreifen. #. Auf dem Hochschulserver können wir nichts installieren, ohne Root-Rechte zu haben. Aus diesen Gründen haben wir uns gezwungenermaßen für die lokale Implementierung entschieden. Es gibt verschiedene Möglichkeiten zur Installation und Einrichtung des Runners, woraufhin wir uns für die Installation über Docker entschieden. Der Grund dafür ist einfach: Wir nutzen verschiedene Betriebssysteme und können so alle dem gleichen Vorgehen folgen und diesen Bericht Betriebssystem-neutral schreiben. **Im Folgenden beschreiben wir wie eine Lokale Installation eines Gitlab-Runners möglich ist:** Folgender Code muss hierbei im Projekt-Root ausgeführt werden: .. code-block:: bash docker run -d --name gitlab-runner --restart always \ -v gitlab-runner-config:/etc/gitlab-runner \ -v /var/run/docker.sock:/var/run/docker.sock \ gitlab/gitlab-runner:latest Damit ist der Runner installiert und lokal aufgesetzt. Der nächste Schritt besteht darin, den Runner in GitLab zu registrieren. **Im Folgenden beschreiben wir wie eine lokaler Gitlab-Runner in gitlab registriert werden kann:** Um dies zu bewerkstelligen, muss wiederum im Projekt-Root ausgeführt werden: .. code-block:: bash docker run --rm -it -v ./gitlab-runner-config:/etc/gitlab-runner gitlab/gitlab-runner register Dieser kommt mit einigen Fragen (eine art wizzard). Wichtig ist hierbei das als executor "shell" gewählt wird. Wenn alles gut läuft ist der Runner nun in GitLab registriert. Dies kann man einsehen unter: Settings -> CI/CD -> Runners (Expand) Um eine Pipeline zu definieren, benötigt man desweiteren eine **.gitlab-ci.yml**. Dies ist das von Gitlab standartisierte Config-file für Pipelines. Eine darin definierte Pipeline wird entweder automatisch durch einen Push, oder durch manuelles Triggern ausgeführt. Dies nahm uns den Wunsch des automatisierten Triggerns direkt ab. Da sich unser Anliegen auf zwei wesentliche Befehle beschränkt, ist der Umfang des Files jedoch sehr klein. 1. make html #. upload html to server Soweit so gut, jedoch traten bei uns erneut komplikationen auf, denn nach unserem nächsten Commit bekamen wir die Meldung, dass wir keine gültigen Runner haben. Dies liegt daran, dass der Runner standardmäßig nur Commits mit Tag nimmt. Nach einer kleinen Anpassung, welche direkt in GitLab möglich ist, lief unsere Pipeline jedoch und failte wie erwartet am Code in der *.gitlab-ci.yml*. Der Grund hierfür war jedoch anders als erwartet: Unser Runner enthielt weder make, python/pip, sphinx, noch irgendetwas anderes. Erwartet hatten wir einen Fail beim Login zum RZ-Server. Um unserem Runner die nötigen Tools nun zu geben, sind wir auf folgende Lösungsmöglichkeiten gestoßen: 1. Ein eigenes Docker-Image aufsetzen und dieses für den Runner nutzen. #. "Gehackte" Lösung: Die Tools manuell beim Runner installieren: Die bessere Lösung wäre die erste, da dies jedoch den Rahmen dieses CI/CD-Projekts sprengen würde, einigten wir uns darauf, diese Lösung, bzw. Docker im Allgemeinen als nächstes Projekt in Angriff zu nehmen. Dies bedeutet wiederum, dass wir vorerst die "gehackte" Lösung nutzen. Hierfür führten wir die folgenden Befehle im Runner aus: .. code-block:: bash docker exec -ti gitlab-runner /bin/bash apt-get update apt-get install make python3 python3-pip rsync pip3 install sphinx su gitlab-runner ssh-keygen #and answer interactive questions ssh-copy-id matze_@login.rz.hs-augsburg.de exit exit docker restart gitlab-runner Daraufhin lief unsere Pipeline durch und committete das erste html auf den RZ-Server. Fazit ----- Durch die Implementierung einer CI/CD-Pipeline auf GitLab können wir in Zukunft wertvolle Zeit sparen, die sonst durch repetitive Aufgaben verloren gehen würde. Natürlich ist das Thema CI/CD viel größer als das, was wir hier erreicht haben, aber unser Ziel einer voll funktionsfähigen Pipeline wurde erfolgreich umgesetzt. Wir haben verschiedene Herausforderungen gemeistert und unterschiedliche Lösungsansätze erarbeitet, was uns allen viel Spaß gemacht hat. Als nächstes werden wir uns dem Thema Docker widmen, um unsere Pipeline zu verbessern und unser Verständnis für Docker zu vertiefen. Wir freuen uns darauf, weitere Schritte zu unternehmen, jene CI/CD-Pipeline noch effizienter und funktionsreicher zu gestalten. .. _quellen: Literaturangaben / Quellen -------------------------- https://docs.gitlab.com/ee/ci/quick_start/ https://docs.gitlab.com/runner/install/ https://docs.gitlab.com/runner/install/docker.html https://docs.gitlab.com/runner/register/index.html