31 Job Definition in GitLab CI

Ein Job ist die grundlegende Einheit in einer GitLab CI/CD-Pipeline. Jeder Job repräsentiert eine spezifische Aufgabe oder ein Skript, das ausgeführt werden soll. Er gehört zu einer Stage und wird in der Reihenfolge der definierten Stages ausgeführt. Der Job wird in der .gitlab-ci.yml-Datei beschrieben und kann dabei viele verschiedene Parameter enthalten, die seine Ausführung und das Verhalten in der Pipeline steuern.

31.1 Syntax und Aufbau eines Jobs

Ein Job wird als eigener Abschnitt in der .gitlab-ci.yml-Datei definiert. Der Name des Jobs fungiert als Schlüssel und ist frei wählbar, sollte jedoch eindeutig und aussagekräftig sein. Darunter werden verschiedene Parameter wie script, stage, und variables festgelegt, die bestimmen, was der Job ausführt, in welcher Phase der Pipeline er läuft und welche Umgebung er verwendet.

Beispiel:

build_job:
  stage: build
  script:
    - echo "Building the project"
    - make build

In diesem Beispiel ist der Job build_job in der build-Phase der Pipeline zugeordnet. Der Job führt die im script-Abschnitt definierten Befehle aus. Zuerst wird eine einfache Ausgabe mit echo ausgeführt, danach der Build-Prozess mit make build.

31.2 Wichtige Parameter für Jobs:

  1. script: Der wichtigste Parameter, der die Befehle enthält, die im Job ausgeführt werden sollen. Dies können einfache Shell-Befehle oder komplexe Skripte sein.

  2. stage: Gibt an, in welcher Phase der Pipeline der Job ausgeführt wird. Phasen wie build, test, und deploy sind gängig.

  3. tags: Verwendet, um den Job auf spezifischen Runnern mit bestimmten Eigenschaften auszuführen.

  4. artifacts und cache: Werden verwendet, um Ergebnisse zwischen verschiedenen Jobs zu speichern und wiederzuverwenden.

Ein Job kann allein stehen oder in einer größeren Pipeline mit mehreren Jobs und Stages eingebettet sein. Jeder Job läuft in einer isolierten Umgebung, was zu konsistenten und wiederholbaren Builds führt.


Weitere Informationen finden sich in der offiziellen GitLab-Dokumentation zu Job Keywords.

31.3 Script in GitLab CI

Das script-Keyword ist der wichtigste Teil eines Jobs in der GitLab CI-Pipeline. Es legt fest, welche Befehle in einem bestimmten Job ausgeführt werden sollen. Jeder Job muss mindestens ein script enthalten, da dies bestimmt, welche Aktion der Job ausführt. Es kann sich dabei um einfache Shell-Befehle oder um komplexe Abläufe handeln.

31.3.1 Funktionsweise von script

Der Inhalt des script-Blocks wird in der Umgebung des jeweiligen Runners ausgeführt, z. B. in einem Docker-Container oder direkt im Shell-Kontext des Servers. Die Befehle in diesem Block werden in der Reihenfolge ausgeführt, in der sie definiert sind. Wenn einer der Befehle fehlschlägt (d. h. einen Exit-Status ungleich null zurückgibt), wird der Job als fehlgeschlagen markiert und nachfolgende Befehle werden nicht mehr ausgeführt.

Beispiel:

build_job:
  script:
    - echo "Building the project"
    - make build

Hier gibt es zwei Befehle, die nacheinander ausgeführt werden: Zuerst wird der Text “Building the project” ausgegeben, danach wird der Build-Prozess mit dem Befehl make build gestartet.

31.3.2 Verwendung mehrerer Befehle

Im script-Abschnitt können beliebig viele Befehle hintereinander aufgelistet werden. Jeder Befehl wird auf der Shell des Runners ausgeführt. Wenn ein Befehl fehlschlägt, wird der Job abgebrochen, es sei denn, der Fehler wird durch spezielle Maßnahmen abgefangen (z.B. durch || true, um Fehler zu ignorieren).

Beispiel mit mehreren Befehlen:

test_job:
  script:
    - echo "Running tests"
    - npm install
    - npm test

Dieser Job führt eine Test-Pipeline aus, bei der zunächst die Abhängigkeiten installiert werden (npm install) und anschließend die Tests ausgeführt werden (npm test).

31.3.3 Befehle für mehrere Jobs

Jobs in einer Pipeline können unterschiedlich komplex sein. Daher kann der script-Block auch so konfiguriert werden, dass er die Komplexität eines Jobs besser abbildet. Zudem können in Kombination mit globalen Keywords wie before_script und after_script allgemeine Befehle definiert werden, die vor oder nach jedem Job ausgeführt werden.

Beispiel mit vor- und nachgelagerten Befehlen:

before_script:
  - echo "Setting up environment"

test_job:
  script:
    - npm install
    - npm test

after_script:
  - echo "Cleaning up after tests"

In diesem Beispiel wird vor jedem Job der Befehl im before_script-Block und nach jedem Job der Befehl im after_script-Block ausgeführt, zusätzlich zu den job-spezifischen script-Befehlen.

31.3.4 Fehlerbehandlung

Wenn ein Befehl im script-Block fehlschlägt, wird der Job als fehlgeschlagen markiert. Um spezifische Fehler zu tolerieren, können Befehle modifiziert werden, um Fehler nicht als kritisch zu behandeln. Ein gängiges Muster dafür ist die Verwendung von || true, um zu verhindern, dass der Job bei einem Fehler abbricht.

Beispiel mit Fehlerbehandlung:

deploy_job:
  script:
    - echo "Deploying to production"
    - ./deploy.sh || true

In diesem Fall würde der Job nicht abbrechen, selbst wenn der Befehl ./deploy.sh fehlschlägt.


Weitere Informationen finden sich in der offiziellen GitLab-Dokumentation zu script.

31.4 Tags in GitLab CI

Tags in GitLab CI werden verwendet, um Jobs bestimmten Runnern zuzuweisen. Runner sind die ausführenden Instanzen, die die Jobs verarbeiten, und können so konfiguriert werden, dass sie nur Jobs mit bestimmten Tags annehmen. Dies ist besonders nützlich, wenn bestimmte Jobs in speziellen Umgebungen oder auf spezifischer Hardware ausgeführt werden sollen, z. B. auf Maschinen mit speziellen Konfigurationen oder Betriebssystemen.

31.4.1 Funktionsweise von Tags

Ein Job kann mit einem oder mehreren Tags versehen werden, und nur Runner, die ebenfalls mit diesen Tags konfiguriert sind, führen diesen Job aus. Auf diese Weise lassen sich verschiedene Jobs gezielt steuern, etwa um sicherzustellen, dass ressourcenintensive Jobs auf leistungsstarken Maschinen laufen, oder dass bestimmte Tests nur in einer bestimmten Umgebung ausgeführt werden.

Beispiel:

job_name:
  script:
    - echo "Running job on tagged runner"
  tags:
    - docker
    - linux

In diesem Beispiel wird der Job nur von Runnern ausgeführt, die die Tags docker und linux haben. Dies stellt sicher, dass der Job nur auf einer Docker-fähigen Umgebung unter Linux läuft.

31.4.2 Anwendungsmöglichkeiten von Tags

31.4.3 Tags und Shared Runner

In GitLab.com gibt es sogenannte Shared Runner, die von allen Benutzern gemeinsam genutzt werden. Um die Kontrolle über die Ausführung der Jobs zu behalten, können private Runner eingerichtet und mit spezifischen Tags versehen werden. Dies bietet eine höhere Flexibilität und Kontrolle über die Ausführung der CI-Jobs.


Weitere Informationen finden sich in der offiziellen GitLab-Dokumentation zu Tags.

31.5 Artifacts in GitLab CI

Artifacts in GitLab CI sind Dateien oder Verzeichnisse, die während der Ausführung eines Jobs erstellt und nach Abschluss des Jobs gespeichert werden, sodass sie von späteren Jobs innerhalb derselben Pipeline oder von anderen Pipelines verwendet werden können. Artefakte sind nützlich, um Build-Ergebnisse, Testberichte, Log-Dateien oder andere wichtige Dateien zu speichern und weiterzugeben.

31.5.1 Funktionsweise von Artifacts

Ein Job kann eine Liste von Verzeichnissen oder Dateien als Artefakte speichern, die nach Abschluss des Jobs für andere Jobs in derselben Pipeline verfügbar sind. Diese Artefakte werden auf GitLab-Servern gespeichert und können entweder zur weiteren Verarbeitung heruntergeladen oder zur langfristigen Speicherung in externen Registries oder Artifactories verschoben werden.

Beispiel:

build_job:
  script:
    - make build
  artifacts:
    paths:
      - build/

In diesem Beispiel wird das Verzeichnis build/ nach Abschluss des Jobs als Artefakt gespeichert. Nachfolgende Jobs in der Pipeline können auf diese Build-Dateien zugreifen, ohne sie erneut erstellen zu müssen.

31.5.2 Artefakte und ihre Bedeutung in CI/CD

Artefakte sind entscheidend für die Effizienz und Kontinuität einer CI/CD-Pipeline, da sie es ermöglichen, Dateien zwischen Jobs weiterzugeben, ohne dass diese mehrfach erstellt oder heruntergeladen werden müssen. Dies verhindert redundante Prozesse wie Neukompilierungen oder das erneute Herunterladen von Abhängigkeiten.

31.5.3 Typische Beispiele für Artefakte:

31.5.4 Einstellungen für Artifacts

Artefakte werden in GitLab CI/CD über die .gitlab-ci.yml-Datei konfiguriert. Wichtige Einstellungen umfassen:

Beispiel mit zusätzlichen Optionen:

test_job:
  script:
    - npm test
  artifacts:
    paths:
      - test-reports/
    when: always
    expire_in: 1 week

In diesem Beispiel wird das Verzeichnis test-reports/ immer als Artefakt gespeichert, unabhängig davon, ob der Job erfolgreich war oder nicht. Die Artefakte werden eine Woche lang aufbewahrt.

31.5.5 Verwendung von Artifacts in nachfolgenden Jobs

Nachfolgende Jobs in der Pipeline können auf die Artefakte vorheriger Jobs zugreifen. Dafür muss der Job, der auf die Artefakte zugreift, in derselben Pipeline ausgeführt werden.

Beispiel:

build_job:
  script:
    - make build
  artifacts:
    paths:
      - build/

deploy_job:
  script:
    - deploy.sh
  dependencies:
    - build_job

In diesem Beispiel greift der deploy_job auf die Artefakte des build_job zu. Die Option dependencies stellt sicher, dass nur die Artefakte des build_job an den deploy_job weitergegeben werden.

31.5.6 Artefakte vs. Cache

Während Artifacts dazu dienen, Dateien zwischen Jobs innerhalb einer Pipeline zu speichern und weiterzugeben, wird der Cache verwendet, um wiederverwendbare Daten, wie etwa Abhängigkeiten, zwischen verschiedenen Pipeline-Läufen zu speichern. Der Cache ist nützlich für Aufgaben wie das Installieren von Abhängigkeiten, während Artefakte spezifisch für die Ergebnisse eines Jobs innerhalb des aktuellen Pipeline-Laufs gedacht sind.

Unterschiede im Detail: - Artifacts: Speichern spezifische Dateien und Ergebnisse eines Jobs und sind nur für den aktuellen Pipeline-Lauf relevant. - Cache: Speichert wiederverwendbare Daten, die zwischen verschiedenen Pipeline-Läufen verwendet werden.

31.5.7 Temporäre vs. Persistente Artefakte

  1. Temporäre Artefakte: Diese existieren nur für die Dauer der Pipeline und werden nach einer festgelegten Zeit oder nach Abschluss der Pipeline gelöscht. Sie sind nützlich für kurzfristige Builds oder Tests.

  2. Persistente Artefakte: Artefakte, die langfristig in externen Registries oder Artifactories gespeichert werden, sind besonders wichtig für den Einsatz in späteren Stages oder zur Bereitstellung. Beispiele hierfür sind Docker-Images in einer Container-Registry oder Bibliotheken in einer Maven-Repository.

31.5.8 Erweiterte Nutzung und Best Practices für Artifacts

31.5.8.1 Manuelle Downloads und Verteilung von Artefakten

Artifacts können manuell heruntergeladen werden, um direkt auf Ergebnisse wie Build-Artefakte, Testberichte oder Log-Dateien zuzugreifen. Diese Funktion ist nützlich, wenn Teammitglieder auf die Artefakte zugreifen müssen, ohne den gesamten Pipeline-Prozess durchlaufen zu müssen.

31.5.8.2 Externer Speicher für Artifacts

Für Projekte mit großen Datenmengen oder wenn Artefakte langfristig verfügbar bleiben sollen, können diese in externen Speichersystemen wie Amazon S3 oder anderen Cloud-basierten Speicherlösungen abgelegt werden. Dies ermöglicht eine zentrale Speicherung, die besonders in großen Teams oder bei verteilten Projekten von Vorteil ist.

31.5.8.3 Best Practices für den Umgang mit Artifacts

  1. Minimierung der Artefaktgröße: Speichere nur die unbedingt notwendigen Dateien als Artefakte, um Speicher- und Übertragungslasten zu reduzieren.
  2. Expire-Zeiten verwenden: Nutze expire_in, um sicherzustellen, dass Artefakte nach einer bestimmten Zeit automatisch gelöscht werden, wenn sie nicht mehr benötigt werden. Dies spart Speicherplatz.
  3. Gezielte Nutzung von Artefakten: Verwende Artefakte nur in den Jobs, in denen ihre Ergebnisse tatsächlich weiterverwendet werden. Dies hält die Pipeline effizient und vermeidet unnötige Dateispeicherungen.
  4. Nutzung externer Speicherdienste: Für langfristige Speicherung und große Teams empfiehlt sich die Nutzung externer Speicherdienste, um Artefakte dauerhaft verfügbar zu halten.

Weitere Informationen finden sich in der offiziellen GitLab-Dokumentation.

31.6 Dependencies in GitLab CI

Das dependencies-Keyword wird verwendet, um Artefakte zwischen verschiedenen Jobs zu teilen. Es gibt an, von welchen vorherigen Jobs ein bestimmter Job die Artefakte benötigt. Dies ist besonders nützlich in Pipelines, in denen die Ausgabe eines vorherigen Jobs für die Ausführung eines nachfolgenden Jobs erforderlich ist, ohne dass alle Artefakte von allen vorherigen Jobs heruntergeladen werden müssen.

31.6.1 Funktionsweise von dependencies

Standardmäßig lädt ein Job die Artefakte aller vorherigen Jobs derselben Pipeline herunter. Mit dem dependencies-Keyword kann man jedoch festlegen, dass nur bestimmte Jobs und deren Artefakte für einen nachfolgenden Job relevant sind. Dies kann die Pipeline effizienter machen, da unnötige Dateien nicht heruntergeladen werden müssen, was Zeit und Ressourcen spart.

Beispiel:

build_job:
  script:
    - make build
  artifacts:
    paths:
      - build/

test_job:
  script:
    - npm test
  dependencies:
    - build_job

In diesem Beispiel gibt der test_job an, dass er nur die Artefakte des build_job benötigt. Dadurch wird verhindert, dass Artefakte von anderen Jobs, die in der Pipeline ausgeführt wurden, heruntergeladen werden.

31.6.2 Verwendung von dependencies in komplexen Pipelines

In komplexen Pipelines mit vielen Jobs und Phasen hilft das dependencies-Keyword, die Artefaktverteilung effizienter zu gestalten. Besonders bei Pipelines mit vielen parallelen Jobs und unterschiedlichen Aufgaben wie Build, Test und Deployment kann durch die gezielte Angabe von Abhängigkeiten der Ressourcenverbrauch und die Pipeline-Laufzeit optimiert werden.

Beispiel mit mehreren Abhängigkeiten:

build_frontend:
  script:
    - npm run build
  artifacts:
    paths:
      - dist/

build_backend:
  script:
    - make build
  artifacts:
    paths:
      - build/

deploy_job:
  script:
    - ./deploy.sh
  dependencies:
    - build_frontend
    - build_backend

Hier werden die Artefakte sowohl vom build_frontend-Job als auch vom build_backend-Job für den deploy_job verwendet, ohne dass andere Jobs oder Artefakte berücksichtigt werden müssen.

31.6.3 Optimierung der Pipeline mit dependencies

Das Keyword hilft dabei, eine klare Abhängigkeit zwischen Jobs zu definieren, was besonders in großen Projekten mit mehreren Stages und Jobs nützlich ist. Es trägt dazu bei, unnötige Artefakt-Downloads zu vermeiden und so die Effizienz der Pipeline zu steigern. Durch die Angabe von spezifischen Abhängigkeiten reduziert man den Overhead in der Pipeline und sorgt für eine schnellere und besser skalierbare Ausführung.


Weitere Informationen finden sich in der offiziellen GitLab-Dokumentation.

31.7 Cache in GitLab CI/CD

Der Cache in GitLab CI/CD ist ein Mechanismus, der es ermöglicht, Dateien und Verzeichnisse zwischen verschiedenen Pipeline-Läufen zu speichern. Der Hauptzweck des Caches besteht darin, häufig verwendete Dateien – wie Abhängigkeiten, Bibliotheken oder Zwischenergebnisse – zu sichern. Dies beschleunigt den Build-Prozess, indem diese Dateien nicht bei jedem Pipeline-Lauf neu generiert oder heruntergeladen werden müssen.

31.7.1 Vorteile des Caching

31.7.2 Funktionsweise des Caches

Im Gegensatz zu Artefakten, die spezifische Ergebnisse eines Jobs zwischen Jobs innerhalb derselben Pipeline teilen, dient der Cache dazu, Daten zwischen verschiedenen Pipeline-Läufen wiederzuverwenden. Dies ist besonders hilfreich bei großen Projekten, bei denen das Installieren von Abhängigkeiten oder das Kompilieren von Quellcode wiederkehrend und zeitaufwendig ist.

Beispiel für die Cache-Konfiguration:

cache:
  paths:
    - node_modules/
    - .m2/repository/
  key: "$CI_COMMIT_REF_NAME"

In diesem Beispiel werden die Verzeichnisse node_modules und .m2/repository gecacht. Der Schlüssel key stellt sicher, dass der Cache spezifisch für den aktuellen Branch ($CI_COMMIT_REF_NAME) erstellt wird. Jeder Branch hat seinen eigenen Cache, was Konflikte zwischen verschiedenen Versionsständen vermeidet.

31.7.3 Parameter des Cache-Keywords

Beispiel mit mehreren Parametern:

cache:
  key: "$CI_JOB_NAME"
  paths:
    - build/
    - .m2/repository
  policy: pull-push

Hier werden sowohl das build/-Verzeichnis als auch das lokale Maven-Repository .m2/repository gecacht. Der Cache wird für den jeweiligen Job ($CI_JOB_NAME) spezifisch erstellt und wiederverwendet.

31.7.4 Cache-Typen in GitLab CI/CD

GitLab CI/CD bietet zwei grundlegende Arten von Caches, die für unterschiedliche Anwendungsfälle nützlich sind:

  1. Zwischen-Cache (Intermediate Cache): Dieser wird verwendet, um Artefakte und Dateien zwischen verschiedenen Stages innerhalb einer Pipeline weiterzugeben. Er ist besonders nützlich, wenn mehrere Stages auf denselben Build-Prozess zugreifen müssen.

  2. Persistenter Cache (Persistent Cache): Dieser bleibt über mehrere Pipeline-Läufe hinweg bestehen und wird genutzt, um Abhängigkeiten oder häufig benötigte Dateien zwischen verschiedenen CI-Läufen zu speichern. Ein Beispiel dafür ist das Zwischenspeichern von Node.js-Abhängigkeiten oder Maven-Repositories.

31.7.5 Cache-Schlüssel (Cache Keys)

Der Cache-Schlüssel (key) wird verwendet, um zu bestimmen, welche Caches verwendet werden sollen. GitLab erstellt verschiedene Caches basierend auf den verwendeten Schlüsseln. Dadurch wird sichergestellt, dass separate Pipelines oder Branches nicht denselben Cache verwenden, wenn dies nicht erwünscht ist.

31.7.6 Effiziente Nutzung des Caches

Die Verwendung von Caches kann die Pipeline-Performance erheblich verbessern. Es gibt jedoch einige Best Practices, um den Cache effizient zu konfigurieren und zu verwenden:

Beispiel für Cache mit Ablaufdatum:

cache:
  paths:
    - build/
  expire_in: 1 day

In diesem Beispiel wird der Cache nach einem Tag automatisch gelöscht, um unnötigen Speicherverbrauch zu vermeiden.

31.7.7 Unterschiede zwischen Cache und Artefakten

Während Artifacts für spezifische Build-Ergebnisse und Dateien zwischen Jobs innerhalb einer Pipeline gedacht sind, dient der Cache dazu, Dateien zwischen verschiedenen Pipeline-Läufen zu speichern. Typische Anwendungen des Caches sind das Speichern von Abhängigkeiten oder vorgefertigten Bibliotheken, während Artefakte dazu verwendet werden, Zwischenergebnisse zwischen den Stages einer Pipeline zu teilen.


Weitere Informationen finden sich in der offiziellen GitLab-Dokumentation zum Caching.

31.8 Allow Failure in GitLab CI

Das allow_failure-Keyword in GitLab CI ermöglicht es, Jobs so zu konfigurieren, dass sie den Erfolg der gesamten Pipeline nicht beeinflussen, selbst wenn sie fehlschlagen. Dies ist besonders nützlich für nicht-kritische Jobs, bei denen ein Fehler nicht den gesamten Entwicklungsprozess stoppen soll. Ein typisches Beispiel wäre das Ausführen experimenteller Tests oder das Linting des Codes, wo ein Fehlschlag nicht zwingend bedeutet, dass der Code defekt ist.

31.8.1 Funktionsweise von allow_failure

Wenn allow_failure auf true gesetzt wird, markiert GitLab den Job als fehlgeschlagen, setzt jedoch die Pipeline fort, als ob der Job erfolgreich gewesen wäre. Der Status des Jobs wird weiterhin als „failed“ angezeigt, aber die nachfolgenden Jobs und Stages werden trotzdem ausgeführt.

Beispiel:

test_job:
  script:
    - echo "Running tests"
    - npm test
  allow_failure: true

In diesem Beispiel würde der test_job bei einem Testfehler als „fehlgeschlagen“ markiert, aber die Pipeline würde trotzdem mit den nachfolgenden Jobs fortgesetzt.

31.8.2 Anwendungsfälle für allow_failure

31.8.3 allow_failure mit Regeln kombinieren

Das allow_failure-Keyword kann mit anderen Keywords wie rules oder only kombiniert werden, um die Pipeline präzise zu steuern und sicherzustellen, dass nur bestimmte Jobs optional behandelt werden.

Beispiel mit Regeln:

lint_job:
  script:
    - npm run lint
  allow_failure: true
  rules:
    - if: '$CI_COMMIT_BRANCH == "develop"'

In diesem Beispiel wird der Linting-Job auf dem develop-Branch ausgeführt, aber sein Fehlschlag stoppt nicht die Pipeline.


Weitere Informationen finden sich in der offiziellen Dokumentation.

31.9 Retry in GitLab CI

Das retry-Keyword in GitLab CI ermöglicht es, einen Job bei einem Fehlschlag automatisch erneut auszuführen. Diese Funktion ist nützlich, wenn ein Job aus nicht-deterministischen Gründen fehlschlägt, wie etwa aufgrund von Netzwerkfehlern oder temporären Problemen mit externen Diensten. Mit retry kann man sicherstellen, dass ein Job nicht sofort als gescheitert betrachtet wird, sondern mehrere Versuche unternommen werden, bevor die Pipeline endgültig fehlschlägt.

31.9.1 Funktionsweise von retry

Das retry-Keyword legt fest, wie oft ein fehlgeschlagener Job automatisch wiederholt werden soll. Standardmäßig wird ein Job nach einem Fehlschlag nicht wiederholt, es sei denn, retry ist konfiguriert. Man kann die Anzahl der Wiederholungen festlegen (bis zu einem Maximum von 2) und optional die Wiederholung nur bei bestimmten Fehlern aktivieren, wie etwa durch einen Exit-Code.

Beispiel:

job_name:
  script:
    - curl https://example.com
  retry: 2

In diesem Beispiel wird der job_name bei einem Fehlschlag automatisch bis zu zweimal wiederholt, was bedeutet, dass der Job maximal dreimal ausgeführt wird, bevor er endgültig als fehlgeschlagen betrachtet wird.

31.9.2 Anpassung des Verhaltens von retry

Neben der Anzahl der Wiederholungen kann das retry-Keyword spezifisch auf bestimmte Fehlertypen oder Exit-Codes angewendet werden. Dies bietet eine präzisere Steuerung darüber, wann ein Job wiederholt wird, z. B. nur bei bestimmten Fehlercodes oder bei Netzwerkproblemen.

Beispiel mit Exit-Codes:

job_name:
  script:
    - curl https://example.com
  retry:
    max: 2
    when:
      - always
      - network_failure

In diesem Beispiel wird der Job maximal zweimal wiederholt, insbesondere bei einem Netzwerkausfall (network_failure), aber auch bei allen anderen Fehlern (always).

31.9.3 Anwendungsfälle für retry

31.9.4 Grenzen von retry

Es ist wichtig zu beachten, dass das retry-Keyword nicht für alle Jobs sinnvoll ist. Jobs, die deterministisch fehlschlagen, z. B. aufgrund von Programmierfehlern, sollten nicht wiederholt werden. Daher ist es wichtig, retry nur für solche Jobs einzusetzen, bei denen temporäre Fehler erwartet werden können.


Weitere Informationen finden sich in der GitLab-Dokumentation zu retry.

31.10 Parallel in GitLab CI

Das parallel-Keyword in GitLab CI ermöglicht die parallele Ausführung mehrerer Instanzen eines Jobs. Dies ist besonders nützlich, um die Ausführung von Pipelines zu beschleunigen, indem mehrere Instanzen eines Jobs gleichzeitig verarbeitet werden, entweder durch Verteilung der Arbeit auf mehrere Maschinen oder durch Parallelisierung von Tests oder Builds.

31.10.1 Funktionsweise von parallel

Das parallel-Keyword teilt den Job in mehrere Instanzen auf, die gleichzeitig ausgeführt werden. Jede Instanz erhält eine eindeutige Job-ID und kann entweder unterschiedliche Aufgaben innerhalb desselben Jobs übernehmen oder die Last der Aufgabe auf mehrere parallele Instanzen verteilen. Dies spart Zeit und Ressourcen, besonders bei Aufgaben, die in mehrere Teile aufgeteilt werden können, wie zum Beispiel bei Test-Suiten oder bei der Kompilierung großer Projekte.

Beispiel:

test_job:
  script:
    - run_tests.sh
  parallel: 4

In diesem Beispiel wird der test_job in vier Instanzen parallel ausgeführt. GitLab teilt die Last des Jobs auf, sodass alle vier Instanzen gleichzeitig ausgeführt werden, um die Gesamtlaufzeit zu verkürzen.

31.10.2 Verwendung von parallel: matrix

Zusätzlich zur einfachen Parallelisierung kann das parallel-Keyword auch verwendet werden, um eine Matrix von Variablen für die verschiedenen Instanzen zu erstellen. Mit der Matrix-Funktion können verschiedene Kombinationen von Variablen definiert werden, sodass jeder parallele Job eine andere Konfiguration oder Umgebung testen kann.

Beispiel mit Matrix:

test_job:
  script:
    - run_tests.sh
  parallel:
    matrix:
      - VARIANT: [debug, release]
      - OS: [linux, windows]

In diesem Beispiel werden vier parallele Instanzen des Jobs ausgeführt: debug-linux, debug-windows, release-linux und release-windows. Jede Instanz verwendet eine andere Kombination der angegebenen Variablen und führt den Job mit diesen Konfigurationen aus.

31.10.3 Anwendungsfälle für parallel

31.10.3.1 Effiziente Nutzung von parallel

Das parallel-Keyword sollte verwendet werden, um die Ausführungszeit der Pipeline zu optimieren. Es ist jedoch wichtig sicherzustellen, dass genügend Runner zur Verfügung stehen, um die parallelen Instanzen zu handhaben, da sonst die parallelen Jobs nicht zur Verbesserung der Laufzeit beitragen. Zudem sollten die Aufgaben klar aufteilbar sein, um Konflikte oder redundante Arbeit zu vermeiden.


Weitere Informationen finden sich in der GitLab-Dokumentation zu parallel.

31.11 Timeout in GitLab CI

Das timeout-Keyword in GitLab CI legt fest, wie lange ein Job maximal ausgeführt werden darf, bevor er abgebrochen wird. Es wird verwendet, um Jobs, die möglicherweise in Endlosschleifen geraten oder zu lange laufen, zu beenden. Dies hilft dabei, Ressourcen zu sparen und sicherzustellen, dass die Pipeline nicht unnötig lange blockiert wird.

31.11.1 Funktionsweise von timeout

Standardmäßig haben Jobs in GitLab CI eine maximale Ausführungszeit von 1 Stunde. Mit dem timeout-Keyword kann diese Zeit entweder verkürzt oder verlängert werden, um den Anforderungen des Jobs gerecht zu werden. Die Zeitangabe erfolgt im Format Xh Xm Xs (für Stunden, Minuten und Sekunden).

Beispiel:

job_name:
  script:
    - make build
  timeout: 30m

In diesem Beispiel wird der Job job_name nach 30 Minuten abgebrochen, falls er bis dahin nicht abgeschlossen ist. Dies verhindert, dass der Job unnötig lange Ressourcen belegt.

31.11.2 Anwendungsfälle für timeout

31.11.3 Globale und spezifische Timeouts


Weitere Informationen finden sich in der GitLab-Dokumentation zu timeout.

31.12 When in GitLab CI

Das when-Keyword in GitLab CI steuert, wann ein Job in einer Pipeline ausgeführt wird. Es legt fest, unter welchen Bedingungen ein Job gestartet werden soll. Dies ist besonders nützlich, um Jobs bedingt auszuführen, basierend auf bestimmten Pipeline-Ereignissen oder -Ergebnissen. Es gibt drei primäre Optionen für when: on_success, on_failure, und manual.

31.12.1 Optionen von when

31.12.2 Anwendungsfälle für when

31.12.3 Kombination mit allow_failure

Das when-Keyword kann in Kombination mit anderen Keywords wie allow_failure verwendet werden, um noch mehr Kontrolle über die Job-Ausführung zu erlangen. Dies ist besonders nützlich in komplexen Pipelines, wo bedingte und nicht-kritische Jobs gemischt werden.

Beispiel mit allow_failure:

optional_job:
  script:
    - echo "Running optional job"
  when: manual
  allow_failure: true

In diesem Beispiel wird der optional_job manuell ausgeführt und sein Fehlschlag beeinflusst nicht den Erfolg der gesamten Pipeline.


Weitere Informationen finden sich in der GitLab-Dokumentation zu when.

31.13 Rules in GitLab CI

Das rules-Keyword in GitLab CI bietet eine präzisere Kontrolle über die Bedingungen, unter denen ein Job ausgeführt wird. Im Gegensatz zu einfacheren Keywords wie only und except bietet rules flexible und detaillierte Logik, um verschiedene Bedingungen und Variablen zu berücksichtigen. Es ist eine mächtige Funktion, die es ermöglicht, komplexe und dynamische Pipeline-Bedingungen zu definieren.

31.13.1 Funktionsweise von rules

Das rules-Keyword ermöglicht es, Bedingungen in Form einer Liste festzulegen. Die einzelnen Bedingungen werden von oben nach unten ausgewertet. Sobald eine Bedingung erfüllt ist, wird der Job zur Ausführung in die Pipeline aufgenommen. Jede Regel besteht aus einem oder mehreren Ausdrücken, die auf GitLab CI/CD-Variablen basieren und die Bedingung bestimmen.

Beispiel:

build_job:
  script:
    - make build
  rules:
    - if: '$CI_COMMIT_REF_NAME == "main"'
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

In diesem Beispiel wird der Job build_job entweder dann ausgeführt, wenn der Commit im main-Branch erfolgt oder wenn die Pipeline von einem Merge-Request-Event ausgelöst wurde.

31.13.2 Bedingungsarten

Das rules-Keyword unterstützt mehrere Bedingungsarten:

Beispiel mit changes:

test_job:
  script:
    - npm test
  rules:
    - changes:
      - src/*

In diesem Beispiel wird der test_job nur ausgeführt, wenn Dateien im src/-Verzeichnis geändert wurden.

Beispiel mit exists:

deploy_job:
  script:
    - ./deploy.sh
  rules:
    - exists:
      - Dockerfile

Hier wird der deploy_job nur ausgeführt, wenn die Datei Dockerfile im Repository vorhanden ist.

31.13.3 Verwendung von rules für komplexe Logik

Das rules-Keyword ist besonders nützlich, um komplexe Workflows zu implementieren, z. B. wenn bestimmte Jobs nur in bestimmten Umgebungen oder für spezifische Ereignisse ausgeführt werden sollen. Es bietet mehr Flexibilität als die älteren Keywords only und except.

Beispiel für eine komplexere Regel:

deploy_job:
  script:
    - ./deploy.sh
  rules:
    - if: '$CI_COMMIT_REF_NAME == "main"'
      when: manual
    - if: '$CI_COMMIT_REF_NAME == "develop"'
      when: always

In diesem Beispiel wird der deploy_job manuell ausgeführt, wenn er sich im main-Branch befindet, und immer automatisch ausgeführt, wenn er im develop-Branch läuft.

31.13.4 Regeln für unterschiedliche Pipeline-Typen

rules kann auch verwendet werden, um unterschiedliche Pipeline-Typen zu steuern, z. B. Merge-Request-Pipelines, Push-Pipelines oder Scheduled Pipelines. Dies ermöglicht eine präzise Steuerung darüber, wann Jobs in bestimmten Szenarien ausgeführt werden sollen.

Beispiel für Pipeline-Typen:

ci_job:
  script:
    - run_ci_tests.sh
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

Hier wird der Job ci_job nur dann ausgeführt, wenn die Pipeline von einem Merge-Request-Event ausgelöst wurde.


Weitere Informationen finden sich in der GitLab-Dokumentation zu rules besuchen.

31.14 Environment in GitLab CI

Das environment-Keyword in GitLab CI wird verwendet, um Jobs mit spezifischen Umgebungen zu verknüpfen. Diese Umgebungen sind in der Regel Entwicklungs-, Test- oder Produktionsumgebungen, in denen der Code bereitgestellt wird. Das environment-Keyword ermöglicht die Steuerung und Visualisierung von Bereitstellungen und erleichtert die Verwaltung von Deployments über verschiedene Umgebungen hinweg.

31.14.1 Funktionsweise von environment

Mit dem environment-Keyword kann ein Job so konfiguriert werden, dass er auf eine bestimmte Umgebung abzielt. GitLab CI unterstützt die Definition von Umgebungen wie staging, production oder testing. Diese Umgebungen werden in der GitLab-Benutzeroberfläche angezeigt, und es ist möglich, den Status von Bereitstellungen in jeder Umgebung zu überwachen.

Beispiel:

deploy_production:
  stage: deploy
  script:
    - ./deploy.sh
  environment:
    name: production
    url: https://production.example.com

In diesem Beispiel wird der Job deploy_production mit der Produktionsumgebung (production) verknüpft, und die URL der Umgebung wird im GitLab-UI angezeigt.

31.14.2 Parameter von environment

Beispiel mit on_stop:

deploy_staging:
  stage: deploy
  script:
    - ./deploy_staging.sh
  environment:
    name: staging
    url: https://staging.example.com
    on_stop: stop_staging

stop_staging:
  stage: deploy
  script:
    - ./stop_staging.sh
  when: manual
  environment:
    name: staging
    action: stop

Hier wird der deploy_staging-Job mit der staging-Umgebung verknüpft, und der stop_staging-Job kann manuell ausgelöst werden, um die Umgebung zu stoppen.

31.14.3 Verwendung von Umgebungen in CI/CD

Das environment-Keyword wird hauptsächlich in Deployments verwendet, um Jobs mit spezifischen Umgebungen zu verbinden. Dies erleichtert das Management von Bereitstellungen, da Umgebungen wie development, staging und production klar abgegrenzt und überwacht werden können.

Anwendungsfälle:


Weitere Informationen finden sich in der GitLab-Dokumentation zu environment.

31.15 Needs in GitLab CI

Das needs-Keyword in GitLab CI ermöglicht es, Abhängigkeiten zwischen Jobs in verschiedenen Stages festzulegen. Normalerweise werden Jobs innerhalb einer Stage parallel ausgeführt, und die nächste Stage startet erst, wenn alle Jobs der vorherigen Stage abgeschlossen sind. Mit needs kannst du jedoch steuern, dass bestimmte Jobs in einer späteren Stage ausgeführt werden, sobald sie von einem Job in einer früheren Stage abhängig sind. Dies führt zu einer flexibleren und effizienteren Pipeline, da unnötige Wartezeiten zwischen den Stages vermieden werden.

31.15.1 Funktionsweise von needs

Durch das Definieren von Abhängigkeiten mithilfe von needs kannst du sicherstellen, dass Jobs früher gestartet werden, wenn sie die Ergebnisse eines bestimmten Jobs benötigen, ohne auf das Ende der gesamten vorherigen Stage zu warten.

Beispiel:

build:
  stage: build
  script:
    - make build

test:
  stage: test
  script:
    - make test
  needs: [build]

In diesem Beispiel startet der test-Job direkt nach Abschluss des build-Jobs, obwohl er sich in einer späteren Stage befindet. Die anderen Jobs in der test-Stage müssen hingegen warten, bis die build-Stage vollständig abgeschlossen ist.

31.15.2 Vorteile von needs

31.15.3 Kombination von needs mit anderen Keywords

Das needs-Keyword kann mit anderen Keywords wie dependencies, artifacts, und rules kombiniert werden, um eine noch genauere Steuerung der Pipeline zu ermöglichen.

Beispiel:

build:
  stage: build
  script:
    - make build
  artifacts:
    paths:
      - build/

test:
  stage: test
  script:
    - make test
  needs: [build]
  dependencies:
    - build

Hier sorgt needs dafür, dass der test-Job sofort nach dem build-Job startet, und mit dependencies wird festgelegt, dass der test-Job nur die Artefakte des build-Jobs benötigt.

31.15.4 Einschränkungen


Weitere Informationen finden sich in der GitLab-Dokumentation zu needs.

31.16 Bereitstellung, Distribution und Registries

In GitLab CI/CD spielen Artefakte nicht nur innerhalb der Pipeline eine wichtige Rolle, sondern sind auch entscheidend für die Bereitstellung und Distribution von Endergebnissen, sei es in Form von Build-Artefakten, Containern oder anderen Arten von Softwarepaketen. Die effiziente Verwaltung und Verteilung dieser Artefakte über verschiedene Umgebungen hinweg ist ein wesentlicher Bestandteil moderner CI/CD-Pipelines. Dabei kommen neben der kurzfristigen Speicherung von Artefakten in der Pipeline auch Registries und Artifactories für die langfristige Speicherung und Wiederverwendung zum Einsatz.

31.16.1 Bereitstellung von Artefakten innerhalb der Pipeline

Artefakte können innerhalb einer Pipeline von einem Job zu einem anderen weitergereicht werden. Dies ermöglicht die Weitergabe von Dateien oder Verzeichnissen, die für nachfolgende Stages oder das Deployment entscheidend sind. Ein typisches Beispiel ist die Bereitstellung von Build-Artefakten in Staging- oder Produktionsumgebungen.

Beispiel:

deploy_job:
  stage: deploy
  script:
    - scp build/* user@server:/path/to/deploy
  dependencies:
    - build_job
  artifacts:
    paths:
      - build/

In diesem Beispiel wird das build/-Verzeichnis, das während des Build-Prozesses erstellt wurde, auf einen externen Server bereitgestellt. Dies vermeidet, dass der Build-Prozess in der Produktionsumgebung erneut durchgeführt werden muss.

31.16.2 Verwendung von Registries zur Distribution

Für die langfristige Speicherung und Wiederverwendung von Artefakten wie Container-Images oder Softwarepaketen sind Registries eine zentrale Komponente. GitLab bietet eine Container Registry, mit der Docker-Images direkt aus der Pipeline heraus erstellt, gespeichert und versioniert werden können. Externe Systeme wie Docker Hub oder Nexus können ebenfalls für diese Zwecke genutzt werden.

  1. Container Registries: Mit der GitLab Container Registry können Docker-Images versioniert und zentral verwaltet werden. Dies ist besonders nützlich, wenn Images regelmäßig in Staging- oder Produktionsumgebungen verwendet werden.

    Beispiel zur Nutzung der GitLab Container Registry:

    build_image:
      stage: build
      script:
        - docker build -t registry.gitlab.com/your_project/your_image:latest .
        - docker push registry.gitlab.com/your_project/your_image:latest
  2. Package Registries: Für Bibliotheken und Abhängigkeiten wie Maven- oder npm-Pakete bietet GitLab eine Package Registry, die eine zentrale Speicherung und Versionierung ermöglicht. Diese Pakete können in verschiedenen Projekten wiederverwendet werden.

    Beispiel zur Veröffentlichung eines Maven-Pakets:

    publish_maven:
      stage: deploy
      script:
        - mvn deploy
      only:
        - tags

31.16.3 Integration von Artifactories

Während Registries spezifisch für Container- oder Softwarepakete konzipiert sind, bieten Artifactories wie JFrog Artifactory oder Nexus Repository Manager umfassendere Funktionen zur Speicherung und Verteilung von Artefakten in verschiedenen Formaten. Diese Systeme sind besonders nützlich in großen Unternehmen, die komplexe Anforderungen an die Versionierung und Verteilung von Artefakten haben.

Artifactories ermöglichen die Zentralisierung der Artefaktverwaltung und bieten Funktionen wie Zugriffskontrolle, Audit-Logs und erweiterte Unterstützung für unterschiedliche Paketformate (z. B. Docker, Maven, npm, NuGet).

Integration einer externen Artifactory in GitLab CI:

build_and_deploy:
  stage: deploy
  script:
    - curl -u $ARTIFACTORY_USER:$ARTIFACTORY_PASSWORD \
      -T build/my_artefact.jar \
      "https://artifactory.example.com/artifactory/libs-release-local/my_artefact.jar"

In diesem Beispiel wird ein Artefakt in eine externe Artifactory hochgeladen, wodurch es für die spätere Nutzung in verschiedenen Projekten und Umgebungen bereitgestellt wird.

31.16.4 Verteilung von Artefakten in unterschiedlichen Umgebungen

Artefakte können in verschiedenen Umgebungen, wie Staging oder Produktion, verwendet werden. Dabei ist es wichtig, dass die Artefakte den Anforderungen der jeweiligen Umgebung entsprechen. Dies kann über Umgebungsvariablen oder spezifische Konfigurationen gesteuert werden, um sicherzustellen, dass die Artefakte korrekt bereitgestellt werden.

Beispiel einer Pipeline mit Umgebungsvariablen für unterschiedliche Deployments:

deploy_production:
  stage: deploy
  script:
    - scp build/* user@prod-server:/path/to/deploy
  environment:
    name: production
    url: https://prod.example.com

In diesem Beispiel wird das Artefakt in der Produktionsumgebung bereitgestellt, wobei Umgebungsvariablen wie die URL der Zielumgebung definiert sind.


Weitere Informationen finden sich in der GitLab-Dokumentation.

31.17 Best Practices für die Arbeit mit Artefakten und Registries

Die effiziente Arbeit mit Artefakten und die richtige Verwendung von Registries in einer GitLab CI/CD-Pipeline erfordert sorgfältige Planung und eine gute Strukturierung, um die Performance der Pipeline zu maximieren, Speicherressourcen zu optimieren und den Entwicklungsprozess zu vereinfachen. In diesem Abschnitt werden Best Practices vorgestellt, die dabei helfen, den Umgang mit Artefakten und Registries zu verbessern.

31.17.1 Beschränkung der Artefaktgröße

Artefakte, die in einer Pipeline generiert und gespeichert werden, können schnell große Mengen an Speicherplatz beanspruchen, was die Geschwindigkeit der Pipeline beeinträchtigen kann. Es ist daher wichtig, nur die notwendigen Dateien als Artefakte zu speichern und unnötig große Dateien zu vermeiden.

Beispiel:

build_job:
  script:
    - tar -czf build.tar.gz build/
  artifacts:
    paths:
      - build.tar.gz

In diesem Beispiel wird das Verzeichnis build/ komprimiert, bevor es als Artefakt gespeichert wird, um Speicherplatz zu sparen.

31.17.2 Verwendung von expire_in, um Speicher zu optimieren

Artefakte sollten nicht länger gespeichert werden, als sie benötigt werden. Durch die Festlegung von Ablaufzeiten für Artefakte kann der Speicherverbrauch optimiert und das Risiko eines überfüllten Dateisystems vermieden werden.

Beispiel:

artifacts:
  paths:
    - build/
  expire_in: 1 day

In diesem Beispiel werden die Artefakte nur einen Tag lang aufbewahrt. Dies ist sinnvoll, wenn die Artefakte nur kurzfristig benötigt werden.

31.17.3 Verwendung von Registries zur langfristigen Artefaktverwaltung

Für Build-Artefakte, die in verschiedenen Projekten oder Umgebungen wiederverwendet werden müssen, ist die Nutzung von Registries eine Best Practice. Container-Registries (z. B. für Docker-Images) oder Package-Registries (z. B. für Maven-Pakete) bieten eine zentrale Plattform, um Artefakte langfristig zu speichern, zu versionieren und zu verteilen.

Beispiel einer Container-Registry-Integration:

docker_build:
  stage: build
  script:
    - docker build -t registry.gitlab.com/your_project/your_image:latest .
    - docker push registry.gitlab.com/your_project/your_image:latest
  only:
    - master

Hier wird das Docker-Image in die GitLab Container Registry hochgeladen und für zukünftige Deployments gespeichert.

31.17.4 Minimierung der Artefaktgröße durch gezielte Auswahl der Dateien

Anstatt komplette Verzeichnisse als Artefakte zu speichern, solltest du gezielt nur die benötigten Dateien auswählen. Dies verbessert die Pipeline-Effizienz, da weniger Daten gespeichert und heruntergeladen werden müssen.

Beispiel:

artifacts:
  paths:
    - build/output.jar
    - build/reports/*

In diesem Beispiel werden nur die Build-Ausgabe und Testberichte gespeichert, während unnötige Dateien ignoriert werden.

31.17.5 Verwendung von when: on_failure und when: on_success, um Artefakte nur bei Bedarf zu speichern

Um zu verhindern, dass bei jedem Pipeline-Lauf unnötig viele Artefakte gespeichert werden, kannst du das when-Keyword verwenden, um Artefakte nur bei Erfolg oder Fehlschlag eines Jobs zu speichern.

Beispiel:

artifacts:
  paths:
    - logs/
  when: on_failure

In diesem Fall werden die Logs nur dann gespeichert, wenn der Job fehlschlägt.

31.17.6 Nutzung externer Artifactories für komplexe Anforderungen

Für Unternehmen mit komplexen CI/CD-Anforderungen oder großen Artefaktsammlungen bieten externe Artifactories wie JFrog Artifactory oder Nexus Repository Manager umfassende Funktionen zur Versionierung, Verteilung und Verwaltung von Artefakten.

Beispiel für die Integration von Artifactory:

upload_to_artifactory:
  script:
    - curl -u $ARTIFACTORY_USER:$ARTIFACTORY_PASSWORD \
      -T build/output.jar \
      "https://artifactory.example.com/artifactory/libs-release-local/my_project/output.jar"

Hier wird ein Artefakt in eine externe Artifactory hochgeladen, um es für zukünftige Builds und Deployments bereitzustellen.


Weitere Informationen finden sich in der GitLab-Dokumentation.