CI/CD
.yml
GitLab · CI/CD · Magento · Pipeline-Design
Pipeline-Stages sinnvoll designen
Build, Test, Package, Deploy, Verify, Rollback

Eine GitLab-Pipeline, die nur aus einem einzigen langen Script-Block besteht, ist kein CI/CD-Prozess – sie ist ein automatisiertes Chaos. Erst wenn Build, Test, Package, Deploy, Verify und Rollback als eigenständige Stages modelliert werden, entsteht eine Pipeline, die nachvollziehbar, rollbackfähig und teamtauglich ist.

12 Min. Lesezeit stages · needs · artifacts · when · rules GitLab 16+ · Magento 2.4 · PHP 8.4

1. Warum Pipeline-Stages keine Kosmetik sind

Die stages-Direktive in einer .gitlab-ci.yml ist der erste Ort, an dem ein Team die Logik seines Deployment-Prozesses sichtbar macht. Wer alle Schritte in einen einzigen Job packt, verliert die Fähigkeit, einzelne Phasen zu wiederholen, gezielt zu debuggen oder parallel laufen zu lassen. Stages sind keine organisatorische Spielerei, sondern das Rückgrat eines nachvollziehbaren Release-Prozesses.

Für Magento-Projekte ist diese Aufteilung besonders relevant. Der Build eines Magento-Shops umfasst Composer, DI-Compile, Node-Build und Static Content – alles Schritte, die nichts mit dem eigentlichen Deployment auf den Zielserver zu tun haben. Wenn diese Schritte von den Deployment-Schritten getrennt werden, kann dasselbe Artefakt auf Staging und Production ausgerollt werden, ohne neu zu bauen. Das ist der Kerngedanke reproduzierbarer Deployments.

Eine gut designte Stage-Kette macht außerdem deutlich, was passieren soll, wenn ein Schritt scheitert. Schlägt der Test-Job fehl, läuft kein Deploy. Schlägt der Verify-Job fehl, steht die Rollback-Stage bereit. Diese Logik ist in einer Pipeline mit expliziten Stages lesbar und erweiterbar – in einem monolithischen Script-Block hingegen ist sie versteckt und brüchig.

2. Build-Stage: der reproduzierbare Grundstein

Die Build-Stage hat eine einzige Aufgabe: aus dem Quellcode ein vollständiges, deploymentfähiges Artefakt zu erzeugen. In Magento-Projekten bedeutet das: composer install --no-dev, setup:di:compile, Node-Pakete installieren und den Tailwind-Build ausführen. Das Ergebnis wird als GitLab-Artefakt gespeichert und von allen nachfolgenden Jobs wiederverwendet – auf Staging und Production identisch.

Der entscheidende Punkt ist, dass die Build-Stage keine Verbindung zum Produktionsserver benötigt. Sie läuft vollständig im Runner, ohne SSH-Zugang, ohne Datenbankverbindung und ohne Kenntnis der Zielumgebung. Das macht sie testbar, wiederholbar und unabhängig. Wer in der Build-Stage bereits auf den Server zugreift, vermischt zwei Phasen, die konzeptionell getrennt sein müssen.

stages:
  - build
  - test
  - package
  - deploy
  - verify
  - rollback

variables:
  GIT_STRATEGY: fetch
  COMPOSER_CACHE_DIR: .cache/composer
  NPM_CONFIG_CACHE: .cache/npm

# Build stage: produce deployment artifact — no server access needed
build:magento:
  stage: build
  image: php:8.4-cli
  cache:
    key: composer-$CI_COMMIT_REF_SLUG
    paths:
      - .cache/composer/
      - .cache/npm/
  script:
    - composer install --no-dev --prefer-dist --no-interaction --optimize-autoloader
    - npm ci --prefix app/design/frontend/Mironsoft/default/web/tailwind
    - npm run build --prefix app/design/frontend/Mironsoft/default/web/tailwind
    - php bin/magento setup:di:compile
  artifacts:
    paths:
      - vendor/
      - generated/
      - pub/static/frontend/
    expire_in: 2 hours
    when: on_success

3. Test-Stage: Qualitätsgate vor dem Paket

Die Test-Stage ist das Qualitätsgate zwischen Build und Deployment. Hier laufen PHPStan, PHPUnit, PHPCS und Sicherheitschecks – mit den Artefakten aus der Build-Stage als Grundlage. Ein Job, der in der Test-Stage scheitert, verhindert automatisch, dass ein fehlerhaftes Artefakt jemals deployt wird. Das ist der Wert eines Qualitätsgates: nicht nur Fehler zu finden, sondern den Prozess zu blockieren, bis sie behoben sind.

In Magento-Projekten lohnt es sich, die Test-Stage in parallele Jobs aufzuteilen: einen für statische Analyse, einen für Unit-Tests, einen für Coding-Standards. Mit needs können diese Jobs gleichzeitig starten, sobald der Build-Job abgeschlossen ist. Das verkürzt die Pipeline-Laufzeit erheblich, ohne die Logik der Stages aufzubrechen. Nur wenn alle Test-Jobs erfolgreich sind, darf die Package-Stage beginnen.

4. Package-Stage: Artefakte schnüren und signieren

Die Package-Stage wandelt das gebaute Artefakt in ein transportierbares Paket um. Für Magento-Deployments mit SSH und rsync besteht das Paket typischerweise aus dem gesamten Release-Verzeichnis, das per rsync auf den Zielserver übertragen wird. Alternativ kann ein tar.gz-Archiv mit Checksumme erzeugt werden – das ermöglicht eine spätere Verifikation der Integrität vor dem Auspacken auf dem Server.

Die Package-Stage ist auch der richtige Ort für Release-Metadaten: die Build-ID, den Commit-Hash, den Branch-Namen und den Zeitstempel. Diese Informationen werden in eine release.json geschrieben, die mit dem Paket deployt wird. So ist auf dem Server jederzeit nachvollziehbar, welche Pipeline-Run welches Release erzeugt hat – ohne in GitLab nachschlagen zu müssen.

5. Deploy-Stage: atomarer Releasewechsel

Die Deploy-Stage überträgt das Artefakt auf den Zielserver und führt den Symlink-Wechsel durch. In einer sauberen Release-Struktur mit releases/, current und shared/ ist der eigentliche Downtime-kritische Moment auf ein einziges ln -sfn-Kommando reduziert. Alles davor – rsync, Symlinks für Shared-Dateien, Magento-Setup-Schritte – passiert im neuen Release-Verzeichnis, während das aktive current-Verzeichnis unberührt bleibt.

Für Production-Deployments sollte die Deploy-Stage immer mit when: manual oder einer expliziten Tag-Regel gesichert sein. Das verhindert, dass ein versehentliches Merge in main sofort ein Produktionsdeploy auslöst. Staging-Deployments können dagegen automatisch bei jedem Merge in den Develop-Branch starten – ein Muster, das schnelle Feedback-Zyklen ermöglicht, ohne Production zu gefährden.

# Deploy stage: transfer artifact and switch symlink atomically
deploy:production:
  stage: deploy
  environment:
    name: production
    url: https://shop.example.com
  rules:
    - if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
      when: manual
  before_script:
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | ssh-add -
    - mkdir -p ~/.ssh && echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
  script:
    - RELEASE_ID="$(date +%Y%m%d-%H%M%S)-${CI_COMMIT_SHORT_SHA}"
    - 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}/"
    - ssh "${DEPLOY_USER}@${DEPLOY_HOST}" "
        set -euo pipefail &&
        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 &&
        cd ${RELEASE_PATH} &&
        php bin/magento setup:upgrade --keep-generated &&
        php bin/magento cache:flush &&
        ln -sfn ${RELEASE_PATH} ${DEPLOY_PATH}/current"

6. Verify-Stage: fachlicher Abschluss der Pipeline

Die Verify-Stage ist der häufig vergessene Abschluss einer Pipeline. Technisch ist das Deployment nach dem Symlink-Wechsel abgeschlossen – fachlich nicht. Erst wenn der Health-Endpoint antwortet, die Startseite lädt, der Cache-Status korrekt ist und kritische API-Routen reagieren, ist ein Deployment wirklich erfolgreich. Diese Überprüfungen in einen eigenen Verify-Job auszulagern macht sie wiederholbar und protokollierbar.

Ein Verify-Job, der scheitert, sollte automatisch die Rollback-Stage aktivieren oder zumindest einen Alert auslösen. Das schließt die Lücke zwischen einem technisch deployen und einem tatsächlich funktionierenden Release. Für Magento-Shops können diese Checks über curl -f, bin/magento cache:status und einfache HTTP-Assertions implementiert werden – ohne externe Test-Frameworks.

7. Rollback-Stage: der geübte Rückweg

Eine Rollback-Stage, die erst im Störfall erfunden wird, ist kein Rollback – sie ist Improvisation. Der Rollback-Stage sollte in jeder produktiven Pipeline vorhanden sein, auch wenn sie selten ausgeführt wird. Der Mechanismus ist für Magento mit Release-Struktur einfach: der Symlink current wird auf das vorherige Release-Verzeichnis zurückgesetzt, der Cache geleert und der Verify-Job erneut ausgeführt. Das dauert Sekunden und erfordert keinen Build.

In GitLab kann die Rollback-Stage mit when: manual und einer variablen für das Ziel-Release implementiert werden. Das Team entscheidet im Störfall, welches Release reaktiviert wird – die Pipeline führt den Wechsel aus. Wichtig: der Rollback-Job muss dieselben SSH-Credentials und dieselbe Release-Struktur voraussetzen wie der Deploy-Job, damit er zuverlässig funktioniert.

# Verify stage: confirm deployment is functionally complete
verify:production:
  stage: verify
  needs: ["deploy:production"]
  script:
    - curl -f --retry 5 --retry-delay 3 https://shop.example.com/health
    - curl -f https://shop.example.com/
    - ssh "${DEPLOY_USER}@${DEPLOY_HOST}"
        "cd ${DEPLOY_PATH}/current && php bin/magento cache:status | grep -v 'disabled'"
  when: on_success

# Rollback stage: reactivate previous release via symlink — no rebuild needed
rollback:production:
  stage: rollback
  rules:
    - if: '$CI_PIPELINE_SOURCE == "web"'
      when: manual
  script:
    - ssh "${DEPLOY_USER}@${DEPLOY_HOST}" "
        set -euo pipefail &&
        PREV=\$(ls -1t ${DEPLOY_PATH}/releases/ | sed -n '2p') &&
        ln -sfn ${DEPLOY_PATH}/releases/\${PREV} ${DEPLOY_PATH}/current &&
        cd ${DEPLOY_PATH}/current &&
        php bin/magento cache:flush"

8. Stage-Abhängigkeiten mit needs steuern

Das needs-Keyword in GitLab CI erlaubt es, die strenge sequenzielle Reihenfolge von Stages zu durchbrechen und einen DAG (Directed Acyclic Graph) zu definieren. Ein Test-Job kann direkt nach dem Build-Job starten, ohne auf andere Jobs in derselben Stage zu warten. Das verkürzt die Pipeline-Laufzeit erheblich, weil parallele Arbeit möglich wird, ohne die logische Reihenfolge aufzugeben.

Für Magento-Pipelines ist ein typischer Anwendungsfall: PHPStan, PHPUnit und PHPCS starten alle gleichzeitig, sobald der Build-Artefakt verfügbar ist. Die Package-Stage startet erst, wenn alle drei Test-Jobs erfolgreich abgeschlossen sind. Mit needs und dependencies lässt sich dieser Graph explizit modellieren, ohne auf Stage-Barrieren zu verzichten. Das Ergebnis sind schnellere Pipelines ohne Verlust an Kontrollstruktur.

9. Stages im direkten Vergleich

Die Wahl des Stage-Designs hat direkte Auswirkungen auf Geschwindigkeit, Nachvollziehbarkeit und Sicherheit des Deployment-Prozesses. Die folgende Tabelle vergleicht verbreitete Antipatterns mit den empfohlenen Stage-Mustern.

Stage-Entscheidung Antipattern Empfohlenes Muster Vorteil
Build & Deploy trennen composer install auf dem Server Build im Runner, Artefakt deployen Reproduzierbar, kein Netz auf Production nötig
Test-Blockade Tests nach Deploy Test-Stage vor Deploy Fehler blockieren den Deployment-Pfad
Production-Schutz Auto-Deploy bei jedem Push when: manual + Tag-Regel Kein versehentliches Production-Deploy
Verify-Schritt Pipeline endet nach Deploy Verify-Stage mit curl + cache:status Fachlicher Abschluss statt technischer
Rollback Improvisiert im Störfall Rollback-Stage mit when: manual Geübter, dokumentierter Rückweg

Die Antipatterns in der Tabelle sind keine theoretischen Konstrukte – sie begegnen einem in realen Magento-Projekten regelmäßig. Der gemeinsame Nenner: sie entstehen, wenn eine Pipeline schnell zusammengebaut wird und nie strukturell überarbeitet wird. Das empfohlene Stage-Design kostet einmal mehr Planungsaufwand, zahlt sich aber bei jedem Deployment und erst recht bei jedem Vorfall aus.

10. Zusammenfassung

Eine Pipeline mit sinnvoll designten Stages ist kein Luxus für große Teams, sondern die Mindestanforderung an einen professionellen Deployment-Prozess für Magento. Build, Test, Package, Deploy, Verify und Rollback sind keine willkürliche Benennung – sie beschreiben die logische Reihenfolge eines Deployments, bei dem jede Phase eine klare Verantwortung hat und scheitern kann, ohne die nachfolgenden Phasen zu beschädigen.

Der größte Einzelgewinn ist die Trennung von Build und Deploy: ein Artefakt wird einmal gebaut und auf mehrere Umgebungen ausgerollt. Der zweitgrößte Gewinn ist die Verify-Stage: die Pipeline endet nicht nach dem Symlink-Wechsel, sondern erst nach einer bestätigten Funktionsfähigkeit. Und die Rollback-Stage stellt sicher, dass der Rückweg kein Notfall-Improvisation ist, sondern ein bewusst entworfener Teil des Prozesses.

Pipeline-Stages sinnvoll designen — Das Wichtigste auf einen Blick

Build vs. Deploy

Build im Runner ohne Server-Zugriff. Artefakt einmal erzeugen, auf Staging und Production identisch deployen.

Test-Gate

Test-Stage vor Deploy. PHPStan, PHPUnit und PHPCS laufen parallel mit needs – schlägt ein Job fehl, kein Deploy.

Verify-Abschluss

Verify-Stage nach Deploy mit curl und cache:status. Pipeline gilt erst als erfolgreich, wenn die Anwendung tatsächlich antwortet.

Rollback-Bereitschaft

Rollback-Stage mit when: manual. Symlink auf das vorherige Release – kein Rebuild, kein Stresstest im Störfall.

11. FAQ: Pipeline-Stages sinnvoll designen

1Wie viele Stages braucht eine Magento-Pipeline mindestens?
Mindestens vier: Build, Test, Deploy und Verify. Package und Rollback kommen hinzu, sobald mehrere Umgebungen existieren und ein dokumentierter Rückweg benötigt wird.
2Warum sollte Build und Deploy getrennt sein?
Ein einmal gebautes Artefakt kann identisch auf Staging und Production deployt werden. Builds auf dem Server sind langsamer, schwerer reproduzierbar und benötigen unnötigerweise Netz auf der Produktionsmaschine.
3Was gehört in die Verify-Stage?
HTTP-Check auf Health-Endpoint, Request auf Startseite, Cache-Status-Prüfung. Keine vollständigen E2E-Tests – die gehören vor den Deploy in die Test-Stage.
4Wie verhindere ich versehentliche Production-Deployments?
Mit rules und when: manual oder Tag-basierten Regeln. Production-Deploys nur auf semantische Tags begrenzen und zusätzlich durch Environment-Scopes absichern.
5Was ist der Unterschied zwischen stages und needs?
stages definiert sequenzielle Phase-Barrieren. needs definiert feinkörnige Job-Abhängigkeiten. Mit needs starten Jobs sobald ihre direkten Vorgänger fertig sind, unabhängig von der Stage-Grenze.
6Wie lange sollten Artefakte aufbewahrt werden?
Build-Artefakte innerhalb der Pipeline: 2–4 Stunden. Release-Pakete für Rollbacks: mindestens 7 Tage oder die letzten 5 Releases als Verzeichnisse auf dem Server.
7Kann die Rollback-Stage automatisch bei Verify-Fehler ausgelöst werden?
Technisch ja, mit when: on_failure. Aber ein automatischer Rollback ist nicht immer sicher – laufende DB-Migrationen können durch einen Rollback inkonsistente Zustände erzeugen. Manuell ist oft sicherer.
8Sollte Static Content in Build oder Deploy generiert werden?
Im Build, als Teil des Artefakts. Vorab für alle bekannten Locales bauen und als Artefakt mitführen – so entfällt der zeitintensive Static-Content-Deploy auf dem Produktionsserver.
9Wie teste ich Pipeline-Änderungen sicher?
Über einen Feature-Branch mit Staging-Umgebung. Production-Jobs durch Tag-Regeln oder Environment-Scopes sperren, bis die Pipeline vollständig validiert ist.
10Was ist der häufigste Fehler beim Stage-Design?
Das Fehlen einer Verify-Stage. Die Pipeline endet nach dem Deploy und gilt als erfolgreich – obwohl die Anwendung möglicherweise gar nicht antwortet.