From a679a4cf4811cfc39bf67dd22678427b70d8bc81 Mon Sep 17 00:00:00 2001 From: ChrPc Date: Fri, 22 May 2026 11:31:48 +0200 Subject: [PATCH] followed smits guideline: italic instead of bold, added matrikel number --- DMS_paper15_gitlab.tex | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/DMS_paper15_gitlab.tex b/DMS_paper15_gitlab.tex index 78ec3f3..7178b77 100644 --- a/DMS_paper15_gitlab.tex +++ b/DMS_paper15_gitlab.tex @@ -66,7 +66,7 @@ \author{ \begin{tabular}{ccc} \textbf{Roman Schöne} & \textbf{Christopher Schmitt}\\ - 2211275 & ???????\\ + 2211275 & 2023467\\ roman.schoene@stud.th-mannheim.de & christopher.schmitt@stud.th-mannheim.de \end{tabular}\\\\ Technische Hochschule Mannheim @@ -213,13 +213,13 @@ \subsection{GitLab Runner} - Die GitLab-Instanz selbst führt keine \ac{CI}/\ac{CD}-Arbeit aus. Diese Aufgabe übernimmt ein separater Hilfsprozess, der \textbf{Runner} \cite{gitlab_gitlab_nodate}. Ein Runner registriert sich einmal mit einem Token bei der Instanz und holt sich danach selbständig offene Aufgaben ab. Durch diese Trennung kann die Ausführung horizontal skaliert werden. Plattformabhängige Aufgaben lassen sich gezielt auf der passenden Hardware ausführen \cite{painter_practical_2024}. Runner können auf drei unterschiedlichen Ebenen registriert werden: + Die GitLab-Instanz selbst führt keine \ac{CI}/\ac{CD}-Arbeit aus. Diese Aufgabe übernimmt ein separater Hilfsprozess, der \emph{Runner} \cite{gitlab_gitlab_nodate}. Ein Runner registriert sich einmal mit einem Token bei der Instanz und holt sich danach selbständig offene Aufgaben ab. Durch diese Trennung kann die Ausführung horizontal skaliert werden. Plattformabhängige Aufgaben lassen sich gezielt auf der passenden Hardware ausführen \cite{painter_practical_2024}. Runner können auf drei unterschiedlichen Ebenen registriert werden: \begin{itemize} - \item \textbf{Instanz} Auf Instanzebene registrierte Runner stehen allen Projekten der GitLab-Instanz zur Verfügung. Sie werden in der Regel von der Administration bereitgestellt. - \item \textbf{Gruppe} Auf Gruppenebene registrierte Runner nehmen Aufgaben aus sämtlichen Projekten innerhalb dieser Gruppe und ihrer Subgruppen an. Eingesetzt werden sie meistens dann, wenn eine Gruppe besondere Anforderungen an Hardware oder Software stellt. - \item \textbf{Projekt} Auf Projektebene registrierte Runner sind ausschliesslich an ein einzelnes Projekt gebunden. Diese Variante eignet sich für sensitive Projekte, bei denen kein gemeinsam genutzter Runner verwendet werden soll. + \item \emph{Instanz} Auf Instanzebene registrierte Runner stehen allen Projekten der GitLab-Instanz zur Verfügung. Sie werden in der Regel von der Administration bereitgestellt. + \item \emph{Gruppe} Auf Gruppenebene registrierte Runner nehmen Aufgaben aus sämtlichen Projekten innerhalb dieser Gruppe und ihrer Subgruppen an. Eingesetzt werden sie meistens dann, wenn eine Gruppe besondere Anforderungen an Hardware oder Software stellt. + \item \emph{Projekt} Auf Projektebene registrierte Runner sind ausschliesslich an ein einzelnes Projekt gebunden. Diese Variante eignet sich für sensitive Projekte, bei denen kein gemeinsam genutzter Runner verwendet werden soll. \end{itemize} - Wie ein Runner eine konkrete Aufgabe ausführt, hängt vom konfigurierten \textbf{Executor} ab. Der Executor entscheidet, in welcher Umgebung das vom Anwender hinterlegte Skript läuft. Tabelle~\ref{tab:executors} listet die in der Praxis am häufigsten verwendeten Executors auf. + Wie ein Runner eine konkrete Aufgabe ausführt, hängt vom konfigurierten \emph{Executor} ab. Der Executor entscheidet, in welcher Umgebung das vom Anwender hinterlegte Skript läuft. Tabelle~\ref{tab:executors} listet die in der Praxis am häufigsten verwendeten Executors auf. \begin{table}[H] \centering \caption{Häufig verwendete Executors des GitLab Runners \cite{gitlab_gitlab_nodate}} @@ -240,13 +240,13 @@ \subsection{Pipelines} - Eine \textbf{Pipeline} ist in GitLab die oberste Ebene der Automatisierung. Sie umfasst sämtliche Schritte, die als Reaktion auf ein Ereignis im Repository ablaufen \cite{gitlab_gitlab_nodate}. Ausgelöst wird eine Pipeline durch unterschiedliche Ereignisse. Dazu gehören ein Push, das Öffnen eines \textbf{Merge Requests}, ein hinterlegter Zeitplan, ein manueller Klick in der Weboberfläche oder das Ende einer anderen Pipeline \cite{cowell_automating_2023}. + Eine \emph{Pipeline} ist in GitLab die oberste Ebene der Automatisierung. Sie umfasst sämtliche Schritte, die als Reaktion auf ein Ereignis im Repository ablaufen \cite{gitlab_gitlab_nodate}. Ausgelöst wird eine Pipeline durch unterschiedliche Ereignisse. Dazu gehören ein Push, das Öffnen eines \emph{Merge Requests}, ein hinterlegter Zeitplan, ein manueller Klick in der Weboberfläche oder das Ende einer anderen Pipeline \cite{cowell_automating_2023}. - Innerhalb einer Pipeline werden die einzelnen Arbeitsschritte zu sogenannten \textbf{Stages} zusammengefasst. Alle Schritte einer Stage laufen parallel und müssen erfolgreich abgeschlossen sein, bevor die nächste Stage beginnt \cite{gitlab_gitlab_nodate}. Eine in der Praxis verbreitete Reihenfolge der Stages ist \texttt{lint}, \texttt{test}, \texttt{build} und \texttt{deploy}. Abbildung~\ref{fig:pipeline-stages} zeigt das Verhältnis von Pipeline, Stages und Jobs. + Innerhalb einer Pipeline werden die einzelnen Arbeitsschritte zu sogenannten \emph{Stages} zusammengefasst. Alle Schritte einer Stage laufen parallel und müssen erfolgreich abgeschlossen sein, bevor die nächste Stage beginnt \cite{gitlab_gitlab_nodate}. Eine in der Praxis verbreitete Reihenfolge der Stages ist \texttt{lint}, \texttt{test}, \texttt{build} und \texttt{deploy}. Abbildung~\ref{fig:pipeline-stages} zeigt das Verhältnis von Pipeline, Stages und Jobs. \input{diagrams/pipeline_stages} - Die gesamte Definition einer Pipeline liegt in einer einzigen Datei. Diese trägt den Namen \texttt{.gitlab-ci.yml} und befindet sich im Wurzelverzeichnis des Repositories \cite{gitlab_gitlab_nodate}. Damit folgt GitLab dem von Humble und Farley~\cite{humble_continuous_2010} eingeführten \textbf{Pipeline-as-Code}-Prinzip. Die Beschreibung des Build- und Auslieferungsprozesses wird wie Anwendungscode versioniert und im Review geprüft. Listing~\ref{lst:gitlabciyml} zeigt einen minimalen Aufbau mit drei Stages. + Die gesamte Definition einer Pipeline liegt in einer einzigen Datei. Diese trägt den Namen \texttt{.gitlab-ci.yml} und befindet sich im Wurzelverzeichnis des Repositories \cite{gitlab_gitlab_nodate}. Damit folgt GitLab dem von Humble und Farley~\cite{humble_continuous_2010} eingeführten \emph{Pipeline-as-Code}-Prinzip. Die Beschreibung des Build- und Auslieferungsprozesses wird wie Anwendungscode versioniert und im Review geprüft. Listing~\ref{lst:gitlabciyml} zeigt einen minimalen Aufbau mit drei Stages. \begin{lstlisting}[language=yaml,caption={Minimaler Aufbau einer .gitlab-ci.yml},label={lst:gitlabciyml}] stages: @@ -277,16 +277,16 @@ deploy-staging: \subsection{Jobs} - Die eigentliche Arbeitseinheit innerhalb einer Pipeline ist der \textbf{Job}. Ein Job führt ein vom Anwender festgelegtes Skript in einer isolierten Umgebung aus und ist genau einer Stage zugeordnet \cite{gitlab_gitlab_nodate}. Jobs derselben Stage sind voneinander unabhängig und werden parallel auf den verfügbaren Runnern ausgeführt. Ob die Pipeline weiterläuft, hängt vom Ergebnis sämtlicher Jobs einer Stage ab. + Die eigentliche Arbeitseinheit innerhalb einer Pipeline ist der \emph{Job}. Ein Job führt ein vom Anwender festgelegtes Skript in einer isolierten Umgebung aus und ist genau einer Stage zugeordnet \cite{gitlab_gitlab_nodate}. Jobs derselben Stage sind voneinander unabhängig und werden parallel auf den verfügbaren Runnern ausgeführt. Ob die Pipeline weiterläuft, hängt vom Ergebnis sämtlicher Jobs einer Stage ab. Mit dem Schlüsselwort \texttt{rules} wird pro Job festgelegt, unter welchen Bedingungen dieser ausgeführt wird. Beispiele sind die Beschränkung auf bestimmte Branches, die Ausführung nur bei Änderungen an bestimmten Dateien oder die Abhängigkeit vom Ergebnis vorheriger Jobs \cite{cowell_automating_2023}. Ein als \texttt{manual} markierter Job läuft erst nach einer expliziten Freigabe über die Weboberfläche. Diese Konstruktion wird häufig für Auslieferungen in produktive Umgebungen genutzt. Während ein Job läuft, entstehen häufig Dateien, die spätere Jobs weiterverarbeiten. Beispiele sind ein gebautes Bundle, ein Container-Image oder ein Testbericht. GitLab unterscheidet dafür zwei Mechanismen mit unterschiedlicher Lebensdauer \cite{gitlab_gitlab_nodate}: \begin{itemize} - \item \textbf{Artefakte} Artefakte sind benannte Ergebnisse eines Jobs. Sie werden nach dem erfolgreichen Abschluss eines Jobs an die GitLab-Instanz hochgeladen, stehen dort zum Download bereit und werden an spätere Jobs der Pipeline weitergegeben. - \item \textbf{Caches} Caches dienen ausschliesslich dazu, wiederholte Ausführungen zu beschleunigen. Typisch ist das Zwischenspeichern heruntergeladener Abhängigkeiten zwischen Pipeline-Läufen. Über Jobgrenzen hinweg ist der Cache nicht garantiert verfügbar. + \item \emph{Artefakte} sind benannte Ergebnisse eines Jobs. Sie werden nach dem erfolgreichen Abschluss eines Jobs an die GitLab-Instanz hochgeladen, stehen dort zum Download bereit und werden an spätere Jobs der Pipeline weitergegeben. + \item \emph{Caches} dienen ausschliesslich dazu, wiederholte Ausführungen zu beschleunigen. Typisch ist das Zwischenspeichern heruntergeladener Abhängigkeiten zwischen Pipeline-Läufen. Über Jobgrenzen hinweg ist der Cache nicht garantiert verfügbar. \end{itemize} - Das Ziel einer Auslieferung wird durch das Konzept der \textbf{Environments} beschrieben \cite{cowell_automating_2023}. Jedes Environment fasst alle Auslieferungen in eine bestimmte Zielumgebung zusammen. In der Weboberfläche wird zusätzlich protokolliert, welche Version dort gerade läuft. Einen Sonderfall bilden \textbf{Review-Apps}. Für jeden offenen Merge Request erzeugt GitLab automatisch eine isolierte, kurzlebige Auslieferung, in der die geänderte Anwendung vor dem Merge begutachtet werden kann \cite{gitlab_gitlab_nodate}. Nach Rostami Mazrae et al.~\cite{rostami_usage_2023} ist diese direkte Kopplung zwischen Review und laufender Vorschau eines der Merkmale, mit denen sich GitLab von alternativen Plattformen abgrenzt. + Das Ziel einer Auslieferung wird durch das Konzept der \emph{Environments} beschrieben \cite{cowell_automating_2023}. Jedes Environment fasst alle Auslieferungen in eine bestimmte Zielumgebung zusammen. In der Weboberfläche wird zusätzlich protokolliert, welche Version dort gerade läuft. Einen Sonderfall bilden \emph{Review-Apps}. Für jeden offenen Merge Request erzeugt GitLab automatisch eine isolierte, kurzlebige Auslieferung, in der die geänderte Anwendung vor dem Merge begutachtet werden kann \cite{gitlab_gitlab_nodate}. Nach Rostami Mazrae et al.~\cite{rostami_usage_2023} ist diese direkte Kopplung zwischen Review und laufender Vorschau eines der Merkmale, mit denen sich GitLab von alternativen Plattformen abgrenzt. Zampetti et al.~\cite{zampetti_empirical_2020} identifizieren in einer empirischen Untersuchung 79 wiederkehrende Anti-Muster in CI-Konfigurationen. Häufige Probleme sind unnötig sequentielle Stages, zu grobgranulare Jobs und das Vermischen von Cache und Artefakten. Lesbarkeit und Wartbarkeit der Pipeline-Definition sind damit ein eigenes Qualitätskriterium. @@ -294,11 +294,11 @@ deploy-staging: Mit dem Schlüsselwort \texttt{include} können bereits seit längerem ganze Pipeline-Fragmente aus anderen Repositories oder von einer entfernten \ac{URL} eingebunden werden \cite{gitlab_gitlab_nodate}. In der Praxis stellen sich dabei zwei wiederkehrende Probleme. Eingebundene Fragmente sind in den meisten Fällen weder versioniert noch besitzen sie eine eigene Schnittstelle. Eine Änderung am Fragment kann sämtliche Pipelines mit einbinden \cite{cowell_automating_2023}. - Seit GitLab 16.0 lösen \textbf{CI/CD-Komponenten} dieses Problem. Eine Komponente ist ein versionierter und parametrisierbarer Pipeline-Baustein, der ähnlich wie eine Software-Bibliothek verwendet wird \cite{gitlab_gitlab_nodate}. Komponenten werden in einem dedizierten Projekt entwickelt und veröffentlicht. Drei Bestandteile sind dabei zwingend vorgesehen: + Seit GitLab 16.0 lösen \emph{CI/CD-Komponenten} dieses Problem. Eine Komponente ist ein versionierter und parametrisierbarer Pipeline-Baustein, der ähnlich wie eine Software-Bibliothek verwendet wird \cite{gitlab_gitlab_nodate}. Komponenten werden in einem dedizierten Projekt entwickelt und veröffentlicht. Drei Bestandteile sind dabei zwingend vorgesehen: \begin{itemize} - \item \textbf{Manifest} In einer Datei \texttt{template.yml} beschreibt die Komponente ihre Eingabeparameter mit Datentyp und Defaultwert sowie die von ihr beigesteuerten Jobs. - \item \textbf{Versionsschild} Komponenten werden ausschliesslich über Git-Tags freigegeben. Ein Konsument referenziert eine Komponente immer mit einer konkreten Version. Damit kann sich der eingebundene Stand nicht unter dem Konsumenten verändern. - \item \textbf{Katalogeintrag} Ein Projekt, das den Status \textit{Components Project} erhält, erscheint im zentralen \textbf{Component Catalog} der GitLab-Instanz. Die Suche nach geeigneten Komponenten erfolgt dort, ohne dass Repository-Pfade auswendig bekannt sein müssen. + \item \emph{Manifest} In einer Datei \texttt{template.yml} beschreibt die Komponente ihre Eingabeparameter mit Datentyp und Defaultwert sowie die von ihr beigesteuerten Jobs. + \item \emph{Versionsschild} Komponenten werden ausschliesslich über Git-Tags freigegeben. Ein Konsument referenziert eine Komponente immer mit einer konkreten Version. Damit kann sich der eingebundene Stand nicht unter dem Konsumenten verändern. + \item \emph{Katalogeintrag} Ein Projekt, das den Status \textit{Components Project} erhält, erscheint im zentralen \emph{Component Catalog} der GitLab-Instanz. Die Suche nach geeigneten Komponenten erfolgt dort, ohne dass Repository-Pfade auswendig bekannt sein müssen. \end{itemize} Listing~\ref{lst:component} zeigt die Einbindung einer beispielhaften Lint-Komponente in eine bestehende Pipeline. @@ -320,7 +320,7 @@ stages: Zur praktischen Demonstration der vorhergehenden Konzepte wurde eine kleine Webanwendung auf der in Abschnitt~\ref{sec:selfhosted} beschriebenen selbstgehosteten Instanz aufgesetzt. Die Anwendung ist bewusst minimal gehalten. So liegt der Fokus auf der \ac{CI}/\ac{CD}-Konfiguration und nicht auf dem Anwendungscode. - Die Demoanwendung ist ein \texttt{HTTP}-Dienst, der in \textbf{Node.js} mit dem Web-Framework \textbf{Express} geschrieben ist. Bereitgestellt wird ein einzelner Endpunkt \texttt{GET /}, der eine kurze HTML-Seite mit der Bezeichnung der aktuellen Umgebung und der im Build verbauten Versionskennung ausliefert. Beide Werte werden zur Laufzeit über Umgebungsvariablen aus dem Container gelesen und im jeweiligen Deploy-Job gesetzt. Eine kleine Testsuite mit dem Framework \texttt{vitest} prüft, dass der Endpunkt eine HTML-Antwort mit Statuscode~200 und der erwarteten Versionsangabe liefert. + Die Demoanwendung ist ein \texttt{HTTP}-Dienst, der in \emph{Node.js} mit dem Web-Framework \emph{Express} geschrieben ist. Bereitgestellt wird ein einzelner Endpunkt \texttt{GET /}, der eine kurze HTML-Seite mit der Bezeichnung der aktuellen Umgebung und der im Build verbauten Versionskennung ausliefert. Beide Werte werden zur Laufzeit über Umgebungsvariablen aus dem Container gelesen und im jeweiligen Deploy-Job gesetzt. Eine kleine Testsuite mit dem Framework \texttt{vitest} prüft, dass der Endpunkt eine HTML-Antwort mit Statuscode~200 und der erwarteten Versionsangabe liefert. Die zugehörige \texttt{.gitlab-ci.yml} definiert drei Stages: \texttt{lint}, \texttt{test} und \texttt{deploy}. Die Stage \texttt{deploy} enthält dabei zwei Jobs, die sich gegenseitig ausschliessen. Tabelle~\ref{tab:demo-pipeline} fasst zusammen, welcher Schritt unter welchen Bedingungen ausgeführt wird und welches Environment er bedient. \begin{table}[H] @@ -345,11 +345,11 @@ stages: \section{Selbstgehostete Lösung}\label{sec:selfhosted} \authornote{Christopher Schmitt} - GitLab kann nicht nur als \ac{SaaS} bezogen, sondern auch auf eigener Hardware selbst betrieben werden. Diese Variante wird von GitLab als \textbf{Self-Managed} bezeichnet \cite{gitlab_gitlab_nodate}. Sie kommt hauptsächlich in zwei Fällen zum Einsatz. Entweder erlauben Datenschutz- oder Compliance-Vorgaben nicht, dass Quellcode auf fremden Servern liegt. Oder die \ac{SaaS}-Variante wird mit steigender Nutzerzahl zu teuer. Installation, Konfiguration, Aktualisierungen und Sicherungen müssen dafür allerdings selbst übernommen werden \cite{painter_practical_2024}. Im Folgenden wird beschrieben, wie eine solche Instanz im Rahmen dieser Arbeit auf einem privaten Linux-Server aufgesetzt wurde und welcher Aufwand dabei anfiel. + GitLab kann nicht nur als \ac{SaaS} bezogen, sondern auch auf eigener Hardware selbst betrieben werden. Diese Variante wird von GitLab als \emph{Self-Managed} bezeichnet \cite{gitlab_gitlab_nodate}. Sie kommt hauptsächlich in zwei Fällen zum Einsatz. Entweder erlauben Datenschutz- oder Compliance-Vorgaben nicht, dass Quellcode auf fremden Servern liegt. Oder die \ac{SaaS}-Variante wird mit steigender Nutzerzahl zu teuer. Installation, Konfiguration, Aktualisierungen und Sicherungen müssen dafür allerdings selbst übernommen werden \cite{painter_practical_2024}. Im Folgenden wird beschrieben, wie eine solche Instanz im Rahmen dieser Arbeit auf einem privaten Linux-Server aufgesetzt wurde und welcher Aufwand dabei anfiel. \subsection{Installation} - Für die selbstgehostete \ac{CE} bietet GitLab das sogenannte \textbf{Omnibus-Paket} an \cite{painter_practical_2024}. Im Paket enthalten sind sämtliche Komponenten, die GitLab im Betrieb benötigt. Dazu zählen der Webserver \texttt{nginx}, der Anwendungsserver \texttt{Puma}, die relationale Datenbank \texttt{PostgreSQL} und der Schlüssel-Wert-Speicher \texttt{Redis}. Weitere Hintergrundprozesse kommen hinzu \cite{gitlab_gitlab_nodate}. Abbildung~\ref{fig:omnibus-arch} zeigt das Zusammenspiel der einzelnen Bausteine. + Für die selbstgehostete \ac{CE} bietet GitLab das sogenannte \emph{Omnibus-Paket} an \cite{painter_practical_2024}. Im Paket enthalten sind sämtliche Komponenten, die GitLab im Betrieb benötigt. Dazu zählen der Webserver \texttt{nginx}, der Anwendungsserver \texttt{Puma}, die relationale Datenbank \texttt{PostgreSQL} und der Schlüssel-Wert-Speicher \texttt{Redis}. Weitere Hintergrundprozesse kommen hinzu \cite{gitlab_gitlab_nodate}. Abbildung~\ref{fig:omnibus-arch} zeigt das Zusammenspiel der einzelnen Bausteine. \input{diagrams/omnibus_arch}