Zurück zum Katalog
Season 25 14 Episoden 54 min 2026

GitLab CI/CD

Ausgabe 2026. Ein umfassender Leitfaden zum Verständnis und zur Nutzung von GitLab CI/CD für Ihre Software-Deployments, der alles von den Grundlagen der .gitlab-ci.yml bis hin zu fortgeschrittenen Konzepten wie Directed Acyclic Graphs und Multi-project Pipelines abdeckt.

CI/CD DevOps
GitLab CI/CD
Aktuelle Wiedergabe
Click play to start
0:00
0:00
1
Das .gitlab-ci.yml Paradigma
Entdecken Sie die grundlegenden Konzepte von GitLab CI/CD. Diese Episode behandelt die .gitlab-ci.yml-Datei, die Stage- und Job-Architektur und wie die sequenzielle Ausführung standardmäßig funktioniert.
4m 02s
2
Runners und Executors
Lernen Sie GitLab Runners kennen, die Ausführungs-Engines hinter Ihren CI/CD-Pipelines. Wir untersuchen den Unterschied zwischen GitLab-hosted und self-managed Runners und wie Executors die Job-Umgebung definieren.
3m 46s
3
Anatomie eines CI/CD-Jobs
Tauchen Sie in den grundlegenden Baustein von Pipelines ein: den Job. Diese Episode erklärt Job-Scripts, Default-Keywords und wie man komplexe Pipeline-Logs organisiert.
4m 10s
4
CI/CD Variables und Secrets
Erfahren Sie, wie Sie Konfigurationen und sensible Daten in GitLab CI/CD mithilfe von Variables verwalten. Lernen Sie die Unterschiede zwischen Predefined Variables, benutzerdefinierten UI-Variables und File-Type Variables kennen.
4m 14s
5
Artifacts vs. Caches
Verstehen Sie den entscheidenden Unterschied zwischen Artifacts und Caches in GitLab CI/CD. Erfahren Sie, wann Sie welches Konzept verwenden sollten, um Daten zwischen Stages weiterzugeben oder die Ausführung Ihrer Pipeline zu beschleunigen.
3m 46s
6
Ausführungssteuerung mit Rules
Entdecken Sie, wie Sie mit dem rules-Keyword dynamisch steuern können, wann Jobs zu Ihrer Pipeline hinzugefügt werden. Lernen Sie, Bedingungen, Variables und Dateiänderungen zu nutzen, um die Ausführung zu optimieren.
3m 56s
7
Directed Acyclic Graphs mit Needs
Befreien Sie sich von streng sequenziellen Stages. Diese Episode erklärt, wie Sie das needs-Keyword verwenden, um Directed Acyclic Graphs (DAGs) zu erstellen und die Pipeline-Ausführung drastisch zu beschleunigen.
2m 54s
8
Merge Request Pipelines
Erfahren Sie, wie Sie Pipelines konfigurieren, die nur im Kontext eines Merge Requests ausgeführt werden. Wir behandeln Pipeline Sources und Sicherheitsaspekte beim Umgang mit Community Forks.
3m 50s
9
Downstream Pipelines
Meistern Sie Pipeline Triggers, um komplexe Architekturen zu orchestrieren. Diese Episode schlüsselt die Unterschiede zwischen Parent-Child Pipelines für Monorepos und Multi-project Pipelines für Microservices auf.
3m 55s
10
Environments und Deployments
Bringen Sie Transparenz in Ihre Deployments mit GitLab Environments. Erfahren Sie, wie Sie CI/CD-Jobs bestimmten Zielen wie Staging und Production zuordnen und nachverfolgen, welcher Code wo läuft.
3m 40s
11
Dynamic Environments und Review Apps
Stellen Sie für jeden Pull Request temporäre Infrastruktur bereit. Diese Episode befasst sich mit Dynamic Environments, dem Erfassen generierter URLs und der Bereinigung von Ressourcen mit on_stop-Jobs.
3m 49s
12
DRY-Konfigurationen mit Includes
Halten Sie Ihre CI/CD-Konfiguration DRY (Don't Repeat Yourself). Entdecken Sie, wie Sie das include-Keyword verwenden, um Ihre Pipeline-Konfiguration über mehrere Dateien und Projekte hinweg zu modularisieren.
4m 10s
13
CI/CD Components und der Catalog
Erkunden Sie die moderne Evolution der Pipeline-Wiederverwendbarkeit: CI/CD Components. Erfahren Sie, wie Sie Component-Projekte erstellen, Semantic Versioning nutzen und den GitLab CI/CD Catalog einsetzen.
3m 57s
14
Compile-Time CI Expressions
Schalten Sie die ultimative Pipeline-Dynamik mit CI/CD Configuration Expressions frei. Erfahren Sie, wie die Compile-Time-Syntax Inputs und Matrices evaluiert, noch bevor Jobs ausgeführt werden.
4m 43s

Episoden

1

Das .gitlab-ci.yml Paradigma

4m 02s

Entdecken Sie die grundlegenden Konzepte von GitLab CI/CD. Diese Episode behandelt die .gitlab-ci.yml-Datei, die Stage- und Job-Architektur und wie die sequenzielle Ausführung standardmäßig funktioniert.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. GitLab CI/CD, Folge 1 von 14. Viele Engineering-Teams verlassen sich auf unübersichtliche, undokumentierte Release-Prozesse, die nur eine Person wirklich versteht. Der tatsächliche Weg zur Production bleibt unsichtbar, bis etwas kaputtgeht. Das dot gitlab dash c i dot yml Paradigma ändert dies, indem es deinen gesamten Build- und Release-Lifecycle in einen transparenten, sequenziellen Graphen übersetzt. GitLab CI/CD ist das integrierte Continuous Integration und Continuous Deployment System für GitLab. Es wird vollständig über eine einzige Konfigurationsdatei namens dot gitlab dash c i dot yml gesteuert. Du platzierst diese Datei im Root-Directory deines Projekt-Repositorys. Da sie zusammen mit deinem Application-Code committet wird, ist dein Deployment-Prozess versionskontrolliert, auditierbar und für jeden Developer zugänglich, der sich das Repository ansieht. Wenn du einen Commit pushst, der diese Datei enthält, erkennt GitLab das sofort und triggert eine Pipeline. Eine Pipeline ist die oberste Architekturebene deines CI/CD-Prozesses. Sie besteht aus zwei Hauptkomponenten: Jobs und Stages. Jobs legen fest, was genau passiert. Ein Job enthält die spezifischen Shell-Commands oder Skripte, die zur Ausführung eines Tasks benötigt werden, zum Beispiel zum Kompilieren von Source Code, Formatieren von Text oder Verschieben von Files auf einen Server. Stages legen fest, wann diese Jobs ausgeführt werden. Du organisierst Jobs in Stages, um den chronologischen Ablauf der Execution zu steuern. Stell dir eine Standard-Pipeline mit drei Stages vor. Ganz oben in deiner YAML-Konfigurationsdatei deklarierst du deine Stages in genau der Reihenfolge, in der sie laufen sollen: build, test und deploy. Unter dieser Liste definierst du deine einzelnen Jobs und mappst sie auf diese definierten Stages. Du beginnst damit, einen Job namens build dash job zu schreiben, und weist ihn der build Stage zu. Sein Skript sagt dem System, dass es deine Application kompilieren soll. Als Nächstes schreibst du einen Job namens test dash job, weist ihn der test Stage zu und übergibst den Command, um deine Test-Suite auszuführen. Schließlich schreibst du einen deploy dash prod job, verlinkst ihn mit der deploy Stage und gibst ihm die Instructions, die kompilierte Application in dein Production-Environment zu pushen. Hier ist die entscheidende Erkenntnis: GitLab verarbeitet diese Stages strikt nacheinander. Die Pipeline beginnt mit der build Stage. Das System führt deinen build Job aus. Wenn dieser Job erfolgreich abgeschlossen ist, geht die Pipeline automatisch zur test Stage über und führt den test Job aus. Wenn die Tests erfolgreich durchlaufen, geht es weiter zur deploy Stage. Diese strikte Reihenfolge fungiert als definitives Quality Gate. Wenn ein Job an irgendeiner Stelle fehlschlägt – zum Beispiel, wenn ein Unit-Test während der test Stage fehlschlägt –, hält die gesamte Pipeline an. Die deploy Stage wird niemals ausgeführt, was bedeutet, dass kaputter Code nicht in Production gelangen kann. Da diese Logik klar in der YAML-Datei deklariert ist, übersetzt das GitLab User Interface sie in einen visuellen Pipeline-Graph. Jeder in deinem Team kann sich einen Commit ansehen, auf den Graph schauen und sofort verstehen, wo genau sich der Code in der Pipeline befindet, welche Stage erfolgreich war und wo exakt ein Fehler aufgetreten ist. Die Kernstärke dieses Paradigmas ist die Zentralisierung. Indem du Stages und Jobs in einem einzigen Root-File definierst, ist deine Deployment-Sequenz kein Geheimnis mehr, sondern wird zu einem lesbaren, wiederholbaren Prozess, der genau am selben Ort lebt wie dein Code. Wenn du die Show unterstützen möchtest, kannst du auf Patreon nach DevStoriesEU suchen. Das war's für diese Folge. Danke fürs Zuhören und keep building!
2

Runners und Executors

3m 46s

Lernen Sie GitLab Runners kennen, die Ausführungs-Engines hinter Ihren CI/CD-Pipelines. Wir untersuchen den Unterschied zwischen GitLab-hosted und self-managed Runners und wie Executors die Job-Umgebung definieren.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. GitLab CI/CD, Folge 2 von 14. Du verbringst Stunden damit, eine perfekte Pipeline-Konfigurationsdatei zu schreiben, committest sie und wartest. Doch nichts passiert. Deine Pipeline ist völlig nutzlos ohne eine Compute Engine, die darauf wartet, diese Anweisungen auszuführen. Hier kommen GitLab Runner und Executors ins Spiel. Es gibt den weitverbreiteten Irrglauben, dass die GitLab-Anwendung selbst deine Build-Skripte ausführt. Das tut sie nicht. GitLab managt das Repository und trackt den Status deiner Pipelines, aber es delegiert die eigentliche Ausführung strikt. Ein GitLab Runner ist eine separate Anwendung, die als Agent fungiert. Er pollt die GitLab-Instanz kontinuierlich und prüft, ob es ausstehende Jobs gibt, die er bearbeiten darf. Sobald er einen findet, pullt er die Job-Payload, führt die Befehle aus und sendet die Logs und Ergebnisse zurück an GitLab. Du hast zwei Hauptmöglichkeiten, diese Agents bereitzustellen. Der einfachste Weg sind GitLab-hosted Runner. Diese werden für dich auf GitLab SaaS gemanagt und decken gängige Environments wie Linux, macOS und Windows ab. Oft brauchst du jedoch ein Custom Setup. Vielleicht erfordert dein Build spezielle Hardware, wie eine bestimmte GPU, oder braucht Zugriff auf ein privates internes Netzwerk. In diesem Fall nutzt du self-managed Runner. Du installierst die Runner-Anwendung auf deiner eigenen Infrastruktur. Du kannst diese self-managed Runner breit über eine gesamte GitLab-Instanz scopen, sie für eine Gruppe verwandter Projekte sharen oder sie auf ein einzelnes, spezifisches Projekt beschränken. Sobald ein Runner einen Job übernimmt, muss er genau wissen, wie und wo die Befehle ausgeführt werden sollen. Dies wird durch den Executor definiert. Der Executor legt das spezifische Execution Environment für den Job fest. Zwei der gängigsten Typen sind der Shell-Executor und der Docker-Executor. Der Shell-Executor ist simpel. Er führt den Job direkt auf dem Betriebssystem des Hosts aus, über eine Standard-Terminal-Shell wie Bash oder PowerShell. Deswegen müssen alle Dependencies auf diesem Host vorinstalliert sein. Der Docker-Executor arbeitet anders. Er fährt für jeden einzelnen Job einen frischen, isolierten Container hoch, führt die Skripte darin aus und reißt ihn danach wieder ab. Das garantiert jedes Mal ein komplett sauberes Environment. Lass uns ein konkretes Szenario durchgehen, indem wir einen self-managed Projekt-Runner lokal mit einem Shell-Executor registrieren. Zuerst gehst du in deine spezifischen Projekteinstellungen in GitLab und erstellst einen neuen Runner. GitLab generiert dann ein eindeutiges Authentication Token. Als Nächstes installierst du die GitLab Runner-Anwendung auf deiner lokalen Maschine. In deinem lokalen Terminal führst du den register-Befehl aus. Der Prompt wird nach zwei Hauptinformationen fragen. Er braucht die URL deiner GitLab-Instanz und das Authentication Token, das du gerade generiert hast. Dieser Schritt verlinkt deine lokale Maschine sicher mit diesem spezifischen Projekt. Zum Schluss wird dich das Setup bitten, einen Executor auszuwählen. Du tippst shell ein. Ab diesem Moment wird deine lokale Maschine jedes Mal, wenn ein Job in diesem GitLab-Projekt getriggert wird, diesen pullen und die Befehle direkt in ihrem lokalen Terminal-Environment ausführen. Hier ist die wichtigste Erkenntnis. GitLab ist der Orchestrator, aber der Runner und sein Executor bilden die eigentliche Fabrikhalle. Indem du das Management der Jobs von der Execution der Jobs entkoppelst, gewinnst du die Flexibilität, Pipelines auf allem Möglichen laufen zu lassen – von einem Shared Cloud Container bis hin zu einem Bare-Metal-Server in einem verschlossenen Keller. Danke fürs Zuhören, Happy Coding zusammen!
3

Anatomie eines CI/CD-Jobs

4m 10s

Tauchen Sie in den grundlegenden Baustein von Pipelines ein: den Job. Diese Episode erklärt Job-Scripts, Default-Keywords und wie man komplexe Pipeline-Logs organisiert.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. GitLab CI/CD, Folge 3 von 14. Du hast eine Pipeline mit zwanzig Jobs, und jeder einzelne beginnt mit der Ausführung des exakt gleichen Setup-Commands. Wenn sich dieser Setup-Prozess ändert, musst du jetzt zwanzig verschiedene Stellen updaten, und wenn du auch nur eine einzige vergisst, geht dein Build kaputt. Diese Wiederholung aufzulösen, beginnt damit, die Anatomie eines CI/CD-Jobs zu verstehen. Ein Job ist die grundlegende Ausführungseinheit in GitLab CI/CD. Er wird durch einen Namen definiert und muss mindestens ein Command enthalten, das ausgeführt wird. Dieser Haupt-Ausführungsblock wird mit dem Keyword script definiert. Das script repräsentiert ein Array von Commands, die vom Runner nacheinander ausgeführt werden. Wenn ein Command fehlschlägt, stoppt der Job sofort und wird als failed markiert. Jobs laufen selten in einem Vakuum. Oft muss das Environment vor der Ausführung vorbereitet werden, und manchmal brauchen sie danach ein Cleanup. Hier kommen die Keywords before script und after script ins Spiel. Stell dir ein Ruby-Projekt vor. Bevor du deine Tests ausführst oder einen Linter laufen lässt, musst du deine Dependencies installieren. Du packst dein bundle install Command in den before script-Block. Der Runner führt dieses before script zuerst aus. Wenn es erfolgreich ist, läuft das main script. Sobald das main script fertig ist, wird das after script ausgeführt. Hier ist die wichtigste Erkenntnis. Das after script läuft auch dann, wenn das main script fehlschlägt. Das macht es zum richtigen Ort, um Network Connections zu schließen, temporäre Credentials zu löschen oder Test-Datenbanken aufzuräumen. Dasselbe bundle install Command in jeden einzelnen Test-Job zu schreiben, wird schnell repetitiv. Um das zu beheben, nutzt du das Keyword default auf der obersten Ebene deiner Config-Datei. Jede Config, die unter default definiert ist, wird automatisch von allen Jobs in der Pipeline geerbt. Du deklarierst dein bundle install before script ein einziges Mal im default-Block. Jetzt führt jeder Job es automatisch aus. Wenn ein bestimmter Job es nicht braucht, definierst du ein leeres before script innerhalb dieses spezifischen Jobs. Diese lokale Definition überschreibt den globalen default. Manchmal brauchst du eine Job-Definition in deiner Datei, willst aber nicht, dass sie wirklich läuft. Vielleicht schreibst du ein Base-Template, von dem andere Jobs erben sollen, oder du möchtest einen flaky Test vorübergehend deaktivieren, ohne den Code komplett zu löschen. Das machst du, indem du den Job versteckst. Füge einfach einen Punkt ganz an den Anfang des Job-Namens hinzu. Wenn GitLab die Pipeline-Config parst, ignoriert es jeden Job-Namen, der mit einem Punkt beginnt, komplett. Der Job taucht nicht im User Interface auf und wird nicht ausgeführt. Wenn deine Pipeline wächst, kann das Web-Interface mit Dutzenden von einzelnen Jobs ziemlich unübersichtlich werden. Wenn du mehrere eng verwandte Jobs hast, kannst du sie im Pipeline-Graph visuell gruppieren. Das erreichst du, indem du den Jobs ein gemeinsames Prefix gibst, gefolgt von einem Slash oder einem Doppelpunkt. Wenn du zum Beispiel drei separate Jobs build slash ruby one, build slash ruby two und build slash ruby three nennst, kollabiert das Interface sie zu einer einzigen Dropdown-Gruppe, die einfach build heißt. Ein Klick auf die Gruppe expandiert sie und zeigt die einzelnen Jobs darin an. Das ändert nichts daran, wie die Jobs auf den Runnern ausgeführt werden, aber es macht eine riesige Pipeline auf einen Blick viel leichter lesbar. Eine gut strukturierte Pipeline trennt das Setup von der Execution, nutzt defaults, um duplizierten Code zu eliminieren, und verlässt sich auf Naming Conventions, um das visuelle Interface strikt auf das Wesentliche zu fokussieren. Das war's für diese Folge. Danke fürs Zuhören und keep building!
4

CI/CD Variables und Secrets

4m 14s

Erfahren Sie, wie Sie Konfigurationen und sensible Daten in GitLab CI/CD mithilfe von Variables verwalten. Lernen Sie die Unterschiede zwischen Predefined Variables, benutzerdefinierten UI-Variables und File-Type Variables kennen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. GitLab CI/CD, Folge 4 von 14. Einen API Key direkt in deine Pipeline-Konfiguration zu hardcoden, ist der absolut schnellste Weg, deine gesamte Production-Umgebung zu kompromittieren. Du brauchst einen Weg, Konfiguration und Credentials dynamisch an deine Jobs zu übergeben, ohne sie für jeden sichtbar zu machen, der dein Repository lesen kann. CI/CD-Variablen und Secrets sind die Mechanismen, die das übernehmen. Wann immer ein GitLab Runner einen Job übernimmt, startet er nicht mit einem leeren State. GitLab injiziert automatisch vordefinierte Variablen in das Environment. Diese geben deinem Script sofortigen Context. Du hast Zugriff auf Variablen wie C I commit branch, die Pipeline I D und den Projektnamen. Du definierst diese nicht selbst. Sie sind einfach da, bereit, in deinen Scripts verwendet zu werden, um Logik zu routen oder Build-Artefakte zu taggen. Über den vordefinierten Context hinaus musst du deine eigenen Custom-Variablen bereitstellen. Du kannst diese an zwei Orten definieren: in deiner YAML-Konfigurationsdatei oder im GitLab UI. Die Regel, wo du sie ablegst, ist ziemlich simpel. Wenn der Wert sicher lesbar ist, wie ein Compiler-Flag oder eine Development-Server-URL, pack ihn in die YAML-Datei. Die Konfiguration bleibt so beim Code. Ist der Wert sensibel, wie ein Datenbankpasswort, definiere ihn im GitLab Projekt-UI. Wenn du ein Secret im UI hinterlegst, musst du seine Security Boundaries konfigurieren. Leute verwechseln oft das Masking einer Variable und das Protecting einer Variable. Das sind zwei völlig unterschiedliche Konzepte. Das Masking einer Variable verhindert, dass ihr Wert in den Job-Logs auftaucht. Wenn du ein Datenbankpasswort maskierst und ein schlecht geschriebenes Script versucht, es in der Konsole auszugeben, fängt GitLab den Output-Stream ab. Es ersetzt den eigentlichen Text des Passworts durch einen String aus Sternchen, bevor das Log überhaupt gespeichert wird. Masking steuert die Log-Sichtbarkeit. Hier ist die wichtigste Erkenntnis. Masking hindert einen Entwickler nicht daran, ein Script zu schreiben, das das Passwort an einen externen Server sendet. Genau da kommt Protection ins Spiel. Das Protecten einer Variable schränkt ihre Verfügbarkeit ein. Eine protected Variable wird nur in Pipelines injiziert, die auf protected Branches oder protected Tags laufen. Wenn jemand einen Merge Request von einem Standard-Feature-Branch öffnet, wird die Pipeline, die er triggert, diese Variable einfach nicht enthalten. Das verhindert, dass nicht vertrauenswürdiger Code auf Production-Secrets zugreift. Zusätzlich kannst du für extreme Sensibilität versteckte Settings im UI verwenden. Sobald eine Variable gespeichert ist, wird ihr Wert im Interface unkenntlich gemacht. Selbst Projekt-Maintainer können den Raw-Text später nicht einfach abrufen. Das bedeutet, dass jemand mit Zugriff nicht einfach die Settings-Page scrapen kann, um all deine Tokens zu stehlen. Überlegen wir nun, wie die Variable in deine Application gelangt. Die meisten Variablen werden als Standard-Environment-Variablen injiziert. Aber einige Tools weigern sich, Environment-Variablen zu lesen, und bestehen darauf, aus einem physischen File zu lesen. Das AWS Command Line Interface erwartet zum Beispiel oft ein formatiertes Credentials-File, das auf der Disk liegt. Anstatt ein Pipeline-Script zu schreiben, das ein File erstellt, den Variablen-Text hineindumpt und dann versucht, es später sicher zu löschen, kannst du eine File-Type-Variable verwenden. Wenn du eine Variable im UI als File-Type konfigurierst, übernimmt der Runner die Logistik automatisch. Wenn der Job startet, nimmt der Runner den Textwert, schreibt ihn sicher in ein temporäres File auf der Runner-Disk und setzt die Environment-Variable so, dass sie den File-Path enthält, nicht den File-Inhalt. Du lässt dein AWS-Tool einfach auf den Path zeigen, der von der Variable bereitgestellt wird. Wenn der Job beendet ist, zerstört der Runner das File automatisch. Beim Absichern deiner Pipeline geht es darum, die Exposure bei jedem Schritt zu minimieren. Verlass dich nicht auf Log-Masking, um dich vor Malicious Code zu schützen, und schreib keine temporären Credential-Files selbst, wenn der Runner den Lifecycle sicher handhaben kann. Das war's für diese Folge. Danke fürs Zuhören und keep building!
5

Artifacts vs. Caches

3m 46s

Verstehen Sie den entscheidenden Unterschied zwischen Artifacts und Caches in GitLab CI/CD. Erfahren Sie, wann Sie welches Konzept verwenden sollten, um Daten zwischen Stages weiterzugeben oder die Ausführung Ihrer Pipeline zu beschleunigen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. GitLab CI/CD, Folge 5 von 14. Dein Build-Job läuft einwandfrei durch, aber dein Deployment-Job schlägt unerklärlicherweise mit einem File Not Found Error fehl. Du überprüfst den Runner, und die Dateien wurden definitiv erst vor wenigen Minuten generiert. Das Problem lässt sich meist auf ein grundlegendes Missverständnis zwischen zwei Keywords zurückführen: artifacts und cache. Diese beiden Konzepte werden häufig verwechselt, da es in beiden Fällen darum geht, Dateien auf einem Runner zu speichern, aber sie erfüllen völlig unterschiedliche Zwecke. Das cache Keyword definiert eine Liste von Dateien und Verzeichnissen, die deine Pipeline beschleunigen sollen. Es speichert heruntergeladene Dependencies zwischen verschiedenen Pipeline-Runs. Nehmen wir als Beispiel ein typisches Node-Projekt. Dein Build-Job benötigt Tausende von Packages im node_modules-Ordner. Anstatt diese jedes Mal, wenn ein Entwickler Code pusht, aus der Public Registry herunterzuladen, konfigurierst du einen Cache. Du vergibst einen Key basierend auf deiner package-lock-Datei und lässt ihn auf das node_modules-Verzeichnis zeigen. Bei nachfolgenden Runs stellt GitLab diese Dateien lokal wieder her. Hier liegt der entscheidende Punkt: Caching ist eine reine Optimierung. Wenn der Cache geleert wird, abläuft oder die Extraktion fehlschlägt, muss dein Job dennoch erfolgreich ausgeführt werden können, indem die Packages von Grund auf neu heruntergeladen werden. Ein fehlender Cache führt lediglich zu einer langsameren, nicht zu einer kaputten Pipeline. Deine Job-Logik sollte niemals von einem vorhandenen Cache abhängen. Artifacts erfüllen einen völlig anderen architektonischen Zweck. Das artifacts Keyword spezifiziert Dateien und Verzeichnisse, die von einem Job generiert werden und an nachfolgende Jobs innerhalb desselben Pipeline-Runs übergeben werden müssen. Sie stellen keine Optimierung dar. Sie sind eine strukturelle Voraussetzung für deinen CI-Flow. Zurück zum Node-Projekt: Dein Build-Job kompiliert deinen Source Code in ein finales Output-Verzeichnis namens dist. Dein Deployment-Job läuft in einer späteren Stage und benötigt genau diesen dist-Ordner, um ihn auf deinen Production-Server zu pushen. Da Jobs in isolierten Environments ausgeführt werden, kann der Deploy-Job nicht einfach auf den Workspace des Build-Jobs zugreifen. Diese Lücke schließt du mithilfe von Artifacts. Du definierst den dist-Ordner unter dem artifacts Keyword in deinem Build-Job. Nach erfolgreicher Job-Ausführung nimmt GitLab diese Dateien, verpackt sie und hängt sie an die Pipeline an. Wenn der Downstream-Deployment-Job startet, lädt GitLab dieses Artifact-Package automatisch herunter und extrahiert es in das Working Directory. Fehlt ein Artifact, schlägt der Downstream-Job fehl, da die benötigten Dateien im Workspace schlichtweg nicht existieren. Anders als bei einem Cache kannst du ein fehlendes Artifact nicht einfach aus dem Internet herunterladen. Es enthält den einzigartigen Zwischenstand deines aktuellen Pipeline-Runs. In einer korrekt konfigurierten YAML-Datei verwendest du häufig beides im selben Build-Job. Du konfigurierst den Cache so, dass er auf deinen Dependencies-Ordner zeigt, um Zeit zu sparen. Du konfigurierst die Artifacts so, dass sie auf deinen kompilierten Output-Ordner zeigen, um Daten weiterzugeben. Der Deployment-Job später in der Pipeline benötigt den Cache überhaupt nicht. Er benötigt lediglich den gebauten Code, den er nahtlos erhält, da Artifacts standardmäßig in allen nachfolgenden Stages heruntergeladen werden. Beachte diese Regel, wenn du deine nächste Pipeline konfigurierst: Verwende den Cache für externe Dependencies, die du herunterlädst, um Zeit zu sparen, und verwende Artifacts für die internen Build-Ergebnisse, die du weitergeben musst, um das Deployment abzuschließen. Das war's für heute. Vielen Dank fürs Zuhören – geh und bau was Cooles.
6

Ausführungssteuerung mit Rules

3m 56s

Entdecken Sie, wie Sie mit dem rules-Keyword dynamisch steuern können, wann Jobs zu Ihrer Pipeline hinzugefügt werden. Lernen Sie, Bedingungen, Variables und Dateiänderungen zu nutzen, um die Ausführung zu optimieren.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. GitLab CI/CD, Folge 6 von 14. Du hast gerade einen Tippfehler-Fix in eine Markdown-Datei committed, und plötzlich startet deine Pipeline eine zwanzigminütige End-to-End Test Suite. Das ist eine massive Verschwendung von Compute Minutes und deiner Geduld. Um schwere Jobs nicht auszuführen, wenn sie nicht gebraucht werden, steuerst du die Execution mit dem rules Keyword. Das rules Keyword legt genau fest, wann ein Job zu einer Pipeline hinzugefügt wird. Wenn du schon länger mit GitLab arbeitest, erinnerst du dich vielleicht noch daran, only und except zum Filtern von Jobs zu nutzen. Das sind Legacy Keywords. rules ist der moderne, mächtigere Ersatz. Unter der Haube nimmt rules eine Liste von Bedingungen. GitLab wertet diese Liste von oben nach unten aus. Sobald es einen Match findet, hört es auf zu suchen und fügt den Job entweder hinzu oder überspringt ihn, je nachdem, wie du diese spezifische Rule konfiguriert hast. Es gibt drei Hauptbedingungen, die du auswerten kannst. Die erste ist if. Die if-Bedingung wertet Pipeline-Variablen mit einem einfachen logischen Ausdruck aus. Du kannst einem Deployment Job sagen, dass er nur laufen soll, wenn der Commit Branch mit dem Default Branch übereinstimmt. Wenn die Variablen-Auswertung true zurückgibt, matcht die Rule. Die zweite Bedingung checkt nun Dateiänderungen mit dem changes Keyword. Das wertet aus, ob der aktuelle Push Dateien modifiziert hat, die auf einen bestimmten Pfad oder eine Wildcard matchen. Hier sparst du bares Geld. Stell dir einen schweren JavaScript Linter Job vor. Du willst nicht, dass dieser Linter CPU-Zyklen frisst, wenn ein Backend-Entwickler nur Datenbank-Konfigurationsdateien angefasst hat. Du fügst eine Rule mit changes hinzu und gibst die Wildcard für .js-Dateien an. Wenn der Commit Änderungen an einer JavaScript-Datei enthält, matcht die Rule und der Linter läuft. Wenn keine JavaScript-Dateien angefasst wurden, wird der Job komplett aus der Pipeline ausgeschlossen. Die dritte Bedingung ist exists. Anstatt Variablen oder kürzliche Änderungen zu checken, prüft exists einfach, ob eine bestimmte Datei in diesem Moment im Repository vorhanden ist. Vielleicht hast du ein generisches Pipeline Template, das von mehreren Projekten genutzt wird. Du kannst einen Container Build Job mit einer exists Rule definieren, die auf ein Dockerfile zeigt. Wenn das Projekt ein Dockerfile in seinem Root Directory hat, läuft der Job. Wenn nicht, wird der Job komplett übersprungen. Hier ist die wichtigste Erkenntnis. Einen Match zu finden, bedeutet nicht automatisch, dass der Job läuft. Wenn eine Rule zu true auswertet, wendet sie eine zweite Anweisung über das when Attribut an. Standardmäßig geht eine matchende Rule davon aus, dass der Job zur Pipeline hinzugefügt werden soll. Aber du kannst explizit eine Rule definieren, bei der when auf never gesetzt ist. Das ist extrem effektiv fürs Blocklisting. Du kannst eine Rule ganz oben in deine Liste packen, die besagt: Wenn die Commit Message das Wort draft enthält, setze when auf never. Da Rules von oben nach unten ausgewertet werden, wird dieser Job sofort gekillt, bevor irgendwelche anderen Bedingungen gecheckt werden. Wenn du dir eine Sache über das Steuern der Execution merkst, dann dass die Reihenfolge das Ergebnis diktiert. Platziere deine Exclusion Rules ganz oben in deiner Liste, denn in dem Moment, in dem GitLab eine true Bedingung findet, hört es auf zu lesen und loggt die Entscheidung ein. Ich möchte mir kurz einen Moment nehmen, um dir fürs Zuhören zu danken – das hilft uns sehr. Mach's gut!
7

Directed Acyclic Graphs mit Needs

2m 54s

Befreien Sie sich von streng sequenziellen Stages. Diese Episode erklärt, wie Sie das needs-Keyword verwenden, um Directed Acyclic Graphs (DAGs) zu erstellen und die Pipeline-Ausführung drastisch zu beschleunigen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. GitLab CI/CD, Folge 7 von 14. Deine Pipeline ist nicht wirklich langsam. Sie ist nur künstlich ausgebremst. Wahrscheinlich hast du schnelle Jobs, die auf langsame Jobs warten, mit denen sie absolut nichts zu tun haben, einfach nur, weil sie auf deinem Bildschirm in derselben Spalte stehen. Um das zu beheben, lässt du die starren Spalten hinter dir und baust Directed Acyclic Graphs mit Needs. Standardmäßig werden Standard-Pipelines sequenziell nach Stage ausgeführt. Du definierst Stages wie Build, Test und Deploy. Jeder Job in der Test-Stage muss komplett fertig sein, bevor irgendein Job in der Deploy-Stage starten kann. Wenn deine Test-Stage fünf Jobs hat und vier davon in zwei Minuten fertig sind, während einer zehn Minuten braucht, ist die komplette Deploy-Stage bis zur zehnten Minute blockiert. Die Ausführungsbarriere zwischen den Stages ist absolut. Das Needs-Keyword durchbricht diese Barriere. Es erlaubt dir, explizite Beziehungen zwischen Jobs zu definieren, und verwandelt deine Pipeline von einer strikten Sequenz in einen Directed Acyclic Graph. Wenn du das Needs-Keyword in einer Job-Definition verwendest, sagst du dem System ganz genau, welche vorherigen Jobs fertig sein müssen, bevor dieser hier startet. In dem Moment, in dem diese spezifischen Dependencies erfolgreich sind, wird dein Job getriggert. Er wartet nicht mehr darauf, dass die restliche Stage durchläuft. Stell dir ein Monorepo vor, das sowohl ein Frontend als auch ein Backend enthält. Deine Backend-Build- und Test-Jobs sind schnell und dauern etwa zwei Minuten. Dein Frontend-Build ist schwerfällig und braucht zehn Minuten. In einer traditionellen Pipeline kann die Deploy-Stage erst triggern, wenn sowohl die Frontend- als auch die Backend-Tests fertig sind. Dein Backend-Deployment wird quasi vom Frontend-Build als Geisel gehalten. Hier ist die entscheidende Erkenntnis. Du kannst das Needs-Keyword zu deinem Backend-Deploy-Job hinzufügen und nur den Backend-Test-Job als Dependency auflisten. Jetzt ändert sich die Ausführungslogik. Der Backend-Test-Job ist bei Minute zwei fertig. Der Backend-Deploy-Job sieht, dass seine explizite Dependency erfüllt ist, und startet sofort. Er ignoriert komplett die Tatsache, dass der Frontend-Build noch weitere acht Minuten läuft. Die Stages existieren weiterhin zur visuellen Organisation im User Interface, aber die tatsächliche Ausführungsreihenfolge wird jetzt von dem Graph diktiert, den du gebaut hast. Um das einzurichten, fügst du das Needs-Keyword zu einem Job hinzu und übergibst ein Array mit den exakten Job-Namen. Es gibt hier noch einen zweiten Vorteil in Bezug auf den Datentransfer. Normalerweise lädt ein Job Artifacts von allen erfolgreichen Jobs aus vorherigen Stages herunter. Wenn du Needs benutzt, wird der Artifact-Download zielgerichtet. Dein Job lädt nur Artifacts von den spezifischen Jobs herunter, die im Needs-Array aufgelistet sind. Das verhindert, dass dein Backend-Deploy-Job riesige, irrelevante Frontend-Assets herunterlädt, was noch mehr Zeit bei der Job-Initialisierung spart. Wenn du möchtest, dass ein Job sofort beim Erstellen der Pipeline startet und alle Stage-Verzögerungen umgeht, kannst du dem Needs-Keyword ein leeres Array übergeben. Das sagt dem System, dass der Job null Dependencies hat, und pusht ihn zur Ausführung bei Sekunde null. Der wahre Wert eines Directed Acyclic Graph ist die Entkopplung unabhängiger Workflows innerhalb einer einzigen Pipeline. Du hörst auf, Jobs danach zu organisieren, wann sie laufen sollen, und fängst an, sie rein danach zu organisieren, welche Inputs sie zur Ausführung brauchen. Danke fürs Zuhören. Passt auf euch auf, alle zusammen.
8

Merge Request Pipelines

3m 50s

Erfahren Sie, wie Sie Pipelines konfigurieren, die nur im Kontext eines Merge Requests ausgeführt werden. Wir behandeln Pipeline Sources und Sicherheitsaspekte beim Umgang mit Community Forks.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. GitLab CI/CD, Folge 8 von 14. Du betreust ein Open-Source-Projekt. Ein Unbekannter forkt es, versteckt ein Script, das Environment Variables exportiert, in einem Unit Test und reicht eine Contribution ein. Wenn dein System diesen Code automatisch auf deinen privaten Servern ausführt, sind deine Secrets weg. Um das zu verhindern, brauchst du eine strikte Grenze zwischen dem reinen Pushen von Code und dem Ausführen in einer privilegierten Umgebung. Diese Grenze wird durch Merge Request Pipelines geregelt. Normalerweise triggert GitLab eine Pipeline, jedes Mal, wenn du einen Commit auf irgendeinen Branch pushst. Eine Merge Request Pipeline verhält sich da anders. Sie ist ein spezieller Pipeline-Typ, der so konfiguriert ist, dass er auf dem Inhalt des Source Branches läuft, aber nur im Kontext eines offenen Merge Requests. Dieser Kontext gibt dir Zugriff auf spezifische Environment Variables, die mit dem Merge selbst zu tun haben, wie den Namen des Target Branches oder die Merge Request ID. Du sagst einem Job, dass er als Merge Request Pipeline laufen soll, indem du die rules Section in deinem Config File nutzt. Du schreibst eine Rule, die die Pipeline Source Variable auswertet. Du prüfst, ob die CI Pipeline Source exakt dem Text merge request event entspricht, geschrieben mit Underscores zwischen den Wörtern. Wenn du diese Rule anwendest, läuft der Job nur, wenn ein Merge Request erstellt oder aktualisiert wird. Es ist sehr üblich, das mit Rules zu kombinieren, die verhindern, dass der Job bei normalen Branch Pushes läuft. Wenn du das nicht trennst, triggert das Pushen eines Commits in einen offenen Merge Request zwei Pipelines zur exakt gleichen Zeit, die exakt die gleiche Arbeit machen. Das bringt uns zu den Security-Auswirkungen von externen Contributions. Wenn jemand dein Repository forkt, erstellt er eine komplett isolierte Kopie. Wenn er einen Merge Request von seinem Fork zurück in dein Parent Project öffnet, läuft jede Pipeline, die automatisch startet, innerhalb seines Forks. Sie nutzt seine Runner und seine Variables. Das ist genau so gewollt. Die Secrets deines Parent Projects sind sicher, weil der Code des Contributors keinen Zugriff auf deine Infrastruktur hat. Aber irgendwann musst du verifizieren, dass sein Code deine offizielle Test Suite mit deinen eigenen Database Credentials und Deployment Targets besteht. GitLab erlaubt es dir, Pipelines für diese Fork Merge Requests innerhalb des Parent Projects laufen zu lassen, aber das erfordert eine bewusste menschliche Aktion. Ein Developer oder Maintainer im Parent Project muss die Ausführung manuell triggern. In einem sauberen Workflow liest der Maintainer zuerst den eingereichten Code aus dem Fork. Er muss nach allem suchen, was bösartig, destruktiv oder schlecht programmiert ist. Erst wenn der Maintainer absolut sicher ist, dass der Code safe ist, klickt er auf den Button, um die Pipeline zu triggern. Sobald sie getriggert wurde, läuft dieser externe Code auf den Runnern des Parent Projects und hat Zugriff auf die Secrets des Parent Projects. Der manuelle Trigger fungiert als physisches Security Gate. Das ist der entscheidende Punkt. Merge Request Pipelines sind nicht nur ein Weg, um Jobs im User Interface zu gruppieren, sie sind ein grundlegender Kontrollmechanismus, der es dir erlaubt, externen Code zu evaluieren, ohne blind deine interne Infrastruktur preiszugeben. Wenn du helfen willst, den Betrieb hier am Laufen zu halten, kannst du die Show supporten, indem du auf Patreon nach DevStoriesEU suchst. Das war's für diese Folge. Danke fürs Zuhören und keep building!
9

Downstream Pipelines

3m 55s

Meistern Sie Pipeline Triggers, um komplexe Architekturen zu orchestrieren. Diese Episode schlüsselt die Unterschiede zwischen Parent-Child Pipelines für Monorepos und Multi-project Pipelines für Microservices auf.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. GitLab CI/CD, Folge 9 von 14. Du hast eine einzige YAML-Datei mit fünfhundert Jobs. Eine einzige Zeile zu ändern, fühlt sich an wie das Entschärfen einer Bombe, und die Ausführung dauert eine Stunde, weil alles in einem einzigen massiven Block abläuft. Downstream-Pipelines lösen das, indem sie diesen Monolithen in modulare, unabhängige Workflows aufteilen. Eine Downstream-Pipeline ist einfach eine beliebige GitLab CI/CD-Pipeline, die von einer anderen Pipeline getriggert wird. Die Pipeline, die den Trigger ausführt, wird Upstream-Pipeline genannt. Anstatt jeden Job in einer einzigen Sequenz auszuführen, fungiert die Upstream-Pipeline als Koordinator und delegiert die Arbeit an kleinere, fokussierte Pipelines. GitLab unterteilt Downstream-Pipelines in zwei spezifische Typen, basierend darauf, wo sie ausgeführt werden. Der erste Typ ist eine Parent-Child-Pipeline. Das passiert komplett innerhalb desselben Projekts. Wenn du ein Monorepo hast, ist ein Parent-Child-Setup genau das, was du brauchst. Die Parent-Pipeline erkennt, was sich geändert hat, und triggert nur die relevante Child-Konfiguration. Der zweite Typ ist eine Multi-Project-Pipeline. Das passiert, wenn eine Pipeline in einem Repository eine Pipeline in einem komplett anderen GitLab-Projekt triggert. Das nutzt du für Architekturen, die über mehrere Repositories verteilt sind, zum Beispiel um ein Integration-Testing-Projekt erst zu triggern, nachdem die Pipeline eines eigenständigen API-Projekts erfolgreich war. Du konfigurierst beide Typen mit einem spezifischen Job-Keyword namens trigger. Ein Trigger-Job ist grundlegend anders als ein Standard-Job. Er enthält niemals eine script-Section. Er führt keine Commands auf einem Runner aus. Sein einziger Zweck ist es, die Downstream-Pipeline zu starten. Für eine Multi-Project-Pipeline übergibst du dem trigger-Keyword den Pfad zum Zielprojekt. Für eine Parent-Child-Pipeline nutzt du das trigger-Keyword kombiniert mit dem include-Keyword, das auf eine andere YAML-Datei im selben Repository zeigt. Stell dir eine Routing-Parent-Pipeline vor, die drei separate Microservices in einem Monorepo verwaltet. Die Parent-Pipeline evaluiert den Commit und triggert drei parallele Child-Pipelines. Eine kümmert sich um den User-Service, eine um den Payment-Service und eine um den Inventory-Service. Jede Child-Pipeline hat ihre eigenen Stages, Jobs und Rules. Sie werden unabhängig voneinander ausgeführt. Standardmäßig arbeitet ein Trigger-Job nach dem Fire-and-Forget-Prinzip. Der Upstream-Job startet die Downstream-Pipeline und ist sofort erfolgreich. Wenn die Upstream-Pipeline warten und den Status der Downstream-Pipeline spiegeln soll, fügst du dem Trigger-Job den Parameter strategy depend hinzu. Das zwingt die Parent-Pipeline zum Warten, was bedeutet, dass ein Fehler in der Child-Pipeline nach oben durchgereicht wird und den Parent-Job als failed markiert. Hier ist die wichtigste Erkenntnis. Entwickler konfigurieren oft Parent-Child-Pipelines und gehen sofort davon aus, dass sie kaputt sind, weil die Child-Pipelines nicht auf der Haupt-Indexseite der Pipelines auftauchen. Das ist eine bewusste Designentscheidung. Der Haupt-Index zeigt nur die Parent-Pipelines an, um Unordnung zu vermeiden. Um die Child-Pipelines zu sehen, musst du in die Detailansicht der Parent-Pipeline klicken. Sie sind unter dem spezifischen Job verschachtelt, der sie getriggert hat. Multi-Project-Pipelines hingegen tauchen im Pipeline-Index ihrer jeweiligen Zielprojekte auf, weil sie Top-Level-Pipelines in diesen Repositories sind. Der Wechsel zu Downstream-Pipelines zwingt dich dazu, deine CI/CD-Konfiguration wie echte Softwarearchitektur zu behandeln und ein fragiles Script durch separate Komponenten mit isolierten Failure-Domains zu ersetzen. Das war's für diese Folge. Bis zum nächsten Mal!
10

Environments und Deployments

3m 40s

Bringen Sie Transparenz in Ihre Deployments mit GitLab Environments. Erfahren Sie, wie Sie CI/CD-Jobs bestimmten Zielen wie Staging und Production zuordnen und nachverfolgen, welcher Code wo läuft.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. GitLab CI/CD, Folge 10 von 14. Wenn dein Team in Slack nachfragen muss, wer gerade auf den Staging-Server gepusht hat, hast du eine Sichtbarkeitslücke in deinem Workflow. Du brauchst eine eindeutige, automatisierte Methode, um in jeder Sekunde genau zu tracken, welcher Code wo läuft, und genau dieses Problem lösen GitLab Environments und Deployments. In GitLab ist ein Environment eine logische Tracking-Einheit. GitLab provisioniert nicht automatisch deine Server oder fährt deine Cloud-Infrastruktur hoch, nur weil du ein Environment erstellt hast. Das Environment ist einfach nur ein Label. Es teilt GitLab mit, dass ein bestimmter Job in deiner Pipeline dafür zuständig ist, Code an ein bestimmtes Ziel wie Staging oder Production zu pushen. Du richtest das ein, indem du das environment Keyword direkt in deinen Deployment-Job einfügst. Du vergibst einen statischen Namen für das Ziel. Zum Beispiel könntest du einen Job namens deploy to staging erstellen und innerhalb dieses Jobs den Environment-Namen auf staging setzen. Die script Section deines Jobs übernimmt weiterhin die eigentliche Arbeit. Sie führt die Commands aus, die Dateien kopieren, Konfigurationen anwenden oder Remote-Services neu starten. Stell dir das Szenario vor, in dem du einen neuen Release Candidate deployst. Du mergest deinen Code und die Pipeline startet. Sie buildet die Anwendung, führt deine Test Suite aus und erreicht den Staging Deployment-Job. Weil du das environment Keyword an diesen Job angehängt hast, ändert GitLab, wie es die Ausführung behandelt. Es beobachtet den Job-Output ganz genau. Wenn dein Deployment Script durchgelaufen ist und der Job erfolgreich beendet wurde, registriert GitLab ein formelles Deployment Event für das Staging Environment. Hier ist der entscheidende Punkt. Die Nutzung dieses einzigen Keywords aktiviert eine ganze Reihe von Deployment Tracking Features innerhalb des GitLab Interfaces. Wenn du in der Seitenleiste zum Operate-Menü navigierst und Environments auswählst, bekommst du ein Dashboard präsentiert, das den Echtzeit-Status deiner Deployment Targets anzeigt. Für dein Staging Environment musst du nicht mehr raten, was gerade läuft. Das Dashboard zeigt den exakten Commit Hash, der aktuell aktiv ist, den Branch, aus dem dieser Commit stammt, den Autor des Codes und wie lange es her ist, dass das Deployment abgeschlossen wurde. Es erstellt einen unveränderlichen, geteilten Record des Server States. Jeder im Projekt hat exakt dieselbe Sichtbarkeit, ohne Server Logs checken oder Kollegen fragen zu müssen. Ein Klick in das Staging Environment zeigt die komplette Deployment History. Dieser historische Record ist es, der manuelle Rollbacks direkt aus dem User Interface ermöglicht. Wenn ein neuer Release Candidate den Staging-Server komplett zerschießt, musst du zur Behebung keinen Revert Commit schreiben oder manuell eine ältere Pipeline zusammenbauen. Du öffnest die History-Liste, identifizierst das letzte bekannte erfolgreiche Deployment und klickst auf den Rollback-Button daneben. GitLab führt den Deployment-Job von diesem älteren, stabilen Commit sofort erneut aus. Es ersetzt den kaputten Code und bringt dein Staging Environment schnell wieder in einen funktionierenden Zustand. Indem du das environment Keyword nutzt, schließt du die Lücke zwischen dem Ausführen von Scripts und dem Tracking von tatsächlichen Deployments. Es verwandelt einen isolierten Pipeline-Job in einen klaren, sichtbaren Record darüber, welche Software-Version aktuell auf deiner Infrastruktur läuft. Ich möchte mir kurz die Zeit nehmen, dir fürs Zuhören zu danken – das hilft uns sehr. Mach's gut!
11

Dynamic Environments und Review Apps

3m 49s

Stellen Sie für jeden Pull Request temporäre Infrastruktur bereit. Diese Episode befasst sich mit Dynamic Environments, dem Erfassen generierter URLs und der Bereinigung von Ressourcen mit on_stop-Jobs.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. GitLab CI/CD, Folge 11 von 14. Wenn du deinem Produktmanager für jeden einzelnen Feature Branch eine live klickbare URL gibst, entfällt komplett das Argument, dass es auf deinem Rechner funktioniert. Dieser Workflow basiert komplett auf Dynamic Environments und Review Apps. Standardumgebungen wie Staging oder Production sind statisch. Du definierst sie einmal und sie bleiben bestehen. Dynamic Environments werden on the fly erstellt. Du fährst sie hoch, um einen bestimmten Branch zu testen, nutzt sie und wirfst sie danach wieder weg. Wenn du ein Dynamic Environment speziell dafür nutzt, um Code-Änderungen innerhalb eines Merge Requests in der Vorschau anzusehen, nennt GitLab das eine Review App. Um ein Dynamic Environment zu erstellen, kannst du den Namen nicht in deiner Konfigurationsdatei hardcoden. Stattdessen nutzt du Pipeline-Variablen. Die wichtigste Variable dafür ist der CI commit ref slug. Diese Variable nimmt deinen Branch-Namen, wandelt ihn in Kleinbuchstaben um, entfernt Sonderzeichen und kürzt ihn. Das garantiert dir einen DNS-sicheren String, den du für die Benennung deines Environments in GitLab und deiner tatsächlichen Infrastruktur-Ressourcen nutzen kannst. Wenn du deinen Environment-Namen als das Wort review, gefolgt von einem Slash und dieser Slug-Variable definierst, generiert GitLab automatisch ein separates, getracktes Environment für jeden einzelnen Branch, den du pushst. Hier ist der entscheidende Punkt. Den Environment-Record in GitLab zu erstellen, ist nur die halbe Miete. Du musst die Reviewer auch zum tatsächlich deployten Code routen. Sagen wir mal, du fährst eine temporäre AWS Lambda-Instanz für deinen Feature Branch hoch. Wenn dein Deployment-Skript läuft, generiert AWS eine zufällige URL für diese neue Lambda-Funktion. Du kennst diese URL nicht im Voraus. Du brauchst einen Weg, diese dynamisch generierte Adresse an das GitLab User Interface zurückzugeben, damit die Reviewer darauf klicken können. Das löst du mit einem speziellen Artifact-Typ namens dotenv report. Innerhalb deines Deployment Jobs, nachdem AWS die Lambda-Funktion provisioniert und den Endpoint zurückgibt, schreibt dein Skript diese URL in eine einfache Textdatei, formatiert als Key-Value-Pair. Du konfigurierst deinen Job so, dass er diese Datei als dotenv report Artifact ausgibt. GitLab liest diese Datei am Ende des Jobs und stellt die Variable bereit. Dann konfigurierst du den environment URL Parameter in deiner Pipeline-Definition so, dass er genau diese Variable ausliest. Durch diese Verbindung zeigt dein Merge Request jetzt einen View App Button an, der die User direkt zu diesem spezifischen AWS Lambda Endpoint routet. Temporäre Infrastruktur kostet Geld. Hunderte von verwaisten Lambda-Funktionen laufen zu lassen, wird dein Budget schnell aufbrauchen. Du brauchst einen automatisierten Weg zum Aufräumen. Das machst du mit dem on stop Keyword. In deinem Deployment Job fügst du die on stop Property hinzu und gibst ihr den exakten Namen eines anderen Jobs in deiner Pipeline. Dieser zweite Job enthält dein Infrastruktur-Teardown-Skript. Indem du sie so verknüpfst, übernimmt GitLab das Lifecycle Management. Wenn ein Entwickler den Feature Branch merget oder den Branch löscht, führt GitLab diesen Teardown Job automatisch aus. Die Infrastruktur wird sofort zerstört. Der wahre Wert von Review Apps ist nicht nur die Code-Preview, sondern die Automatisierung des kompletten Infrastruktur-Lifecycles. Du provisionierst dynamisch, verknüpfst nahtlos und zerstörst zuverlässig temporäre Environments, ohne dass ein einziger Entwickler jemals eine Hosting-Konsole anfassen muss. Das war's für diese Folge. Danke fürs Zuhören und keep building!
12

DRY-Konfigurationen mit Includes

4m 10s

Halten Sie Ihre CI/CD-Konfiguration DRY (Don't Repeat Yourself). Entdecken Sie, wie Sie das include-Keyword verwenden, um Ihre Pipeline-Konfiguration über mehrere Dateien und Projekte hinweg zu modularisieren.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. GitLab CI/CD, Folge 12 von 14. Das Copy-and-Paste exakt desselben Deployment-Scripts in fünfzig verschiedene Repositories garantiert eine Sache: Wenn sich dieses Script unweigerlich ändern muss, wirst du vergessen, mindestens ein Repository zu updaten. Die Lösung ist das Schreiben von DRY-Konfigurationen mit dem include Keyword. In GitLab CI lässt dich das include Keyword deine Pipeline-Konfiguration in mehrere kleinere, wiederverwendbare Files aufteilen. Anstatt ein riesiges YAML-File zu pflegen, baust du ein modulares System. Wenn eine Pipeline triggert, pausiert GitLab, holt sich alle included Files, mergt sie zusammen und wertet dann die kombinierte Konfiguration als Ganzes aus. Es gibt drei primäre Subkeys, die du benutzt, um diese externen Files reinzuziehen. Der einfachste ist local. Du benutzt include local, um ein File reinzuziehen, das in genau demselben Repository liegt wie dein Main-Pipeline-File. Das ist strikt dafür gedacht, ein einzelnes großes Projekt zu organisieren. Du kannst deine ganze Testing-Logik in ein File namens test pipeline dot yml auslagern, deine Deployment-Logik in deploy pipeline dot yml packen und dein Root-Konfigurations-File sauber halten, indem du einfach auf diese lokalen Pfade referenzierst. Der zweite Subkey ist project, und hier skaliert die Pipeline-Modularität über eine ganze Organisation hinweg. Include project zieht ein YAML-File aus einem komplett anderen Repository, das auf derselben GitLab-Instanz gehostet wird. Du gibst den Pfad des externen Projekts an, zusammen mit dem File-Pfad und optional der spezifischen Branch- oder Commit-Referenz, die du pullen willst. Stell dir ein Plattform-Team vor, das eine zentrale Security-Scanning-Pipeline pflegt. Anstatt dass fünfzig verschiedene Microservice-Teams ihre eigenen Security-Jobs schreiben und pflegen, pflegt das Plattform-Team ein einziges, maßgebliches YAML-Template in einem dedizierten Plattform-Projekt. Die fünfzig Microservice-Projekte fügen einfach einen include project Block hinzu, der auf dieses zentrale Repository zeigt. Wenn das Plattform-Team die Scanner-Version updatet oder die Security-Rules in ihrem Template anpasst, führen alle fünfzig Microservices bei ihrer nächsten Pipeline-Execution automatisch die geupdateten Checks aus. Kein repetitives Copy-and-Paste ist nötig. Der dritte Subkey ist remote. Include remote nimmt eine vollständige HTTPS-URL und holt ein Konfigurations-File von einem beliebigen öffentlichen Webserver. Du könntest das nutzen, um vom Vendor bereitgestellte Pipeline-Definitions oder Open-Source-Community-Standards reinzuziehen. Die einzige strikte Voraussetzung ist, dass die URL über einen Standard-Web-Request ohne Authentifizierung öffentlich zugänglich sein muss. Pass jetzt bei diesem Teil gut auf. Du wirst oft auf eine Situation stoßen, in der ein included File einen Job definiert, aber das lokale Projekt ihn leicht modifizieren muss. GitLab handhabt das durch sein Merge-Verhalten. Wenn Files included werden, führt GitLab einen Deep Merge der Konfigurationen durch. Wenn ein included File einen Job namens run security scan definiert, und dein Main-File ebenfalls einen Job namens run security scan definiert, hat die Konfiguration in deinem Main-File Vorrang. Das bedeutet, dass du ein zentralisiertes Template nicht verwerfen musst, nur weil dein spezifisches Projekt einen kleinen Tweak braucht. Du kannst das Plattform-Team-Template includen und dann lokal einfach nur den run security scan Job mit einer geupdateten Variable oder einer Custom-Script-Ergänzung definieren. Deine lokalen Overrides greifen, während der Rest der Job-Definition exakt so bleibt, wie das Plattform-Team sie geschrieben hat. Die wahre Power der Pipeline-Modularität ist nicht nur das Zentralisieren von Code, sondern das Designen von Templates als sinnvolle Defaults, die Downstream-Projekte lokal überschreiben können, ohne die Vererbungskette kaputt zu machen. Das war's für diese Folge. Danke fürs Zuhören und keep building!
13

CI/CD Components und der Catalog

3m 57s

Erkunden Sie die moderne Evolution der Pipeline-Wiederverwendbarkeit: CI/CD Components. Erfahren Sie, wie Sie Component-Projekte erstellen, Semantic Versioning nutzen und den GitLab CI/CD Catalog einsetzen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. GitLab CI/CD, Folge 13 von 14. Deine Pipeline ist gerade fehlgeschlagen, weil jemand ein geteiltes YAML-Snippet drei Repositories weiter aktualisiert hat. Du hattest keine Vorwarnung und verbringst jetzt eine Stunde damit, einen Job zu fixen, den du gar nicht geschrieben hast. Die Zeiten, in denen du dich auf fehleranfällige, unversionierte YAML-Snippets verlassen musstest, sind vorbei. CI/CD Components und der CI/CD Catalog fixen das, indem sie die Zuverlässigkeit von Package Managern direkt in deine Pipelines bringen. Components sind wiederverwendbare Single-Purpose-Pipeline-Konfigurationen. Sie sind die moderne Weiterentwicklung der alten Include-Template-Methode. Mit Legacy-Templates hast du im Prinzip rohes YAML über das Netzwerk importiert. Wenn sich das Upstream-File änderte, änderte sich deine Pipeline sofort – oft mit katastrophalen Folgen. Components lösen dieses Problem durch striktes Versioning. Der CI/CD Catalog dient als zentrale Registry, in der deine Organisation diese versionierten Components veröffentlichen, finden und teilen kann. Um eine Component zu bauen, brauchst du ein Repository mit einer ganz bestimmten Dateistruktur. Die Core-Logik muss in einem Directory liegen, das explizit templates heißt. Du kannst mehrere YAML-Files in dieses Directory packen, wobei jedes File eine eigene Component repräsentiert. Im Root des Repositories musst du außerdem ein readme dot md File bereitstellen. Dieses Markdown-File ist nicht nur eine nette Empfehlung. Es dient als die offizielle Dokumentation, die im Catalog angezeigt wird, und beschreibt detailliert, was die Component macht und welche Parameter sie benötigt. Hier ist der entscheidende Punkt: Components sind ohne Inputs zu starr, um nützlich zu sein. Inputs verhalten sich genau wie Function Arguments für deine Pipeline-Konfiguration. Wenn du das Component-YAML schreibst, deklarierst du ganz oben einen Block, der die akzeptierten Inputs definiert. Du gibst ihre Namen an, ihre Default-Werte und ob sie required sind. Stell dir ein Platform-Engineering-Team vor, das verpflichtende Security Scans ausrollt. Sie erstellen ein Component-Project namens corporate-security. Im templates-Directory schreiben sie ein File speziell für Secret Detection. Um es flexibel zu halten, definieren sie einen einzigen required Input namens stage. Application Developer im gesamten Unternehmen müssen Secret-Detection-Jobs nun nicht mehr selbst schreiben oder maintainen. Um genau diese Secret-Detection-Component zu konsumieren, nutzt ein Developer die include component Syntax in seiner Pipeline-Konfiguration. Er gibt den Pfad zur Component auf dem Server an. Dann hängt er ein At-Zeichen an, gefolgt von einer Semantic Version, wie eins punkt null punkt null. Das ist der entscheidende Schritt. Das Pinnen der Semantic Version garantiert, dass die Pipeline niemals unerwartet bricht, selbst wenn das Platform-Team später in der Woche eine stark modifizierte Version zwei punkt null punkt null released. Wenn ein Developer absichtlich die Bleeding Edge will, kann er anstelle einer Versionsnummer das spezielle Tag tilde latest anhängen, aber Semantic Versioning ist der sicherere Default. Direkt unter der include-Deklaration übergibt der Developer seine Variablen und mappt den stage-Input auf die Pipeline-Stage, die zu seinem spezifischen Projekt passt, wie test oder pre-build. Pipeline-Logik als versionierte Software zu behandeln, verändert die Art und Weise, wie Teams Infrastruktur skalieren. Die wahre Power von Components ist nicht nur Code Reuse, es ist die absolute Garantie, dass eine Pipeline, die heute erfolgreich durchläuft, in sechs Monaten noch exakt genauso laufen wird. Danke fürs Zuhören. Macht's gut, Leute.
14

Compile-Time CI Expressions

4m 43s

Schalten Sie die ultimative Pipeline-Dynamik mit CI/CD Configuration Expressions frei. Erfahren Sie, wie die Compile-Time-Syntax Inputs und Matrices evaluiert, noch bevor Jobs ausgeführt werden.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. GitLab CI/CD, Folge 14 von 14. Du versuchst, den Stage-Namen eines Jobs mit einer Standard-CI-Variable zu definieren, pushst deinen Code und bekommst sofort einen Syntax Error. Die Pipeline weigert sich zu starten. Das Problem ist das Timing. Der Runner kann die Pipeline-Struktur nicht mit Variablen definieren, die er erst bekommt, nachdem die Pipeline schon gestartet ist. Genau hier kommen Compile-Time CI Expressions ins Spiel. Hier ist der entscheidende Punkt. Standard-Runtime-Variablen, die mit einem einzelnen Dollarzeichen geschrieben werden, werden von der Shell erst ausgewertet, wenn der Job tatsächlich ausgeführt wird. Wenn der Runner sie sieht, ist die gesamte Pipeline-Architektur bereits festgeschrieben. Du kannst einen Stage-Namen, einen Service oder eine Image-Version während der Runtime nicht dynamisch ändern, weil GitLab diese Infos im Voraus braucht, um den Pipeline-Graph zu bauen. Compile-Time Expressions lösen das, indem sie die Logik genau in dem Moment auswerten, in dem GitLab deine YAML-Config parst – lange bevor überhaupt ein Runner zugewiesen wird. Die Syntax nutzt ein Dollarzeichen, gefolgt von doppelten eckigen Klammern. Innerhalb dieser Klammern schreibst du eine Expression, die zu einem Wert evaluiert wird, bevor die Pipeline erstellt wird. Diese Expressions ziehen ihre Daten aus spezifischen Contexts. Ein Context ist im Grunde ein eingeschränkter Datensatz, der während des YAML-Parsings verfügbar ist. Der wichtigste Context ist der Inputs-Context, der beim Bauen von CI/CD-Components extrem oft genutzt wird. Nehmen wir das Szenario einer dynamischen Deployment-Component. Du möchtest, dass das Projekt, das diese Component nutzt, einen Environment-Namen als Input übergibt. Diesen Input willst du dann nutzen, um den Stage-Namen des Jobs zu setzen und vorzugeben, welche spezifische Docker-Image-Version gepullt wird. In deiner Component-Config schreibst du das Stage-Feld und weist ihm eine Compile-Time Expression zu, die inputs dot environment enthält. Wenn ein Projekt deine Component einbindet, liest GitLab den übergebenen Environment-Input. Es evaluiert die Expression sofort. Der resultierende Pipeline-Graph sieht einen statischen, hardcodierten Stage-Namen und ein hardcodiertes Image-Tag. Der Runner bekommt die doppelten Klammern nie zu Gesicht. Er erhält einfach eine Standard-Config. Neben Inputs unterstützen Compile-Time Expressions auch einen Matrix-Context, der aktuell in der Beta ist. Wenn du parallele Jobs mit einem Keyword wie parallel matrix generierst, kannst du Compile-Time Expressions nutzen, um Job-Properties dynamisch anzupassen, basierend auf den spezifischen Variablen, die jeder parallelen Instanz zugewiesen sind. Das erspart dir, Job-Definitions duplizieren zu müssen, nur um ein oder zwei Felder pro Matrix-Run zu ändern. Diese Expressions sind mächtiger als einfaches Text-Replacement. Du kannst Logik direkt in den Klammern schreiben, indem du Equality-Operatoren sowie logische AND- und OR-Operatoren nutzt. Du kannst prüfen, ob ein Input mit einem bestimmten String matcht, und einen Wert basierend auf dem Ergebnis bedingt ändern. Außerdem hast du Zugriff auf Built-in Functions. Die expand vars Function erlaubt es dir zum Beispiel, Compile-Time-Werte sicher in einen String zu injecten und dabei die Standard-Runtime-Variablen-Syntax explizit beizubehalten. Das garantiert, dass der Runner weiterhin die Runtime-Variablen bekommt, die er erwartet, ohne schon früh Parsing-Konflikte zu verursachen. Das wichtigste Takeaway ist, dass Compile-Time Expressions dir einen nativen Mechanismus geben, um deinen Pipeline-Graph zu templaten, wodurch die strukturelle Generierungslogik sauber von der eigentlichen Script-Execution getrennt wird. Nimm dir etwas Zeit, die offizielle GitLab-Documentation durchzulesen, schau dir die unterstützten Functions an und versuche hands-on, eine Component zu deployen. Wenn du Themen hast, die wir in einer zukünftigen Serie behandeln sollen, besuche devstories dot eu und lass es uns wissen. Danke, dass du ein paar Minuten mit mir verbracht hast. Bis zum nächsten Mal, mach's gut.