CI/CD
Datum: Februar 2023
Lesedauer: 4 Minuten
Nach dem Lesen dieses Blogposts weisst du, was CI/CD ist und wie man es in Projekten implementieren kann.
Was ist CI/CD?
Continuous Integration / Continuous Deployment ist ein Prozess, bei welchem Code regelmässig und automatisch getestet, gebuildet und auf ein
Repository oder sogar eine Produktionsumgebung gestellt wird.
Durch die Automatisierung wird sichergestellt, dass der Code jederzeit fehlerfrei ist. Zudem kann beim Deployment viel manueller Aufwand gespart
werden, da die nötigen Schritte automatisch ausgeführt werden können.
In den nachfolgenden Zeilen beschreibe ich, wie man dieses Konzept mit GitLab verwenden kann.
.gitlab-ci.yml
Das .gitlab-ci.yml
File ist die CI/CD Konfiguration eines Projektes. Die Datei definiert die Pipelines, Jobs und Umgebungen. Abgelegt wird sie im Root des
Repos/Projekts.
Stages & Jobs
Ein Job ist eine einzelne Aufgabe. Es ist nichts Weiteres als ein Script, welches unter bestimmten Bedingungen und in einer definierten Umgebungen
ausgeführt wird.
Eine Stage ist ein Abschnitt, der gruppierte Aufgaben/Jobs hält. Die Stages definieren, in welcher Reihenfolge welche Arten von Jobs durchgeführt werden.
stages:
- test
- export
- deploy
test-job:
stage: test
image: cypress/base:16.17.0
script:
- echo "Running tests..."
- npm ci
- npm run test
- echo "Tests done."
Einschränkungen
Jobs können so konfiguriert werden, dass sie beispielsweise nur bei Aktionen auf dem master
durchgeführt werden.
only:
- master
Artifacts
Da jeder Job einzeln ausgeführt wird, hat man vorerst keinen Zugriff auf Resultate der vorherigen Scripts. Mit Artefakten kann man aber Outputs zum
nächsten Job übernehmen.
So kann man das Projekt beispielsweise in einem Job exportieren und im nächsten das Resultat dieses Exports deployen.
Genauer beschreiben ist dies hier: https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html (opens in a new tab)
Variables
Variablen sind in CI/CD nicht nur gut zur Speicherung von wiederkehrenden Werten, sondern auch zum Schutz von Passwörtern und Nutzernamen.
Denn solche sensible Daten darf man nicht sichtbar im Script platzieren.
Variablen können auf GitLab definiert werden.
Im Code können diese dann mit einem Dollar Zeichen verwendet werden: $PASSWORD
Runner
Um das vorhin beschriebene .gitlab-ci.yml
File verwenden zu können, benötigt man einen Runner. Ein Runner ist eine externe Maschine, welchen den
Code ausführen kann.
Bei der Erstellung eines Runners kann gewählt werden, welche Infrastruktur/Plattform darauf sein soll.
Dies sind die Features der Runner: https://docs.gitlab.com/runner/#features (opens in a new tab)
Specific Runner
Um Runners zu verwenden, gibt es zwei Möglichkeiten. Eine davon ist die Verwendung eines specific Runners. Dabei wird ein eigener Runner auf einem System erstellt.
# Download and install binary
# Download the binary for your system
sudo curl --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64
# Give it permission to execute
sudo chmod +x /usr/local/bin/gitlab-runner
# The rest of the commands execute as the user who will run the runner
# Register the runner (steps below), then run
cd ~
gitlab-runner install
gitlab-runner start
# Command to register runner
gitlab-runner register --url https://git.namics.com/ --registration-token $REGISTRATION_TOKEN
Beim Setup wird man nach einem Executer gefragt. Auf dem Executer wird schlussendlich der Code ausgeführt.
Shared Runners
Die gängigere Variante ist die Verwendung von shared Runners zu aktivieren. Shared Runners sind Runners, welche über die gesamte GitLab Instanz
geteilt werden.
Um das Yaml File auszuführen, wird ein passender Runner des Pools genutzt.
Docker-Image
Die Scripts aus dem Yaml File werden in der Regel nicht direkt auf den Runners ausgeführt. Meistens wird, mithilfe eines Docker Images, eine passende Umgebungen definiert.
Ein Docker ist im Grunde genommen eine virtuelle Maschine, deren Konfiguration (Systeme und Versionen) definiert werden kann. Dadurch wird
garantiert, dass der Code in einer konsistenten Umgebung ausgeführt wird.
Insbesondere bei Testprozessen ist diese einheitliche Umgebung von Vorteil.
Und wenn nicht alle Mitglieder eines Entwicklungsteams dasselbe Betriebssystem verwenden, kann Docker ebenfalls die Lösung sein.
Ein Docker Image ist eine Definition, welche als Anleitung zum Bau eines Docker Containers verwendet wird. Sie gibt vor, was der Container für Spezifikation haben muss.
Beispiel
Ich habe ein Projekt, welches auf Node 16.17.0 läuft. Nun will ich es beim Merge auf den Master automatisch deployen.
Natürlich könnte ich im Export Script auf dem Runner eine Node-Version-Manager installieren und damit die Node-Version auslesen, herunterladen und
verwenden. Dies wird aber schnell kompliziert. Und wenn man dann davor noch Tests durchführen will, benötigt man eventuell noch weitere Umgebungen.
Der einfachste Weg ist also, ein Image bei den Scripts anzugeben. So kann man die Befehle direkt auf der gewünschten Umgebung ausführen.
Ein weiterer Vorteil dieses Vorgehens ist, dass man dieselbe Umgebung für mehrere Scripts verwenden kann.
Alle Images findet man hier: https://hub.docker.com/ (opens in a new tab)
Einsatzmöglichkeiten
Um einen Denkanstoss zu geben, werden hier drei der Einsatzmöglichkeiten von CI/CD aufgezeigt:
- Builds & Deployments: Durch die Automatisierung dieser Prozesse spart man Zeit. Zudem können auch Fehler vermieden werden.
- Testing: Die Code Qualität und Sicherheit kann bei jedem Push/Merge/Deployment sichergestellt werden.
- Überwachung: Durch Scripts kann die Performance, Fehlermeldungen und Sicherheitsbedrohungen einer Applikation automatisch überwacht werden. So werden Probleme schneller erkannt.
Fazit
Mit einem guten CI/CD Setup, kann man Aufgaben zuverlässig und automatisiert durchführen.
Es ist also durchaus sinnvoll, sich ein solches Script zu erstellen. Denn auf lange Sicht wird dadurch viel Zeit und Arbeit gespart.