Was in den Release-Build gehört – und was nicht
Wer wahllos Verzeichnisse in GitLab-Artefakte packt, erhält aufgeblähte Pakete, nicht reproduzierbare Deployments und unnötige Serverrisiken. Die richtige Trennung von Build-Output, Shared-Daten und Server-State ist der Kern eines belastbaren Release-Prozesses für Magento.
Inhaltsverzeichnis
- 1. Was ein GitLab-Artefakt wirklich ist
- 2. Build-Output vs. Server-State: die zentrale Trennlinie
- 3. Magento-Verzeichnisse im Artefakt-Check
- 4. vendor/ und generated/ – bauen oder deployen?
- 5. pub/static und Frontend-Assets im Build
- 6. Shared-Daten: was nie ins Artefakt gehört
- 7. artifacts in .gitlab-ci.yml korrekt konfigurieren
- 8. Paketgröße kontrollieren: expire_in und exclude
- 9. Vergleich: aufgebläht vs. sauber getrennt
- 10. Zusammenfassung
- 11. FAQ
1. Was ein GitLab-Artefakt wirklich ist
Ein GitLab-Artefakt ist kein Backup und keine Servorkopie – es ist das definierte Output-Paket eines CI-Jobs, das an nachfolgende Jobs in der Pipeline oder ans Deployment weitergegeben wird. GitLab speichert Artefakte im CI-System und stellt sie bei Bedarf zum Download bereit. Das klingt technisch simpel, hat aber weitreichende Konsequenzen für den gesamten Deployment-Prozess: Was im Artefakt landet, muss reproduzierbar aus dem Quellcode entstehen. Was nicht reproduzierbar entsteht, gehört nicht in das Paket.
Der entscheidende Gedanke ist die Trennung zwischen Build-Output und Betriebszustand. Der Build-Output entsteht aus dem Repository durch definierte Kommandos – Composer, npm, di:compile, scd. Der Betriebszustand hingegen ist das Ergebnis des laufenden Betriebs: Logs, Sessions, Upload-Dateien, Konfiguration mit echten Credentials. Wer diese beiden Kategorien vermischt, bekommt Artefakte, die weder sicher noch konsistent sind. Für Magento-Projekte ist diese Trennung besonders wichtig, weil das Framework viele Schichten hat, die auf den ersten Blick wie Build-Output aussehen, aber tatsächlich serverspezifisch sind.
2. Build-Output vs. Server-State: die zentrale Trennlinie
Die Grundregel lautet: Alles, was aus dem Repository heraus deterministisch erzeugt werden kann, ist potenzieller Build-Output. Alles, was umgebungsspezifisch ist oder zur Laufzeit entsteht, ist Server-State und hat im Artefakt nichts verloren. Für Magento bedeutet das konkret: vendor/ ist das Ergebnis von composer install mit einer fixen composer.lock – deterministisch, also Build-Output. Die Datei app/etc/env.php hingegen enthält Datenbankpasswörter und ist pro Umgebung unterschiedlich – Server-State, niemals ins Artefakt.
Diese Trennung hat direkte Auswirkungen auf die Rollback-Fähigkeit. Ein Artefakt, das keine serverspezifischen Daten enthält, kann zu einem früheren Release zurückgerollt werden, ohne dass Credentials oder Nutzerdaten gefährdet sind. Ein Artefakt, das env.php enthält, trägt Produktionsdaten durch das CI-System – ein erhebliches Sicherheitsrisiko. Die saubere Trennlinie ist daher keine akademische Frage, sondern hat direkte Sicherheits- und Betriebsrelevanz für jeden Magento-Shop.
3. Magento-Verzeichnisse im Artefakt-Check
Magento hat eine komplexe Verzeichnisstruktur, und jedes Verzeichnis muss einzeln bewertet werden. vendor/ enthält alle Composer-Abhängigkeiten und ist klar Build-Output. generated/ enthält den kompilierten DI-Code und ist ebenfalls Build-Output, sofern setup:di:compile im Build-Job läuft. pub/static/ enthält die deployte Frontend-Assets nach setup:static-content:deploy und ist Build-Output. Diese drei Verzeichnisse sind die Kernbestandteile eines Magento-Release-Artefakts.
Auf der anderen Seite stehen Verzeichnisse, die auf dem Server verbleiben müssen: pub/media/ enthält hochgeladene Produktbilder und Kundenfotos. var/log/, var/session/ und var/cache/ sind Betriebsdaten. app/etc/env.php und app/etc/config.php tragen umgebungsspezifische Konfiguration. Diese Verzeichnisse werden über das Shared-Konzept im Release-Modell verknüpft – Symlinks aus dem Release-Verzeichnis auf gemeinsame Pfade außerhalb der Release-Struktur.
4. vendor/ und generated/ – bauen oder deployen?
Die Frage, ob vendor/ im Artefakt mitgeschickt oder auf dem Server neu installiert werden soll, wird in Magento-Teams oft diskutiert. Die klarere Antwort: Im CI-System bauen und als Artefakt deployen. Das vermeidet, dass auf dem Produktionsserver Composer laufen muss, was Netzwerkabhängigkeiten, auth.json-Geheimnisse und unterschiedliche Composer-Versionen im Spiel bringt. Ein einmal gebautes vendor/ aus der Pipeline ist reproduzierbar und sicher – der Produktionsserver benötigt kein Composer.
generated/ folgt derselben Logik. bin/magento setup:di:compile läuft im Build-Job, das Ergebnis wird ins Artefakt gepackt. Damit läuft kein Compile-Prozess auf dem Produktionsserver. Das ist besonders relevant, weil di:compile CPU-intensiv ist und auf einem Webserver unter Last erhebliche Auswirkungen hätte. Beide Verzeichnisse gemeinsam machen das Artefakt vollständig: Es enthält den gesamten PHP-Code, alle Abhängigkeiten und den kompilierten DI-Container.
build:magento:
stage: build
image: php:8.4-cli
before_script:
# Install system dependencies for Magento build
- apt-get update -qq && apt-get install -y -qq git unzip libzip-dev libicu-dev
- docker-php-ext-install zip intl bcmath sockets
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
script:
# Install PHP dependencies — no dev packages, locked versions
- composer install --no-dev --prefer-dist --no-interaction --optimize-autoloader
# Compile Dependency Injection container
- php bin/magento setup:di:compile
artifacts:
name: "magento-build-${CI_COMMIT_SHORT_SHA}"
paths:
- vendor/
- generated/
expire_in: 2 days
when: on_success
5. pub/static und Frontend-Assets im Build
Das Verzeichnis pub/static/ entsteht durch bin/magento setup:static-content:deploy und enthält alle statischen Frontend-Dateien: CSS, JavaScript, Bilder, Fonts, Hyvä-Tailwind-Output. Es ist eindeutig Build-Output und gehört ins Artefakt – allerdings mit einem wichtigen Vorbehalt: setup:static-content:deploy benötigt eine vollständige Magento-Installation inklusive Datenbankzugang, um Themenkonfigurationen zu lesen. Das macht diesen Schritt in einem isolierten CI-Container schwierig.
Der pragmatische Ansatz für Magento-Teams ohne Datenbankzugang im Build-Container: Tailwind und node_modules im Build-Job verarbeiten, setup:static-content:deploy aber als ersten Schritt im Deploy-Job auf dem Server ausführen, bevor der Symlink gewechselt wird. In diesem Fall gehört pub/static/ nicht ins CI-Artefakt, sondern wird serverseitig generiert. Diese Entscheidung muss im Team explizit getroffen und dokumentiert sein – der häufigste Fehler ist eine implizite Annahme, die auf Staging funktioniert, aber auf Production unter anderen Pfaden fehlschlägt.
6. Shared-Daten: was nie ins Artefakt gehört
Shared-Daten sind Dateien und Verzeichnisse, die über mehrere Releases hinweg unverändert bleiben und nicht mit jedem Deployment neu erzeugt werden. In Magento sind das primär: app/etc/env.php mit Datenbankverbindung und Cache-Konfiguration, pub/media/ mit allen hochgeladenen Mediadateien, var/log/ für Anwendungslogs und var/session/ für aktive Benutzersitzungen. Diese Daten dürfen niemals im Artefakt landen.
Die technische Umsetzung erfolgt über ein shared/-Verzeichnis außerhalb der Release-Struktur und Symlinks aus jedem Release-Verzeichnis auf diese gemeinsamen Pfade. Wenn ein neues Release deployed wird, verweisen die Symlinks sofort auf die korrekten Shared-Daten, ohne dass etwas kopiert werden muss. Der Artefakt-Build bleibt sauber: Er enthält ausschließlich versionierten Code und deterministisch erzeugten Output – keine Credentials, keine Nutzerdaten, keine umgebungsspezifischen Einstellungen.
7. artifacts in .gitlab-ci.yml korrekt konfigurieren
Die artifacts-Direktive in GitLab CI hat mehr Optionen als die meisten Teams verwenden. Das paths-Array definiert, welche Verzeichnisse und Dateien gespeichert werden. expire_in legt fest, wann das Artefakt automatisch gelöscht wird – wichtig für Speicherkosten und Datenschutz. Das Schlüsselwort when: on_success stellt sicher, dass Artefakte nur bei erfolgreichem Job gespeichert werden. Mit exclude können einzelne Unterverzeichnisse aus Pfaden ausgeschlossen werden, was bei vendor/ für Test-Dependencies nützlich ist.
Ein oft übersehener Punkt: Artefakte zwischen Jobs werden automatisch heruntergeladen, wenn dependencies gesetzt ist oder kein explizites dependencies: [] vorhanden ist. Das kann Pipelines verlangsamen, wenn große Artefakte unnötig in viele Jobs geladen werden. Für Magento empfiehlt sich, den Deploy-Job explizit nur auf die Build-Artefakte zu zeigen und alle anderen Jobs mit dependencies: [] zu konfigurieren, um unnötige Downloads zu vermeiden.
package:release:
stage: package
# Only download artifacts from the build job
dependencies:
- build:magento
- build:frontend
script:
# Create a timestamped release package
- export RELEASE_ID="$(date +%Y%m%d-%H%M%S)-${CI_COMMIT_SHORT_SHA}"
- mkdir -p "dist/${RELEASE_ID}"
# Copy build outputs into release directory
- rsync -a --exclude='.git' --exclude='var/' --exclude='pub/media/' ./ "dist/${RELEASE_ID}/"
- tar -czf "release-${RELEASE_ID}.tar.gz" -C dist "${RELEASE_ID}"
artifacts:
name: "release-${CI_COMMIT_SHORT_SHA}"
paths:
- release-*.tar.gz
expire_in: 7 days
when: on_success
# Quality-check job that does NOT need build artifacts
test:phpcs:
stage: test
dependencies: []
script:
- vendor/bin/phpcs --standard=Magento2 app/code/
8. Paketgröße kontrollieren: expire_in und exclude
Unkontrollierte Artefaktgrößen sind ein häufiges Problem in Magento-Pipelines. vendor/ kann 200–400 MB groß sein, und wenn dieses Artefakt in jeder Pipeline für 30 Tage aufbewahrt wird, summiert sich das schnell auf Gigabytes im GitLab-Speicher. Die Lösung ist eine kurze expire_in-Zeit für Build-Artefakte – ein bis zwei Tage sind für die meisten Workflows ausreichend, da Release-Pakete separat mit längerer Aufbewahrung gespeichert werden können.
Mit der exclude-Option lassen sich bekannte große Unterverzeichnisse aus den Artefakten heraushalten. Für vendor/ empfiehlt sich der Ausschluss von Testverzeichnissen innerhalb der Packages: vendor/*/*/Test/, vendor/*/*/tests/ und ähnliche Muster. Bei Tailwind und npm ist node_modules/ fast immer vollständig ausgeschlossen – das npm-Build-Output in Form von CSS-Dateien ist das einzige, was ins Artefakt gehört, nicht das gesamte node_modules-Verzeichnis mit hunderten von Megabytes.
9. Vergleich: aufgebläht vs. sauber getrennt
Der Unterschied zwischen einem schlecht und einem gut konfigurierten Artefakt zeigt sich direkt in der Pipeline-Performance und der Sicherheit des Deployments.
| Verzeichnis | Im Artefakt? | Begründung | Wohin stattdessen? |
|---|---|---|---|
vendor/ |
Ja | Deterministisch aus composer.lock | — |
generated/ |
Ja | DI-Compile-Output aus Build-Job | — |
pub/static/ |
Situationsabhängig | Benötigt DB-Zugang für SCD | Erster Schritt im Deploy-Job |
app/etc/env.php |
Niemals | Credentials, umgebungsspezifisch | shared/ auf dem Server |
pub/media/ |
Niemals | Nutzerdaten, nicht versioniert | shared/ auf dem Server |
node_modules/ |
Niemals | Hunderte MB, nur für Build nötig | GitLab Cache |
Die Tabelle zeigt die Entscheidungslogik: Deterministisch aus Quellcode erzeugbar und für den Produktivbetrieb nötig bedeutet Artefakt. Umgebungsspezifisch oder Nutzerdaten bedeutet Shared-Verzeichnis auf dem Server. Nur für den Build-Prozess nötig bedeutet GitLab Cache, nicht Artefakt. Diese drei Kategorien decken alle Magento-Verzeichnisse ab und geben klare Antworten für jeden Einzelfall.
10. Zusammenfassung
Die Entscheidung, was in ein GitLab-Release-Artefakt gehört und was nicht, ist eine der grundlegendsten Design-Entscheidungen im Deployment-Prozess. Für Magento lautet die Regel: vendor/ und generated/ werden im Build-Job erzeugt und als Artefakt weitergegeben. pub/static/ gehört idealerweise ebenfalls in den Build, wenn Datenbankzugang im CI verfügbar ist – andernfalls als ersten Deployment-Schritt auf dem Server. Alles Umgebungsspezifische und alle Nutzerdaten verbleiben im Shared-Bereich des Servers.
Die Konsequenz dieser sauberen Trennung ist ein Deployment-Prozess, der reproduzierbar, rollbackfähig und sicher ist. Reproduzierbar, weil das Artefakt immer aus denselben Eingaben entsteht. Rollbackfähig, weil ein früheres Release-Verzeichnis reaktiviert werden kann, ohne Credentials zu berühren. Sicher, weil Produktionsdaten nie durch das CI-System fließen. Wer diese Trennung einmal konsequent eingeführt hat, wird sie in jedem künftigen Magento-Projekt als selbstverständlich voraussetzen.
GitLab-Artefakte für Magento — Das Wichtigste auf einen Blick
Build-Output ins Artefakt
vendor/ und generated/ sind deterministischer Build-Output und gehören ins Artefakt. Kein Composer auf Production.
Server-State bleibt auf dem Server
env.php, pub/media/ und var/ sind Shared-Daten und werden niemals ins Artefakt gepackt.
Paketgröße kontrollieren
expire_in kurz halten, node_modules/ ausschließen, Test-Verzeichnisse in vendor/ mit exclude herausfiltern.
dependencies: [] in nicht-deploy Jobs
Jobs, die kein Artefakt brauchen, mit dependencies: [] konfigurieren – spart Pipeline-Zeit und vermeidet unnötige Downloads.