CI/CD
.yml
GitLab · Magento Deployment · CI/CD · Zero Downtime
Von Null zu Zero-Downtime:
Vollständiger GitLab-Workflow für Magento

Repository-Governance, Build-Artefakte, Release-Verzeichnisse, Symlink-Switch, Verify-Jobs und Rollback als geschlossener, nachvollziehbarer Prozess – alle Bausteine im Zusammenhang erklärt.

15 Min. Lesezeit GitLab CI/CD · Magento · Release-Struktur · Symlink · Rollback Magento 2.4 · PHP 8.4 · GitLab 17+

1. Warum ein Gesamtbild so viel hilft

Magento-Deployments scheitern selten an einem einzelnen fehlenden Schritt. Sie scheitern daran, dass die Schritte zwar einzeln bekannt sind, aber nie als zusammenhängendes System gedacht wurden. Ein Team kennt den Build-Job, ein anderes kennt die Release-Ordner, und niemand hat das Rollback-Skript je wirklich geprobt. Der vollständige GitLab-Workflow für Magento muss deshalb als Gesamtbild präsentiert werden, nicht als Sammlung isolierter Konfigurationsschnipsel.

Das Gesamtbild beginnt mit der Repository-Governance: Welche Branches sind geschützt? Wer darf auf Production deployen? Wie werden Tags für Releases vergeben? Erst wenn diese Fragen beantwortet sind, kann eine Pipeline darauf aufbauen. Die Pipeline selbst ist dann kein Selbstzweck, sondern der Mechanismus, der eine definierte Freigabe in einen reproduzierbaren Deployment-Vorgang übersetzt. Jeder Schritt – Build, Package, Deploy, Verify, Rollback – hat eine klar abgegrenzte Verantwortung. Dieses Kapitel zeigt, wie diese Verantwortungen zusammenspielen.

Die Stärke des GitLab-Workflows für Magento liegt nicht in komplexen Einzelkonfigurationen, sondern in der Konsistenz des Gesamtprozesses. Ein Deployment, das auf Staging geprobt wurde, soll auf Production mit denselben Variablen, denselben Skripten und derselben Release-Struktur laufen. Das ist Zero Downtime nicht als technisches Feature, sondern als organisatorische Disziplin.

2. Repository-Grundlage: Branches, Tags und Schutzregeln

Der erste Baustein des vollständigen Workflows ist das Repository selbst. Ohne Protected Branches läuft jede Pipeline auf einer unsicheren Grundlage. Der main-Branch muss geschützt sein: kein direktes Pushen, alle Änderungen über Merge Requests, Approvals durch mindestens ein weiteres Teammitglied. Der Branch release/* wird für Release-Kandidaten genutzt, deren Pipeline vollständig grün sein muss, bevor der Deploy freigegeben wird.

Tags folgen dem Schema v* und sind ebenfalls geschützt. Ein Production-Deploy wird ausschließlich über einen signierten, freigegebenen Tag ausgelöst, niemals über einen Branch-Push. Das verhindert, dass unbeabsichtigte Commits direkt in die Produktion gelangen. Der Zusammenhang zwischen Branch, Tag, Pipeline und Deployment-Ziel muss in der Dokumentation des Projekts explizit beschrieben sein, damit neue Teammitglieder ihn nachvollziehen können.

3. CI/CD-Variablen als Konfigurationsvertrag

Variablen sind der Konfigurationsvertrag der Pipeline. Sie trennen, was der Code tut, von dem, wohin er deployt wird. Die wichtigsten Variablen für einen Magento-GitLab-Workflow sind SSH_PRIVATE_KEY, SSH_KNOWN_HOSTS, DEPLOY_HOST, DEPLOY_USER, DEPLOY_PATH und COMPOSER_AUTH. Jede dieser Variablen muss mit dem richtigen Environment Scope versehen sein, damit Staging-Secrets niemals in Production-Jobs landen und umgekehrt.

Zusätzlich zu den Deployment-Secrets gibt es Prozessvariablen wie RELEASE_RETENTION, die steuert, wie viele alte Release-Verzeichnisse auf dem Server erhalten bleiben. Ein Wert von 5 ist für die meisten Projekte ausreichend und erlaubt schnellen Rollback zu den letzten fünf Releases. Variablen wie GIT_STRATEGY: fetch und COMPOSER_CACHE_DIR auf Pipeline-Ebene steuern das Verhalten von GitLab Runner und Composer-Caching global und müssen nicht in jedem Job einzeln gesetzt werden.

# .gitlab-ci.yml — Global pipeline configuration for Magento deployment
stages:
  - build
  - test
  - package
  - deploy
  - verify
  - rollback

variables:
  GIT_STRATEGY: fetch
  COMPOSER_CACHE_DIR: "$CI_PROJECT_DIR/.cache/composer"
  NPM_CONFIG_CACHE: "$CI_PROJECT_DIR/.cache/npm"
  RELEASE_RETENTION: "5"

# Cache Composer and npm dependencies across pipeline runs
cache:
  key: "$CI_COMMIT_REF_SLUG"
  paths:
    - .cache/composer/
    - .cache/npm/

4. Pipeline-Stages: Reihenfolge mit Bedeutung

Die Stages einer Magento-Pipeline sind keine Kosmetik, sondern die fachliche Reihenfolge des Deployment-Prozesses. Build erzeugt das Artefakt: Composer-Abhängigkeiten, Frontend-Assets, DI-Compile. Test prüft das Artefakt auf Korrektheit: PHPStan, PHPCS, Unit Tests. Package bündelt das geprüfte Artefakt und bereitet es für die Übertragung vor. Deploy überträgt das Artefakt auf den Server und wechselt den Symlink. Verify prüft, ob der neue Release korrekt läuft. Rollback existiert als manueller Job für den Notfall.

Jede Stage darf erst beginnen, wenn die vorherige erfolgreich abgeschlossen ist. Das ist die Grundregel der Pipeline-Kaskade. Ein Deploy, der ohne vorherigen grünen Test-Lauf stattfindet, ist kein kontrollierter Deploy mehr. Die Stages erzwingen diese Reihenfolge mechanisch und nehmen dem Team die manuelle Disziplin ab. Das ist der Unterschied zwischen einer Pipeline als Werkzeug und einer Pipeline als Prozessgarant.

5. Build-Stage: Artefakte statt Serverzustand

Der Build-Job ist der kritischste Schritt im gesamten Workflow. Er muss alle Abhängigkeiten auflösen, den Frontend-Build ausführen und den DI-Compile-Schritt von Magento durchführen – alles in einer isolierten Umgebung, ohne Zugriff auf den Produktionsserver. Das Ergebnis ist ein Artefakt, das den vollständigen, reproduzierbaren Zustand des Releases enthält.

Artefakte werden in GitLab mit der artifacts-Direktive deklariert. Die Pfade vendor/, generated/ und pub/static/ sind die Mindestanforderungen für ein Magento-Artefakt. Die Ablaufzeit des Artefakts sollte auf mindestens einen Tag gesetzt sein, damit der Deploy-Job, der in einer späteren Stage läuft, noch Zugriff auf das Artefakt hat. Ein Build-Job, der auf dem Produktionsserver ausgeführt wird, ist kein Build-Job mehr – er ist ein Wartungsschritt mit unkontrollierten Seiteneffekten.

# Build job: produces the Magento release artifact
build:magento:
  stage: build
  image: php:8.4-cli
  before_script:
    - apt-get update -qq && apt-get install -y -qq git unzip curl nodejs npm
    - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
  script:
    # Install PHP dependencies without dev packages
    - composer install --no-dev --prefer-dist --no-interaction --optimize-autoloader
    # Install and build frontend assets
    - npm ci --prefix app/design/frontend/Mironsoft/default/web/tailwind
    - npm run build --prefix app/design/frontend/Mironsoft/default/web/tailwind
    # Compile Magento dependency injection
    - php bin/magento setup:di:compile
    # Deploy static content for German locale
    - php bin/magento setup:static-content:deploy de_DE -f --jobs=4
  artifacts:
    name: "magento-release-$CI_COMMIT_SHORT_SHA"
    paths:
      - vendor/
      - generated/
      - pub/static/
      - app/etc/config.php
    expire_in: 2 days
  only:
    - tags
    - main

6. Release-Struktur auf dem Zielserver

Die Release-Struktur auf dem Zielserver ist das Fundament von Zero Downtime. Sie besteht aus drei Verzeichnissen: releases/ enthält alle versionierten Releases als vollständige Verzeichnisse. shared/ enthält Dateien, die zwischen Releases geteilt werden: app/etc/env.php, pub/media/, var/log/, var/session/. current ist ein Symlink, der auf das aktive Release zeigt.

Der atomare Symlink-Wechsel ist der Kern des Zero-Downtime-Ansatzes. Mit ln -sfn /releases/NEUES_RELEASE /current wechselt der aktive Code in einem einzigen, atomaren Systemaufruf. Laufende PHP-FPM-Prozesse halten ihre Dateihandles auf die alten Dateien, neue Anfragen greifen sofort auf das neue Release zu. Dieses Prinzip funktioniert nur, wenn die Release-Struktur vorab sauber eingerichtet wurde und die Shared-Pfade korrekt verlinkt sind. Ein Server ohne diese Struktur kann keinen sicheren Symlink-Wechsel durchführen.

7. Deploy: Artefakt übertragen, Symlink wechseln

Der Deploy-Job überträgt das gebaute Artefakt auf den Zielserver und führt die Magento-spezifischen Release-Schritte aus. Die Übertragung erfolgt mit rsync, das nur geänderte Dateien überträgt und so den Netzwerkverkehr minimiert. Nach der Übertragung werden die Shared-Pfade verlinkt, die Magento-Konfiguration wird aus dem shared/-Verzeichnis eingespielt, und der Symlink wird auf das neue Release umgebogen.

Die Reihenfolge der Magento-Schritte im Deploy ist nicht beliebig. setup:upgrade muss vor cache:flush laufen, da das Upgrade den Cache invalidiert. Der Maintenance-Mode sollte so kurz wie möglich gehalten werden – idealerweise nur für den Zeitraum des setup:upgrade-Aufrufs. Für Deployments ohne Datenbankmigrationen kann der Maintenance-Mode vollständig weggelassen werden, was den Zero-Downtime-Ansatz maximiert. Der Symlink-Wechsel selbst ist der einzige Schritt, der ohne jede Downtime ausgeführt wird.

# Deploy job: transfers artifact and switches symlink on production server
deploy:production:
  stage: deploy
  environment:
    name: production
    url: https://shop.mironsoft.de
  script:
    # Setup SSH authentication
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh && chmod 700 ~/.ssh
    - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts && chmod 644 ~/.ssh/known_hosts
    # Create release directory and transfer artifact
    - RELEASE_ID=$(date +%Y%m%d-%H%M%S)
    - RELEASE_PATH="$DEPLOY_PATH/releases/$RELEASE_ID"
    - ssh "$DEPLOY_USER@$DEPLOY_HOST" "mkdir -p $RELEASE_PATH"
    - rsync -az --delete --exclude='.git' ./ "$DEPLOY_USER@$DEPLOY_HOST:$RELEASE_PATH/"
    # Link shared files and switch symlink
    - |
      ssh "$DEPLOY_USER@$DEPLOY_HOST" bash -s << 'SSH'
      set -euo pipefail
      RELEASE_PATH="$DEPLOY_PATH/releases/$RELEASE_ID"
      # Link environment-specific files from shared directory
      ln -sfn "$DEPLOY_PATH/shared/app/etc/env.php" "$RELEASE_PATH/app/etc/env.php"
      ln -sfn "$DEPLOY_PATH/shared/pub/media" "$RELEASE_PATH/pub/media"
      ln -sfn "$DEPLOY_PATH/shared/var" "$RELEASE_PATH/var"
      # Switch symlink atomically
      ln -sfn "$RELEASE_PATH" "$DEPLOY_PATH/current"
      # Post-deploy Magento steps
      cd "$DEPLOY_PATH/current"
      bin/magento cache:flush
      # Cleanup old releases, keep last 5
      ls -dt "$DEPLOY_PATH/releases"/*/ | tail -n +6 | xargs rm -rf
      SSH
  when: manual
  only:
    - tags

8. Verify: Health-Checks nach dem Umschalten

Ein Deployment ohne Verifikation ist keine fertige Pipeline. Der Verify-Job prüft nach dem Symlink-Wechsel, ob der neue Release korrekt antwortet. Ein HTTP-Health-Check gegen den /health-Endpoint bestätigt, dass der Webserver antwortet. Ein Smoke-Test gegen die Startseite prüft, ob Magento ohne 500er antwortet. Ein Cache-Status-Check via SSH stellt sicher, dass der Cache nach dem Flush korrekt neu aufgebaut wurde.

Schlägt der Verify-Job fehl, aktiviert die Pipeline automatisch den Rollback-Pfad. Der Rollback ist kein außerplanmäßiger Schritt, sondern Teil des normalen Pipeline-Designs. Er muss genauso sorgfältig gepflegt werden wie der Deploy-Job selbst: getestete Skripte, definierte Reihenfolge, klare Ausgabe. Ein Rollback, der unter Druck das erste Mal ausgeführt wird, ist kein echter Rollback. Die Pipeline erzwingt, dass er vorbereitet und getestet ist.

9. Improvisiert vs. reproduzierbar: direkter Vergleich

Der Unterschied zwischen einem improvisierten und einem reproduzierbaren Deployment-Prozess zeigt sich in jedem Störfall. Improvisierte Prozesse hängen von nicht dokumentierten Serverannahmen ab: Welche PHP-Version ist installiert? Welche Composer-Version? Welche Node-Version? Ein reproduzierbarer Prozess beantwortet diese Fragen durch den Build-Job selbst, der in einem kontrollierten Docker-Container mit explizit definierten Tool-Versionen läuft.

Die folgende Tabelle zeigt die wichtigsten Unterschiede zwischen beiden Ansätzen auf einen Blick. Sie macht deutlich, warum das Investieren in einen vollständigen Workflow – auch wenn er mehr initialen Aufwand erfordert – die Betriebsstabilität fundamental verbessert.

Aspekt Improvisiert Reproduzierbar (GitLab-Workflow) Vorteil
Build-Ort Direkt auf Production CI-Container, isoliert Keine Seiteneffekte auf Live-System
Rollback Manuell, improvisiert Symlink auf altes Release Sekunden statt Stunden
Secrets Hartcodiert oder per Hand GitLab Vars mit Scope Umgebungsgetrennt, auditierbar
Verifikation Keine oder manuell Automatischer Verify-Job Fehler sofort erkannt
Downtime Unkontrolliert, variabel Nur bei DB-Migrationen Planbares Wartungsfenster

Ein improvisierter Prozess sieht in ruhigen Phasen oft genauso aus wie ein reproduzierbarer. Der Unterschied zeigt sich im Störfall: wenn der falsche Commit deployt wurde, wenn das Backup fehlt, wenn kein dokumentierter Rollback-Weg existiert. Ein vollständiger GitLab-Workflow für Magento bereitet das Team auf genau diese Situationen vor, bevor sie eintreten.

10. Zusammenfassung

Der vollständige GitLab-Workflow für Magento von Null zu Zero-Downtime ist kein einzelnes Feature, sondern das Ergebnis konsequent durchdachter Einzelentscheidungen: Protected Branches verhindern unkontrollierte Deploys. Build-Jobs in isolierten Containern erzeugen reproduzierbare Artefakte. Release-Verzeichnisse mit Symlink-Switch ermöglichen atomare Umschaltungen. Verify-Jobs prüfen den neuen Release sofort nach dem Umschalten. Rollback-Skripte sind vorbereitet und getestet, nicht improvisiert.

Zero Downtime ist das natürliche Ergebnis dieses Prozesses, nicht sein Ziel. Wer jeden Baustein richtig implementiert, erhält automatisch eine Deployment-Infrastruktur, die Störfälle minimiert, Rollbacks ermöglicht und Teams die Sicherheit gibt, auch unter Druck kontrolliert zu handeln.

GitLab-Workflow für Magento — Das Wichtigste auf einen Blick

Repository-Grundlage

Protected Branches, Protected Tags, Merge-Request-Pflicht – ohne diese Governance ist jede Pipeline nur halb abgesichert.

Build-Artefakt

Composer, DI-Compile, Frontend-Build im CI-Container – nie auf Production. Das Artefakt wird einmal gebaut, mehrfach deployt.

Symlink-Switch

Release-Verzeichnisse mit atomarem Symlink-Wechsel sind die Basis von Zero Downtime und schnellem Rollback.

Verify & Rollback

Kein Deployment ohne automatischen Health-Check danach. Rollback ist kein Sonderfall, sondern Teil des normalen Prozessdesigns.

11. FAQ: GitLab-Workflow für Magento

1Was ist der wichtigste Schritt?
Der atomare Symlink-Wechsel: ln -sfn /releases/NEU /current. Er ist der einzige Schritt ohne Downtime und bildet die Grundlage für schnellen Rollback.
2Muss ich immer Maintenance-Mode nutzen?
Nein. Ohne Datenbankmigrationen kann er entfallen. Maintenance ist nur bei setup:upgrade mit DB-Änderungen sinnvoll.
3Wie viele Releases aufbewahren?
Fünf ist ein guter Standard. Erlaubt Rollback zu den letzten fünf Releases ohne zu viel Speicher zu belegen. Als Variable RELEASE_RETENTION definieren.
4Was gehört in shared/?
app/etc/env.php, pub/media/, var/log/, var/session/. Diese Pfade existieren einmal auf dem Server und werden per Symlink in jeden Release eingebunden.
5Staging-Secrets von Production trennen?
Mit Environment Scopes in GitLab CI/CD Variables. Ohne Scope gilt die Variable global – ein Sicherheitsrisiko.
6Wann löst der Verify-Job Rollback aus?
Wenn der Health-Check nicht antwortet oder 5xx zurückgibt. Rollback-Job mit when: on_failure definieren, sofort ausführbar.
7Gleicher Workflow für Staging und Production?
Ja, ausdrücklich empfohlen. Derselbe Prozess, dieselben Skripte, verschiedene Variablen. Was auf Staging funktioniert, läuft auch auf Production.
8Wie lange dauert ein Deployment?
Build 3–10 Minuten, Deploy unter einer Minute (rsync + Symlink), Verify 30–60 Sekunden. Gesamtzeit typischerweise 5–15 Minuten.
9Häufigster Fehler bei GitLab-Deployments?
Kein Verify-Job und kein geübter Rollback. Die Pipeline deployt, aber niemand kann im Störfall zurückrollen. Rollback muss dokumentiert und getestet sein.
10Static Content im Build oder auf dem Server?
Im Build-Job. Die generierten Dateien aus pub/static/ werden als Artefakt übertragen. Production braucht keine Node- oder Build-Tools.