CI/CD
.yml
GitLab · CI Templates · Multi-Projekt · Magento
GitLab CI Templates für mehrere
Magento-Projekte wiederverwenden

Zehn Magento-Shops mit zehn identischen Pipeline-Dateien zu betreiben ist technische Schulden in Reinform. Jede Änderung am Deploy-Prozess muss zehnmal gemacht werden. GitLab-Templates mit include und extends lösen das Problem – ein zentraler Build-Standard, individuell erweiterbar pro Projekt.

13 Min. Lesezeit include · extends · YAML-Anchors · Template-Repository · Overrides GitLab · Magento 2.4 · Multi-Projekt

1. Das Problem mit kopierten Pipeline-Dateien

Agenturen und Teams, die mehrere Magento-Projekte betreiben, kennen das Problem: Die erste .gitlab-ci.yml wird sorgfältig entwickelt, getestet und als funktionierend befunden. Beim zweiten Projekt wird sie kopiert und leicht angepasst. Beim dritten Projekt wird die Kopie des zweiten Projekts kopiert. Nach einem Jahr existieren zehn Pipeline-Dateien, die sich in Details unterscheiden, weil Verbesserungen nur in einige Projekte eingepflegt wurden. Eine Sicherheitslücke im Deploy-Skript muss in zehn Repositories einzeln gefixt werden.

Das ist kein akademisches Problem, sondern ein alltäglicher Betriebszustand in Agenturen mit mehreren Kundenprojekten. Die Lösung ist dieselbe, die Softwareentwickler seit Jahrzehnten für Code-Duplikation einsetzen: Abstraktion und Wiederverwendung. GitLab bietet dafür das include-Schlüsselwort, das externe YAML-Dateien in die aktuelle Pipeline einbindet, und extends, das Job-Definitionen aus eingebundenen Templates ableitet und erweitert.

Das Ziel ist ein System, in dem der gemeinsame Build-, Test- und Deploy-Standard an einem Ort definiert ist – im Template-Repository – und jedes Projekt nur noch das einbindet und dort konfiguriert, was projektspezifisch ist. Eine Verbesserung am Deploy-Standard wird einmal gemacht und steht sofort allen Projekten zur Verfügung, die das Template in einer kompatiblen Version referenzieren.

2. GitLab include: Grundlagen und Varianten

Das include-Schlüsselwort in GitLab CI/CD erlaubt das Einbinden externer YAML-Dateien in die aktuelle Pipeline-Konfiguration. Es gibt vier Varianten: local (Datei im selben Repository), project (Datei in einem anderen GitLab-Projekt), remote (URL zu einer externen YAML-Datei) und template (vordefinierte GitLab-Templates). Für die Wiederverwendung über mehrere Magento-Projekte ist die project-Variante die geeignetste, weil sie ein zentrales Template-Repository in derselben GitLab-Instanz referenziert und von GitLabs Zugriffskontrolle profitiert.

Ein wichtiger Aspekt bei include: project ist die ref-Option, die festlegt, welcher Branch, Tag oder Commit-SHA aus dem Template-Repository verwendet wird. Wenn ref auf einen fixen Tag zeigt, ist die Template-Version eingefroren und Änderungen am Template-Repository wirken sich nicht sofort auf alle Projekte aus. Wenn ref auf main zeigt, verwenden alle Projekte immer die neueste Template-Version – praktisch für kleine Teams, aber riskant, weil Breaking Changes sofort alle Projekte treffen.

# .gitlab-ci.yml in a Magento project
# Includes templates from a central template repository

include:
  # Pin to a specific version tag for stability
  - project: "mironsoft/gitlab-ci-templates"
    ref: "v2.1.0"
    file:
      - "/magento/build.yml"
      - "/magento/test.yml"
      - "/magento/deploy.yml"

# Project-specific variables override template defaults
variables:
  MAGENTO_VERSION: "2.4.8"
  PHP_VERSION: "8.4"
  DEPLOY_HOST: "shop1.example.com"
  DEPLOY_PATH: "/var/www/shop1"
  THEME_PATH: "app/design/frontend/Mironsoft/default"

# Project-specific stage additions (template stages remain)
stages:
  - build
  - test
  - package
  - deploy
  - verify
  - rollback

3. extends: Jobs aus Templates ableiten und überschreiben

Das extends-Schlüsselwort erlaubt es, einen Job aus einem Template abzuleiten und einzelne Eigenschaften zu überschreiben oder zu ergänzen. GitLab führt dabei ein Deep-Merge durch: Dictionaries (wie variables und cache) werden zusammengeführt, Skalare und Listen werden überschrieben. Das ermöglicht fein granulierte Overrides, ohne die komplette Job-Definition kopieren zu müssen.

Ein typisches Muster ist, einen Template-Job zu definieren, der den Standard-Build-Prozess für Magento beschreibt, und in jedem Projekt nur die projektspezifischen Abweichungen zu überschreiben. Das Template definiert das PHP-Image, die Composer-Optionen, den Cache und die Artefakt-Konfiguration. Das Projekt überschreibt nur das spezifische Theme-Verzeichnis oder fügt projektspezifische Build-Schritte hinzu.

# templates/magento/build.yml (in template repository)
# Base build job for Magento projects — extended in each project

.build:magento:base:
  stage: build
  image: "php:${PHP_VERSION:-8.4}-cli"
  variables:
    COMPOSER_CACHE_DIR: "${CI_PROJECT_DIR}/.cache/composer"
    COMPOSER_HOME: "${CI_PROJECT_DIR}/.cache/composer"
    THEME_PATH: "app/design/frontend/Mironsoft/default"  # Default theme
  cache:
    key:
      files:
        - composer.lock
    paths:
      - .cache/composer/
    policy: pull-push
  script:
    - composer install --no-dev --prefer-dist --optimize-autoloader
    - npm ci --prefix "${THEME_PATH}/web/tailwind"
    - npm run build --prefix "${THEME_PATH}/web/tailwind"
    - bin/magento setup:di:compile
  artifacts:
    paths:
      - vendor/
      - generated/
      - "${THEME_PATH}/web/tailwind/css/"
    expire_in: 3 hours

---
# .gitlab-ci.yml in a specific project — extends the template

build:magento:
  extends: .build:magento:base
  variables:
    THEME_PATH: "app/design/frontend/Acme/custom"  # Project-specific override
  script:
    - !reference [.build:magento:base, script]  # Include base script
    - echo "Project-specific post-build step"

4. YAML-Anchors als Alternative innerhalb einer Datei

YAML-Anchors sind eine YAML-native Lösung für Wiederverwendung innerhalb einer einzigen Datei. Mit &anchor-name wird ein Block als Anker definiert, mit *anchor-name wird er referenziert und mit <<: *anchor-name werden die Werte in einen anderen Block eingemischt. GitLab CI/CD unterstützt YAML-Anchors vollständig, was sie für die Wiederverwendung innerhalb der projektlokalen .gitlab-ci.yml nützlich macht.

YAML-Anchors sind jedoch keine Lösung für projektübergreifende Wiederverwendung, weil sie nicht aus externen Dateien importiert werden können. Sie eignen sich für das Vermeiden von Duplikationen innerhalb einer Datei, nicht als Ersatz für das include-System. In der Praxis werden YAML-Anchors oft für Common-Variables-Blöcke und SSH-Setup-Schritte verwendet, die in mehreren Jobs derselben Pipeline benötigt werden.

5. Ein zentrales Template-Repository für Magento-Projekte

Das zentrale Template-Repository ist der Kern der Template-Wiederverwendung. Es enthält die gemeinsamen Bausteine für alle Magento-Projekte: Build-Jobs, Test-Jobs, Deploy-Jobs, Verify-Jobs und Rollback-Jobs. Die Struktur sollte nach Funktionsbereichen organisiert sein, damit Projekte nur die Teile einbinden, die sie benötigen. Ein Projekt, das kein Rollback-Job benötigt, bindet rollback.yml nicht ein.

Das Template-Repository benötigt eine eigene Pipeline, die die Templates validiert. GitLab bietet dafür den ci-lint-Endpoint der API, der eine Pipeline-Konfiguration syntaktisch und semantisch prüft. Für das Template-Repository bedeutet das: Ein Test-Job in der Template-Pipeline führt einen Lint-Check über alle Template-Dateien aus und stellt sicher, dass keine syntaktisch ungültige Konfiguration veröffentlicht wird.

# Structure of the central template repository
# mironsoft/gitlab-ci-templates/

# magento/build.yml      — Composer, npm, di:compile, static content
# magento/test.yml       — PHPStan, PHPCS, PHPUnit
# magento/deploy.yml     — SSH, rsync, symlink switch, shared files
# magento/verify.yml     — Health check, smoke tests, cache status
# magento/rollback.yml   — Symlink switch to previous release
# magento/cleanup.yml    — Remove old releases, clean old artifacts

# Template repository pipeline (validates all templates)
# .gitlab-ci.yml (in template repo itself)
validate:templates:
  stage: test
  image: alpine:latest
  script:
    - apk add --no-cache curl
    # Validate each template file against GitLab CI lint API
    - |
      for file in magento/*.yml; do
        echo "Validating: $file"
        curl -sf \
          --header "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \
          --header "Content-Type: application/json" \
          --data "{\"content\": \"$(cat ${file} | jq -Rs .)\"}" \
          "${CI_API_V4_URL}/ci/lint" | jq -e '.valid == true'
      done

6. Projektspezifische Overrides und Erweiterungen

Nicht jedes Magento-Projekt ist identisch. Einige Projekte haben zusätzliche Stores mit unterschiedlichen Themes, andere deployen auf mehrere Server-Umgebungen, wieder andere haben spezifische Test-Anforderungen. Das Template-System muss Overrides und Erweiterungen ermöglichen, ohne die Wiederverwendbarkeit der Basis-Templates zu beeinträchtigen.

Die empfohlene Strategie ist, projektspezifische Konfiguration über Variablen zu übergeben, die im Template als Defaults definiert sind. Wenn das Template MAGENTO_LOCALE: "de_DE" als Default setzt und ein Projekt mehrsprachig ist, überschreibt das Projekt die Variable auf MAGENTO_LOCALE: "de_DE en_US fr_FR". Der Template-Job konsumiert die Variable, ohne den Job-Code zu verändern. Nur wenn die Projektanforderung fundamental über das Template hinausgeht, wird der Job mit extends abgeleitet und die abweichenden Schritte überschrieben.

# Project-specific .gitlab-ci.yml — minimal override pattern

include:
  - project: "mironsoft/gitlab-ci-templates"
    ref: "v2.1.0"
    file: ["/magento/build.yml", "/magento/deploy.yml", "/magento/verify.yml"]

# Override only what differs from the template defaults
variables:
  DEPLOY_HOST: "${PROD_DEPLOY_HOST}"  # From GitLab CI/CD variables
  DEPLOY_PATH: "/var/www/shop"
  MAGENTO_LOCALE: "de_DE en_US"       # Multi-locale override
  THEME_PATH: "app/design/frontend/Mironsoft/default"

# Extend the template deploy job with a project-specific step
deploy:production:
  extends: .deploy:production:base  # From included template
  after_script:
    # Notify project-specific Slack channel after deployment
    - |
      curl -X POST "${SLACK_WEBHOOK_URL}" \
        -d "{\"text\": \"Deployed ${CI_COMMIT_TAG} to production\"}"

7. Template-Versionierung und Breaking Changes

Templates, die von mehreren Projekten referenziert werden, müssen versioniert sein. Ohne Versionierung führt jede Änderung am Template sofort zu Auswirkungen auf alle Projekte, die das Template einbinden. Das ist für Breaking Changes – zum Beispiel das Umbenennen eines versteckten Jobs oder das Hinzufügen einer Pflicht-Variable – inakzeptabel, weil Projekte möglicherweise ohne Vorwarnung brachen.

Semantische Versionierung (SemVer) ist auch für CI-Templates geeignet: Patch-Versionen für Bug-Fixes, Minor-Versionen für neue optionale Features, Major-Versionen für Breaking Changes. Projekte, die auf einen Major-Versions-Tag zeigen, erhalten automatisch alle kompatiblen Verbesserungen, müssen aber beim nächsten Major-Release bewusst migrieren. Die Template-Repository-Pipeline erzeugt automatisch Tags bei Merges auf main, um den Versionierungsprozess zu vereinfachen.

8. Vergleich: Kopierte Pipelines vs. Template-basierte Pipelines

Der Unterschied zwischen kopierten und template-basierten Pipelines zeigt sich besonders deutlich, wenn ein Sicherheitsproblem oder ein Best-Practice-Update über alle Projekte eingespielt werden muss. Bei kopierten Pipelines ist das ein manueller Prozess über alle Repositories. Bei template-basierten Pipelines ist es eine einzige Änderung im Template-Repository.

Aspekt Kopierte Pipelines Template-basierte Pipelines Vorteil
Security-Fix einspielen N Repositories editieren 1 Template-Update Drastisch weniger Aufwand
Konsistenz über Projekte Divergiert mit der Zeit Zentral erzwungen Gleicher Standard überall
Neue Projekte aufsetzen Kopieren, anpassen, testen include + Variablen setzen Minuten statt Stunden
Nachvollziehbarkeit Jedes Repo eigenständig Zentraler Changelog Auditierbar, nachvollziehbar
Projektspezifische Anpassungen Direkt möglich Via extends und Variablen Flexibel, aber kontrolliert

9. Fallstricke bei der Template-Wiederverwendung

Ein häufiger Fallstrick ist das unbeabsichtigte Überschreiben von Template-Variablen durch Projekt-Variablen. Wenn ein Template eine Variable als Pflicht-Variable definiert und das Projekt eine gleichnamige Variable mit einem anderen Wert setzt, gilt der Projekt-Wert – ohne Fehlermeldung. Das kann zu stillen Fehlfunktionen führen, die schwer zu debuggen sind. Eine Namenskonvention für Template-interne Variablen (zum Beispiel Präfix _TMPL_) reduziert Kollisionen.

Ein zweiter Fallstrick betrifft die Referenzierung von hidden Jobs aus Templates. Hidden Jobs beginnen mit einem Punkt (zum Beispiel .build:magento:base) und werden nicht direkt ausgeführt. Wenn ein Projekt einen Job mit extends: .build:magento:base erweitert und der Template-Job umbenannt wird, schlägt die Pipeline des Projekts mit einer nichtssagenden Fehlermeldung fehl. Breaking Changes in Templates müssen daher immer mit einer Major-Version und einem klaren Changelog kommuniziert werden.

Ein dritter Fallstrick ist das Caching von Template-Dateien durch GitLab. Bei der include: remote-Variante cached GitLab die externe URL. Bei include: project mit einem Branch-Ref (statt einem Tag) wird die Template-Datei zum Zeitpunkt der Pipeline-Ausführung aus dem Repository gelesen – was die erwartete Aktualität bietet, aber bei einem ungültigen Commit im Template-Repository sofort alle abhängigen Projekte-Pipelines blockiert.

10. Zusammenfassung

GitLab CI-Templates für mehrere Magento-Projekte wiederverwenden ist eine Investition, die sich ab dem zweiten Projekt auszahlt. Das include: project-System ermöglicht es, einen gemeinsamen Build-, Test- und Deploy-Standard zentral zu definieren und über Versionstags kontrolliert an alle Projekte auszuliefern. extends erlaubt projektspezifische Overrides ohne vollständige Job-Kopien. Variablen-Defaults im Template und Overrides im Projekt-Repository trennen den gemeinsamen Standard von den projektspezifischen Details.

Das Template-Repository selbst braucht eine eigene Pipeline mit Lint-Checks und semantischer Versionierung. Breaking Changes müssen kommuniziert werden; Projekte migrieren bewusst auf neue Major-Versionen. Mit diesem System ist ein Security-Fix im Deploy-Skript ein einmaliger Commit im Template-Repository statt zehn Commits in zehn Repositories.

GitLab CI Templates — Das Wichtigste auf einen Blick

include: project

Bindet Templates aus einem zentralen Repository ein. ref auf Tag setzen für Stabilitätskontrolle. Zugriff über GitLab-Berechtigungen gesteuert.

extends

Leitet Jobs aus Template-Definitionen ab. Deep-Merge für Dictionaries. Nur abweichende Eigenschaften überschreiben.

Versionierung

SemVer für Template-Tags. Patch: Bug-Fixes, Minor: neue Features, Major: Breaking Changes mit explizitem Changelog.

Projekt-Overrides

Variablen-Overrides für konfigurierbare Unterschiede. extends für strukturelle Abweichungen. Kein direktes Editieren von Template-Dateien.

11. FAQ: GitLab CI Templates für mehrere Magento-Projekte

1include:project vs. include:remote?
include:project nutzt GitLabs Zugriffskontrolle und liest aus einem internen Repo. include:remote liest von externer URL ohne Authentifizierung.
2Mehrere Template-Dateien einbinden?
Ja, include:file akzeptiert eine Liste. Build-, Test- und Deploy-Templates separat halten und je nach Bedarf einbinden.
3Gleicher Job-Name in Template und Projekt?
Projekt überschreibt den Template-Job vollständig. Für partielle Overrides extends verwenden statt gleicher Job-Name.
4Template-Updates auf alle Projekte ausrollen?
Branch-Ref: sofort beim nächsten Pipeline-Lauf. Tag-Ref: manuelle Aktualisierung des Tags im Projekt. Tags sind kontrollierbarer.
5Templates können andere Templates einbinden?
Ja, aber mit Vorsicht. Verschachtelte includes erhöhen Komplexität. Für die meisten Fälle reicht eine Template-Ebene.
6Pflicht-Variablen in Templates definieren?
Kein natives GitLab-Feature. Validierungs-Job am Anfang der Pipeline, der Variablen prüft und mit klarer Fehlermeldung abbricht.
7extends vs. YAML-Anchors?
extends: über Dateigrenzen, GitLab-nativ. YAML-Anchors: nur innerhalb einer Datei. Für Templates immer extends verwenden.
8Wie viele Projekte lassen sich verwalten?
Keine technische Obergrenze. Ab vielen Projekten wird das Template-Repository selbst kritisch und braucht eigene Tests und Reviews.
9Mehrere Magento-Versionen im Template?
Über MAGENTO_VERSION-Variable. Für sehr unterschiedliche Versionen separate Template-Dateien pro Version sinnvoller.
10Template-Repository öffentlich?
Nein, privat reicht. Runner-Token oder CI-Job-Token braucht Lesezugriff. Gruppen-Zugriffsregeln korrekt setzen.