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.
Inhaltsverzeichnis
- 1. Warum Pipeline-Stages keine Kosmetik sind
- 2. Build-Stage: der reproduzierbare Grundstein
- 3. Test-Stage: Qualitätsgate vor dem Paket
- 4. Package-Stage: Artefakte schnüren und signieren
- 5. Deploy-Stage: atomarer Releasewechsel
- 6. Verify-Stage: fachlicher Abschluss der Pipeline
- 7. Rollback-Stage: der geübte Rückweg
- 8. Stage-Abhängigkeiten mit needs steuern
- 9. Stages im direkten Vergleich
- 10. Zusammenfassung
- 11. FAQ
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.