Zum Hauptinhalt springen
Technische Details

CI/CD für PHP: Ein umfassender Leitfaden

← Technische Details

Von Evren BalVeröffentlicht Aktualisiert  · 8 Min. Lesezeit

PHP-Elefant, Prüflupe und blaue Pakete durchlaufen eine technische Fertigungslinie.
Diesen Artikel mit Ihrer KI besprechen

CI/CD für PHP ist nicht eine einzelne YAML-Datei, die Code blind in die Produktionsumgebung kopiert. Es ist eine Kette von Prüfpunkten, die aus einer Codeänderung ein geprüftes Release macht und anschließend kontrolliert, wie dieses Release eine Umgebung erreicht. Bei einem PHP-Projekt bedeutet das üblicherweise: exakt die festgelegten Composer-Abhängigkeiten installieren, statische Analyse und Tests ausführen, ein auslieferbares Artefakt erstellen und die Bereitstellung erst zulassen, wenn diese Prüfungen bestanden sind.

💡 Kurzfassung (TL;DR):

  • Kontinuierliche Integration: Prüfen Sie jede Änderung durch reproduzierbare Installation der Abhängigkeiten, statische Analyse, Linting und automatisierte Tests.
  • Kontinuierliche Bereitstellung oder Auslieferung: Halten Sie das geprüfte Release auslieferbar und legen Sie an einer klaren Umgebungsgrenze fest, ob die Produktionsbereitstellung eine Freigabe erfordert oder automatisch erfolgt.
  • Sichere Bereitstellung: Verhindern Sie sich überschneidende Releases, begrenzen Sie den Zugriff auf Geheimnisse, stellen Sie eine bekannte Revision oder ein bekanntes Artefakt bereit, prüfen Sie den Zustand der Anwendung und halten Sie einen Rücksetzpfad vor.

Was CI/CD für ein PHP-Projekt bedeutet

CI/CD wird oft als eine Abkürzung verwendet, doch seine Bestandteile beschreiben unterschiedliche Verantwortlichkeiten:

  • Continuous Integration (CI) prüft Änderungen, sobald sie in ein gemeinsames Repository gelangen. Ein CI-Ablauf installiert Abhängigkeiten, führt Prüfungen aus und meldet, ob die Änderung sicher zusammengeführt werden kann.
  • Continuous Delivery hält den Hauptzweig in einem auslieferbaren Zustand. Ein geprüftes Release kann über einen bewussten Freigabeschritt in die Produktionsumgebung gelangen.
  • Continuous Deployment veröffentlicht automatisch jede Änderung, die alle erforderlichen Prüfpunkte besteht.

Die zweite Bedeutung von CD sollte ausdrücklich benannt werden. Ein Team kann über eine solide CI verfügen, ohne automatisch auszuliefern. Und ein Ablauf, der nur Tests ausführt, ist noch keine vollständige Bereitstellungspipeline.

Eine praxisnahe PHP-Pipeline folgt meist diesem Weg:

  1. Ein Pull Request oder Commit startet den Ablauf.
  2. Composer installiert die in composer.lock festgehaltenen Versionen.
  3. Linter, statische Analyse und automatisierte Tests prüfen die Änderung.
  4. Die Pipeline identifiziert oder erstellt exakt die Revision, das Paket oder das Container-Image, das veröffentlicht werden soll.
  5. Ein separater Bereitstellungsauftrag zielt auf die Staging- oder Produktionsumgebung.
  6. Zustandsprüfungen bestätigen das Release, während der Bereitstellungsmechanismus einen Rücksetzpfad bereithält.

Die Plattform koordiniert diese Abfolge. Die Sicherheit entsteht durch die Prüfpunkte und das Release-Design, nicht durch den Namen des CI-Produkts.

Wählen Sie Prüfungen nach den Folgen eines Fehlers

Eine PHP-Pipeline benötigt nicht jeden denkbaren Test bei jedem Commit. Sie benötigt Prüfungen, die jene Fehler abdecken, welche die Anwendung tatsächlich verursachen kann:

  • Unit-Tests prüfen Funktionen und Klassen isoliert, häufig mit PHPUnit.
  • Integrationstests prüfen Grenzen wie Datenbanken, Warteschlangen, Caches und Adapter externer Dienste.
  • Funktionale oder Ende-zu-Ende-Tests prüfen wichtige Nutzerabläufe mit Werkzeugen wie Symfony Panther, Playwright oder Cypress.
  • Statische Analyse mit PHPStan oder Psalm erkennt Typkonflikte, unmögliche Aufrufe und andere Fehler, ohne die Anwendung auszuführen.
  • Leistungstests gehören in die Pipeline, wenn Latenz, Durchsatz oder Ressourcenverbrauch ein Release verhindern können. Sie müssen jedoch nicht bei jedem kleinen Pull Request laufen.

Das Ziel ist nicht die größtmögliche Testsuite. Das Ziel sind ausreichende Belege, um eine unsichere Änderung zu stoppen, bevor sie die nächste Umgebung erreicht.

Einmal bauen und eindeutig festhalten, was Sie ausliefern

PHP-Anwendungen haben nicht immer einen klassischen Kompilierschritt, besitzen aber dennoch eine Build-Grenze. Dazu können gehören:

  • composer.json validieren und festgeschriebene Abhängigkeiten installieren;
  • Frontend-Assets kompilieren und minimieren;
  • optimierte Autoload-Dateien erzeugen;
  • statische Analyse und Tests ausführen;
  • ein Archiv für ein Release-Verzeichnis erstellen;
  • ein mit der Commit-SHA gekennzeichnetes Container-Image bauen.

Eine Bereitstellung sollte auf eine bekannte Revision oder ein bekanntes Artefakt zeigen. Werden während der Bereitstellung andere Abhängigkeiten neu installiert, kann Code entstehen, der nicht mit dem vom CI-Auftrag geprüften Stand identisch ist. Die konkrete Paketierung hängt von Anwendung und Hosting-Modell ab; die Identität des Releases sollte jedoch nachvollziehbar bleiben.

Eine CI/CD-Plattform auswählen

Sowohl GitHub Actions als auch GitLab CI/CD können eine PHP-Auslieferungspipeline ausführen. Welche Wahl sinnvoller ist, hängt davon ab, wo das Repository liegt und wie die Anwendung bereitgestellt werden muss.

Prüfen Sie vor der Auswahl:

  • ob gehostete oder selbst betriebene Runner die erforderlichen Dienste erreichen können;
  • wie Umgebungen, Freigaben, Parallelität und Geheimnisse kontrolliert werden;
  • ob das Bereitstellungsziel ein Archiv, Container-Image, Serverless-Paket oder einen entfernten Befehl erwartet;
  • wie fehlgeschlagene Releases erkannt und zurückgesetzt werden;
  • welche Protokolle und Bereitstellungsnachweise das Team aufbewahren muss.

Sind diese Entscheidungen getroffen, ist die Einrichtung geradlinig:

  1. Legen Sie die Ablaufkonfiguration in der Versionsverwaltung ab.
  2. Definieren Sie PHP-Version und erforderliche Erweiterungen ausdrücklich.
  3. Installieren Sie die Abhängigkeiten aus composer.lock.
  4. Fügen Sie die Prüfungen hinzu, die vor dem Zusammenführen oder Veröffentlichen bestehen müssen.
  5. Halten Sie die Bereitstellung in einem eigenen Auftrag mit eigenen Berechtigungen und einer eigenen Umgebung.
  6. Testen Sie das Rücksetzverfahren, bevor Sie die Pipeline als produktionsreif behandeln.

Beispiel: PHP-CI mit GitHub Actions

Das folgende Beispiel für .github/workflows/ci.yml setzt die Prüfseite der Pipeline um. Es behauptet nicht, eine Anwendung bereitzustellen, denn der Bereitstellungsbefehl hängt von der tatsächlichen Infrastruktur ab.

name: Verify PHP

on:
  pull_request:
  push:
    branches: [main]

permissions:
  contents: read

concurrency:
  group: verify-${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  verify:
    runs-on: ubuntu-latest

    steps:
      - name: Check out the repository
        uses: actions/checkout@v4

      - name: Set up PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          extensions: mbstring, xml, ctype, iconv, zip
          coverage: none

      - name: Find the Composer cache directory
        id: composer-cache
        run: echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"

      - name: Cache Composer downloads
        uses: actions/cache@v4
        with:
          path: ${{ steps.composer-cache.outputs.dir }}
          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
          restore-keys: |
            ${{ runner.os }}-composer-

      - name: Validate Composer metadata
        run: composer validate --strict

      - name: Install dependencies
        run: composer install --prefer-dist --no-progress --no-interaction

      - name: Run static analysis
        run: vendor/bin/phpstan analyse

      - name: Run tests
        run: vendor/bin/phpunit

Dieses Beispiel beschränkt das Standard-Token auf Lesezugriff auf das Repository. Außerdem entfernt es die veraltete Option --no-suggest aus dem Composer-Befehl. Passen Sie PHP-Version, Erweiterungen und Projektbefehle an die Anwendung an, statt sie ungeprüft zu kopieren.

Versions-Tags halten Beispiele lesbar. Ein Produktions-Repository sollte jedoch seine Richtlinie für die Lieferkette von Actions festlegen. GitHub empfiehlt, Drittanbieter-Actions an eine geprüfte vollständige Commit-SHA zu binden und einem Ablauf ausdrücklich nur die benötigten Berechtigungen zu geben.

Bereitstellung als separaten kontrollierten Auftrag ergänzen

Ein Bereitstellungsauftrag sollte von der Prüfung abhängen und nur für das vorgesehene Release-Ereignis laufen. Der folgende Auftrag zeigt diese Grenze, ohne vorzugeben, dass ein einziger Bereitstellungsbefehl für jeden Server oder jede Plattform geeignet wäre:

  deploy:
    needs: verify
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest

    permissions:
      contents: read

    environment: production

    concurrency:
      group: production
      cancel-in-progress: false

    steps:
      - name: Check out the deployment scripts
        uses: actions/checkout@v4

      - name: Deploy the verified revision
        env:
          RELEASE_SHA: ${{ github.sha }}
        run: ./scripts/deploy-production.sh "$RELEASE_SHA"

Das Skript bildet eine ausdrückliche Projektgrenze, kein allgemeingültiges Rezept. Je nach Ziel kann es Deployer anweisen, ein Release-Verzeichnis zu aktivieren, ein Container-Image über seinen Digest zu aktualisieren oder ein Serverless-Paket zu veröffentlichen. Unabhängig von der Umsetzung sollte es:

  • die mit RELEASE_SHA verknüpfte Revision oder das zugehörige Artefakt bereitstellen;
  • verhindern, dass zwei Produktions-Releases gleichzeitig laufen;
  • Bereitstellungszugangsdaten aus der geschützten Produktionsumgebung lesen;
  • fehlschlagen, wenn die Zustandsprüfung fehlschlägt;
  • das vorherige Release für eine Rücksetzung aufbewahren oder eindeutig benennen.

GitHub-Umgebungen können Bereitstellungszweige einschränken, einen Auftrag verzögern, eine Freigabe verlangen und Umgebungsgeheimnisse zurückhalten, bis die Schutzregeln bestanden sind. Eine geschützte Umgebung ist daher mehr als eine Bezeichnung in der YAML-Datei.

Moderne Strategien für die Bereitstellung von PHP

Die Bereitstellungsstrategie sollte zum Hosting-Modell und zum Fehlermodus passen:

  • Release-Verzeichnisse und Symlink-Umschaltung: Werkzeuge wie Deployer bereiten ein neues Release-Verzeichnis vor und schalten nach erfolgreicher Vorbereitung den aktiven Symlink um. Für eine Rücksetzung kann der Symlink wieder auf ein früheres Release zeigen.
  • Container-Bereitstellungen: Eine Pipeline baut ein Image einmal, kennzeichnet oder erfasst es unveränderlich und lässt den Orchestrator die Instanzen über eine rollierende oder Blue-Green-Bereitstellung ersetzen. Zustandsprüfungen entscheiden, wann die bisherigen Instanzen keine Anfragen mehr bedienen müssen.
  • Serverless-PHP: Werkzeuge wie Bref paketieren PHP-Anwendungen für AWS Lambda. Infrastrukturverwaltung verändert sich, statt zu verschwinden; auch die Rücksetzung erfordert eindeutig identifizierbare Versionen oder Aliasse.

Keine dieser Strategien ist universell die beste. Entscheidend ist, welche Strategie ein reproduzierbares Release, einen sicheren Umgang mit Geheimnissen, einen beobachtbaren Systemzustand und eine für die Anwendung vertretbare Wiederherstellungszeit ermöglicht.

Häufige Fehler in PHP-Pipelines

  • Veralteter Abhängigkeitscache: Verknüpfen Sie den Composer-Downloadcache mit composer.lock. Speichern Sie heruntergeladene Pakete im Cache, nicht ein undurchsichtiges vendor/-Verzeichnis, das Installationsprobleme verbergen kann.
  • Fehlende Erweiterungen: Deklarieren Sie die erforderlichen PHP-Erweiterungen ausdrücklich, damit der Runner der unterstützten Laufzeitumgebung der Anwendung entspricht.
  • Sich überschneidende Bereitstellungen: Nutzen Sie Parallelitätsregeln auf Bereitstellungsebene und brechen Sie ein laufendes Produktions-Release nicht automatisch mittendrin ab.
  • Zu früh zugängliche Geheimnisse: Halten Sie Produktionszugangsdaten aus Pull-Request-Aufträgen heraus und beschränken Sie sie auf eine geschützte Umgebung.
  • Tests bestehen, die Bereitstellung scheitert: Prüfen Sie Zielerreichbarkeit, Schreibrechte, Migrationen, Zustandsprüfungen und Rücksetzung getrennt von den Anwendungstests.
  • Anderer Code wird bereitgestellt: Binden Sie das Release an die Commit-SHA, den Artefakt-Digest oder die Paketkennung, die der geprüfte Ablauf erzeugt hat.

Offizielle Dokumentation und weiterführende Lektüre

Die praktische Entscheidung

Eine brauchbare PHP-CI/CD-Pipeline macht den Weg von der Änderung zum Release nachvollziehbar. Sie benennt, was geprüft wird, was bereitgestellt wird, wer oder was die Produktion freigeben kann und wie das System nach einem fehlgeschlagenen Release in einen bekannten Zustand zurückkehrt.

Beginnen Sie mit dem Fehler- und Wiederherstellungsmodell der Anwendung. Wählen Sie anschließend Prüfungen, Plattform und Bereitstellungsmechanismus so, dass sie dieses Modell durchsetzen. Eine kürzere Pipeline mit klaren Prüfpunkten und erprobtem Rücksetzpfad ist glaubwürdiger als ein langer Ablauf, der sich produktionsreif nennt, ohne den letzten Schritt zu kontrollieren.

Änderungen an diesem Artikel

  • 27.08.2026: Continuous Integration, Continuous Delivery und Continuous Deployment voneinander abgegrenzt; das GitHub-Actions-Beispiel um einen geprüften CI-Auftrag und eine separate, kontrollierte Bereitstellungsgrenze neu aufgebaut; Hinweise zu Umgebungen, Parallelität, Berechtigungen, Geheimnissen, Release-Identität, Zustandsprüfungen und Rücksetzung ergänzt; veraltete Composer-Optionen und wiederholende FAQ-Inhalte entfernt.
  • 20.06.2026: Einen GitHub-Actions-Ablauf, moderne Testempfehlungen, Strategien für unterbrechungsfreie Bereitstellung, Hinweise zur Fehlerbehebung und Links zur offiziellen Dokumentation ergänzt.
  • 11.05.2022: Artikelzusammenfassung aktualisiert.

Wenn dieser Artikel hilfreich war

Ein Link von einer passenden Seite Ihrer Website oder das Teilen in sozialen Medien hilft diesem Artikel, mehr Menschen zu erreichen. Vielen Dank.

Hinweise zu Links und Marke →