Repository, Default Branch, Branch Protection, Tags
Bevor die erste Zeile der .gitlab-ci.yml geschrieben wird, müssen Repository, Default Branch, Branch Protection und Protected Tags korrekt konfiguriert sein. Diese Einstellungen sind der organisatorische Rahmen, der verhindert, dass technisch gute Pipelines durch schlechte Governance ausgehebelt werden.
Inhaltsverzeichnis
- 1. Warum das Projekt-Setup der erste Schritt ist
- 2. Repository-Struktur für Magento
- 3. .gitignore für Magento korrekt einrichten
- 4. Default Branch und Einstellungen
- 5. Branch Protection: main und release/*
- 6. Merge Requests und Approval-Regeln
- 7. Protected Tags für Release-Freigaben
- 8. Deploy Keys und SSH-Zugriff einrichten
- 9. Setup-Varianten im Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Warum das Projekt-Setup der erste Schritt ist
Das GitLab-Projekt-Setup ist keine Formalität, die man nachträglich nachholen kann. Wer direkt mit der Pipeline beginnt und das Projekt-Setup ignoriert, merkt oft erst dann, dass etwas fehlt, wenn der erste Incident eintritt: Ein Entwickler pusht direkt auf main und löst unbeabsichtigt ein Deployment aus. Ein Production-Secret ist zu breit sichtbar und wird in einem Feature-Branch-Job verwendet. Ein Release-Tag wird von einem Entwickler ohne Maintainer-Rechte erstellt und löst ein ungeprüftes Production-Deployment aus. Diese Szenarien sind vermeidbar – aber nur, wenn das Projekt vor der ersten Pipeline korrekt aufgesetzt wurde.
Für Magento-Projekte ist dieser Punkt besonders kritisch. Ein Magento-Shop enthält sensible Konfigurationsdaten, Composer-Zugangsdaten für Adobe Commerce und SSH-Schlüssel für Deployment-Server. Diese Daten dürfen nicht in das Repository gelangen und müssen in CI/CD-Variablen mit korrekten Scopes und Flags verwaltet werden. Wer das Repository nicht von Anfang an mit einer korrekten .gitignore und strukturierten Branch-Regeln einrichtet, schafft technische Schulden, die später sehr aufwendig zu beheben sind.
Die gute Nachricht: Das korrekte Setup eines GitLab-Projekts für Magento dauert etwa zwei Stunden und kann einmal dokumentiert werden. Danach dient es als Vorlage für alle weiteren Magento-Projekte in derselben Organisation. Die folgenden Abschnitte gehen jeden Schritt durch – von der Repository-Struktur über Branch Protection und Protected Tags bis zu Deploy Keys und SSH-Zugriff.
2. Repository-Struktur für Magento
Die Entscheidung, was ins Repository gehört und was nicht, hat direkte Auswirkungen auf die Pipeline. Für Magento-Projekte empfiehlt sich ein Monorepo mit dem gesamten Shop-Code: Custom-Module in app/code/, Theme in app/design/, composer.json und composer.lock, package.json und package-lock.json sowie die .gitlab-ci.yml. Was nicht ins Repository gehört: vendor/, generated/, pub/static/ (werden im Build erzeugt), var/ (Laufzeit-Daten), app/etc/env.php (enthält Secrets) und auth.json (Composer-Zugangsdaten).
Die composer.lock-Datei sollte unbedingt ins Repository eingecheckt werden, weil sie die exakten Versionen aller Abhängigkeiten festlegt und damit reproduzierbare Builds garantiert. Ohne composer.lock kann composer install bei jedem Build andere Patch-Versionen von Abhängigkeiten installieren, was zu nicht reproduzierbaren Artefakten führt. Dasselbe gilt für package-lock.json: Sie gehört ins Repository, damit npm ci garantiert exakt dieselben npm-Pakete installiert.
# Recommended Magento repository structure
# app/code/Vendor/Module/ — Custom modules
# app/design/frontend/Vendor/ — Custom theme
# app/etc/config.php — Committed (no secrets)
# composer.json — Committed
# composer.lock — Committed (reproducible builds)
# package.json — Committed
# package-lock.json — Committed
# .gitlab-ci.yml — Committed
# NOT in repository (add to .gitignore):
# vendor/ — Generated by composer install
# generated/ — Generated by setup:di:compile
# pub/static/ — Generated by setup:static-content:deploy
# var/ — Runtime data (logs, cache, sessions)
# app/etc/env.php — Contains secrets (DB password, Redis URL)
# auth.json — Composer auth (use CI variable instead)
# .env — Environment file (use CI variables)
3. .gitignore für Magento korrekt einrichten
Die .gitignore-Datei für Magento muss vollständig sein und von Anfang an korrekt konfiguriert werden, weil nachträgliche Ergänzungen Git-Objekte, die bereits getrackt werden, nicht automatisch aus dem Index entfernen. Besonders kritisch ist, dass app/etc/env.php und auth.json niemals ins Repository gelangen dürfen – sie enthalten Datenbankpasswörter, Redis-URLs und Composer-Zugangsdaten. Eine einmal in den Git-History eingecheckte Datei mit Secrets muss mit aufwendigen Verfahren wie git filter-branch oder BFG Repo Cleaner vollständig aus der History entfernt werden.
Magento liefert eine Standard-.gitignore mit, die die wichtigsten generierten Verzeichnisse abdeckt. Diese sollte um projektspezifische Ergänzungen erweitert werden: IDE-Konfigurationsverzeichnisse wie .idea/ und .vscode/, temporäre Build-Dateien, lokale Konfigurationsdateien und alle Dateien, die Secrets enthalten könnten. GitLab bietet beim Erstellen eines neuen Projekts die Option, eine .gitignore aus einer Vorlage zu generieren – für Magento sollte die PHP-Vorlage als Ausgangspunkt gewählt und dann manuell ergänzt werden.
4. Default Branch und Einstellungen
Der Default Branch ist der Branch, auf den neue Repositories standardmäßig zeigen und der bei Merge Requests als Ziel vorausgewählt wird. Für Magento-Projekte sollte der Default Branch main heißen – nicht master (veraltete Konvention) und nicht develop (verwechselt den Default Branch mit einem Entwicklungs-Branch). main repräsentiert den aktuellen Produktions-Code und ist der Branch, aus dem Releases erstellt werden.
Unter Settings > General > Visibility, project features, permissions sollten folgende Optionen für produktive Magento-Projekte konfiguriert sein: Visibility auf Private, Merge Requests auf Enabled, Issues nach Bedarf. Die Option Delete source branch after merge unter Settings > General > Merge request sollte aktiviert sein, damit der Branch-Baum übersichtlich bleibt. Die Option Squash commits when merging kann auf Encouraged gesetzt werden, damit Merge Requests eine saubere Commit-Historie hinterlassen.
# GitLab project settings — configure before first pipeline run
# Settings > General > Visibility:
# Visibility level: Private
# Issues: Enabled (optional)
# Merge Requests: Enabled (required)
# Pipelines: Enabled (required)
# Settings > General > Merge request:
# Merge method: Merge commit (or Squash)
# Squash commits: Encouraged
# Delete source branch: Enabled (checked by default)
# Pipelines must succeed: Enabled
# All discussions must be resolved: Enabled
# Settings > Repository > Default branch:
# Default branch: main
# Verify correct default branch is set
# git remote add origin git@gitlab.mironsoft.de:mironsoft/shop.git
# git push -u origin main
# Then set main as default in GitLab UI
5. Branch Protection: main und release/*
Protected Branches sind der wichtigste technische Kontrollmechanismus für Deployment-Sicherheit in GitLab. Für main gilt die strikteste Konfiguration: Allowed to push: No one, Allowed to merge: Maintainers (oder Developers, wenn das Team den Prozess versteht). Diese Einstellung stellt sicher, dass kein Entwickler direkt auf main pushen kann – weder durch Unachtsamkeit noch durch einen Force Push. Alle Änderungen müssen den Weg über einen Merge Request nehmen, der reviewed und genehmigt werden muss.
Das Pattern release/* schützt alle Branches, die mit release/ beginnen. Diese Branches werden für Release-Kandidaten und Hotfix-Prozesse verwendet: Ein Release-Branch release/1.2.3 wird aus main erstellt, erhält letzte Anpassungen und wird dann zurück in main gemergt. Protected Branches für release/* verhindern direktes Pushen auf diese Branches und erfordern denselben Review-Prozess wie für main. Die Einstellung Allowed to force push: No sollte für alle Protected Branches aktiviert sein – Force Pushes auf geschützte Branches können Commit-History zerstören und sind in keinem produktiven Workflow notwendig.
6. Merge Requests und Approval-Regeln
Merge Requests sind der kontrollierte Weg, wie Code in Protected Branches gelangt. Für Magento-Projekte sollten folgende Approval-Regeln konfiguriert sein: Mindestens ein Approval von einem Maintainer ist erforderlich, bevor ein Merge Request auf main zusammengeführt werden kann. Für sicherheitskritische Dateien wie .gitlab-ci.yml, composer.json und Konfigurationsdateien in app/etc/ kann in GitLab Premium ein Code-Owner-System eingerichtet werden, das einen spezifischen Reviewer für diese Dateien erzwingt.
Die Pipeline-Integration mit Merge Requests ist ein wichtiger Qualitätsmechanismus: Unter Settings > General > Merge request kann die Option Pipelines must succeed aktiviert werden. Das bedeutet, dass ein Merge Request erst zusammengeführt werden kann, wenn alle Pipeline-Jobs erfolgreich durchgelaufen sind – inklusive PHPStan, PHPUnit und Lint-Checks. Dieser Mechanismus verhindert, dass fehlerhafter Code in main gelangt, der die nächste Pipeline fehlschlagen lassen würde.
# Branch protection configuration summary
# Settings > Repository > Protected Branches
# main branch
# - Allowed to push: No one
# - Allowed to merge: Maintainers
# - Allowed to force push: No
# - Code owner approval: Yes (GitLab Premium)
# - Pipelines must succeed: Yes (via MR settings)
# release/* branches
# - Allowed to push: No one
# - Allowed to merge: Maintainers
# - Allowed to force push: No
# development branches (feature/*, fix/*)
# - No protection (developers push freely)
# - MR required to merge into main or release/*
# Settings > Repository > Protected Tags
# - v* pattern
# - Allowed to create: Maintainers
7. Protected Tags für Release-Freigaben
Protected Tags mit dem Muster v* sind das Auslösesignal für Production-Deployments. Die Logik ist einfach und wirkungsvoll: Ein Maintainer erstellt einen Tag nach dem Muster v1.2.3, dieser Tag ist durch die Protection-Regel geschützt und kann nur von Maintainern erstellt werden, und die Pipeline führt den Production-Deploy-Job nur dann aus, wenn der Commit durch einen solchen Tag ausgelöst wurde. Das erzeugt eine technische Schranke, die unbeabsichtigte Production-Deployments strukturell ausschließt.
Für die Versionierung bietet sich Semantic Versioning an: Major-Version für inkompatible API-Änderungen, Minor-Version für neue Features und Patch-Version für Bugfixes. Das ist für Magento nicht nur eine Konvention, sondern auch praktisch: Tags wie v1.2.3 machen in der GitLab-Pipeline-Übersicht sofort klar, was released wurde. Ein Annotated Tag (git tag -a v1.2.3 -m "Release 1.2.3: Checkout-Fix und Performance-Verbesserungen") enthält eine Beschreibung und ist die empfohlene Form für Release-Tags.
8. Deploy Keys und SSH-Zugriff einrichten
Deploy Keys ermöglichen einem externen System – in diesem Fall dem GitLab Runner oder einem Deployment-Skript – Read-only oder Read-Write-Zugriff auf das Repository, ohne dass ein persönlicher Access Token mit vollen Benutzerrechten verwendet werden muss. Für Magento-Deployments wird typischerweise kein Read-Write-Zugriff benötigt – der Runner checkt den Code aus und überträgt ihn auf den Server, schreibt aber nicht zurück ins Repository.
Neben Deploy Keys für das Repository braucht die Pipeline SSH-Zugriff auf die Deployment-Server. Dieser wird über eine CI/CD-Variable SSH_PRIVATE_KEY verwaltet, die den privaten SSH-Schlüssel des Deployment-Users enthält. Der öffentliche Schlüssel muss auf allen Deployment-Servern in ~/.ssh/authorized_keys des Deployment-Users eingetragen sein. Für eine neue Deployment-Umgebung sollte immer ein dedizierter Deployment-User ohne Sudo-Rechte angelegt werden – Least-Privilege-Prinzip.
# SSH setup for GitLab CI/CD deployment
# Generate dedicated deployment keypair (outside of repository):
# ssh-keygen -t ed25519 -C "gitlab-deploy@mironsoft.de" -f gitlab-deploy
# Public key (gitlab-deploy.pub) -> add to server:
# cat gitlab-deploy.pub >> /home/deploy/.ssh/authorized_keys
# chmod 600 /home/deploy/.ssh/authorized_keys
# Private key (gitlab-deploy) -> add to GitLab CI/CD variable:
# Settings > CI/CD > Variables
# Name: SSH_PRIVATE_KEY
# Value: <contents of gitlab-deploy>
# Protected: Yes, Masked: Yes, Scope: production
# Known hosts -> get with:
# ssh-keyscan -H web01.mironsoft.de
# Add output to CI/CD variable SSH_KNOWN_HOSTS
# Usage in .gitlab-ci.yml:
# before_script:
# - 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
9. Setup-Varianten im Vergleich
Das Ausmaß des Projekt-Setups hängt von der Teamgröße und dem Risikoprofil ab. Für ein Einzelentwickler-Projekt ohne Team können einige Regeln gelockert werden – aber auch dann sollte die Repository-Struktur, die .gitignore und die Protected Tags vollständig konfiguriert sein. Für Teamprojekte mit mehreren Entwicklern und einer Production-Umgebung ist die vollständige Konfiguration aller Governance-Regeln Pflicht.
| Setup-Element | Einzelentwickler | Kleines Team | Größeres Team |
|---|---|---|---|
| Repository-Struktur | Vollständig | Vollständig | Vollständig |
| Protected main Branch | Optional | Empfohlen | Pflicht |
| Merge Request Approval | Nicht notwendig | Optional | Pflicht |
| Protected Tags v* | Empfohlen | Empfohlen | Pflicht |
| Deploy Keys | Pflicht | Pflicht | Pflicht |
Die Faustregel: Alles, was Security betrifft – .gitignore für Secrets, Protected Tags für Release-Kontrolle, Deploy Keys statt persönlicher Tokens – ist immer Pflicht, unabhängig von der Teamgröße. Governance-Regeln für Review-Prozesse können skaliert werden, aber Sicherheitsregeln nicht.
10. Zusammenfassung
Das GitLab-Projekt-Setup für Magento umfasst fünf wesentliche Schritte: Repository-Struktur mit korrekter .gitignore, Default Branch auf main setzen, Protected Branches für main und release/* konfigurieren, Protected Tags mit Muster v* für Release-Freigaben einrichten und SSH-Zugriff über dedizierte Deployment-Keys verwalten. Diese Einstellungen bilden das organisatorische Fundament, auf dem alle Pipeline-Jobs aufbauen.
Der häufigste Fehler ist nicht, eine dieser Einstellungen falsch zu konfigurieren, sondern sie zu überspringen, weil sie "später noch gemacht werden können". In der Realität kommt "später" oft nicht, weil das Projekt bereits läuft und das Nachkonfigurieren laufende Prozesse unterbricht. Wer das Setup vor der ersten Pipeline-Ausführung vollständig abschließt, erspart sich Governance-Nacharbeit in einem ungünstigen Moment – nämlich dann, wenn das erste kritische Deployment ansteht.
GitLab Projekt-Setup — Das Wichtigste auf einen Blick
Repository-Struktur
.gitignore von Anfang an vollständig – besonders env.php und auth.json. Nie Secrets ins Repository. composer.lock und package-lock.json immer committen.
Branch Protection
main und release/* schützen – kein direktes Pushen. Alle Änderungen über Merge Requests mit Pipeline-Pflichtprüfung.
Protected Tags
Muster v* nur für Maintainer. Technische Schranke für Production-Deployments. Semantic Versioning mit Annotated Tags.
SSH & Deploy Keys
Dedizierter Deployment-User ohne Sudo. SSH-Key als Protected+Masked CI-Variable. SSH_KNOWN_HOSTS vorbereiten.