GitHub Actions CI-Pipeline in der Praxis: Build und Test automatisieren
Das Handy vibriert. Eine Nachricht vom Kollegen: „Produktion ist down – dein gestern gemergter Code.“
Kurz der Schock. Lokal liefen die Tests doch? In den Logs zeigte sich später: lokal Node 20, Testumgebung Node 18 – ein API-Verhalten wich ab. In dem Moment ärgert man sich – hätte vor dem Merge eine CI-Pipeline automatisch getestet, wäre das nicht passiert.
Manuelles Testen vergisst man leicht. Wer nicht vergisst, wurde meist schon einmal erwischt. GitHub Actions löst genau das: nach jedem Push automatisch bauen, testen, deployen – die Maschine übernimmt.
Dieser Artikel führt Sie von null zu einer vollständigen CI-Pipeline: kopierfähiges Workflow-Template, Matrix für parallele Mehrfachversionen (oft über die Hälfte Laufzeit gespart) und Praxis aus echten Projekten. Los geht’s.
Kapitel 1: GitHub Actions schnell starten
Was ist GitHub Actions?
Kurz gesagt: GitHub Actions ist die eingebaute Automatisierungsplattform von GitHub. Sie pushen lokal – in der Cloud laufen Test, Build und Deployment.
Früher brauchte man Jenkins-Server mit Wartung und Upgrades. Bei GitHub Actions entfallen Server und Installation: eine YAML-Datei im Repo genügt. Monatlich 2.000 kostenlose Minuten (öffentliche Repos unbegrenzt) – für persönliche Projekte und kleine Teams meist ausreichend.
Gegenüber Jenkins oder Travis CI: tiefe GitHub-Integration, Build-Status direkt im PR, einfache Konfiguration ohne Groovy, tausende Actions im Marketplace. Nachteile: Vendor-Lock-in bei GitHub; sehr komplexe Enterprise-Pipelines sind Jenkins teils flexibler. Für die meisten Projekte reicht GitHub Actions.
Kernbegriffe im Überblick
Anfangs verwirren ein paar Begriffe – in einfachen Worten:
Workflow: Eine YAML-Datei mit dem gesamten Automatisierungsablauf – z. B. „bei jedem Push auf main Tests ausführen“. Liegt unter .github/workflows/.
Job: Eine Gruppe von Schritten im Workflow. Jobs laufen parallel oder mit Abhängigkeiten – zuerst „Test“, danach „Deploy“.
Step: Eine einzelne Aktion im Job, nacheinander – npm test oder actions/checkout@v4.
Runner: Die VM, die den Job ausführt – ubuntu-latest, windows-latest, macos-latest. Eigene Server sind möglich; meist reichen die offiziellen Runner.
Analogie: Workflow = Drehbuch, Job = Szene, Step = Bewegung, Runner = Schauspieler.
Ihr erster CI-Workflow
Nicht zu lange planen – erst laufen lassen. Unter .github/workflows/ci.yml folgenden Inhalt einfügen:
name: CI Pipeline # Name in der GitHub Actions-Oberfläche
on:
push:
branches: [main] # Trigger bei Push auf main
pull_request:
branches: [main] # Trigger bei PR gegen main
permissions:
contents: read # Minimalprinzip: nur Lesezugriff
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
Was passiert hier?
on definiert Trigger: Push auf main oder PR gegen main. permissions mit contents: read – Minimalprinzip, kein versehentliches Überschreiben des Repos. Der Job build auf Ubuntu: Checkout, Node, Dependencies, Test, Build.
Committen, pushen, Actions-Tab öffnen – der grüne Kreis zeigt den laufenden Workflow. Nach wenigen Minuten grüne Häkchen? Ihre erste CI-Pipeline läuft.
Rotes Kreuz? Logs Schritt für Schritt lesen. In den meisten Fällen scheitern Dependency-Install oder Tests selbst – nicht die CI-Konfiguration.
Kapitel 2: Kernkonfiguration der CI-Pipeline
Der Workflow aus Kapitel 1 läuft – für den Alltag fehlen noch Feinheiten. Vier Säulen: Trigger, Berechtigungen, Umgebungsvariablen, Cache. Richtig gesetzt wird die Pipeline sicherer und schneller.
Trigger: wann läuft was?
Am häufigsten: push und pull_request.
on:
push:
branches: [main, dev]
paths:
- 'src/**'
- 'package.json'
pull_request:
branches: [main]
paths ist praktisch: Änderungen nur in docs/ lösen keine CI aus – spart Minuten und Kosten.
Weitere Optionen:
schedule: Cron, z. B. nächtlicher Build:
on:
schedule:
- cron: '0 0 * * *' # täglich 00:00 UTC (08:00 Peking)
Ein Projekt nutzt das für tägliches npm outdated und E-Mail bei veralteten Paketen.
workflow_dispatch: manueller Start ohne Push – Button „Run workflow“ in der Actions-UI.
on:
workflow_dispatch:
Berechtigungen: Sicherheit zuerst
Standardmäßig erhält der Workflow ein GITHUB_TOKEN mit Schreibrechten – praktisch, aber riskant: missbrauchte Workflows könnten das Repo verändern.
2021 gab es einen Vorfall: über einen gefälschten PR lief bösartiger Code in der CI. Seitdem gilt: explizit minimale Rechte.
permissions:
contents: read
pull-requests: write # nur wenn PR-Kommentare o. Ä. nötig
Für reine CI (Test + Build) reicht contents: read. Release oder PR-Kommentare? Gezielt ergänzen.
Tipp: in den Repo-Einstellungen Default auf „Read repository contents“ – Workflows starten read-only, Schreiben nur wo deklariert.
Umgebungsvariablen: Ebenen
Drei Ebenen: Workflow, Job, Step – tiefer überschreibt höher.
env:
NODE_ENV: production
CI: true
jobs:
build:
env:
BUILD_TARGET: web
steps:
- name: Run custom script
env:
MY_VAR: hello
run: echo $MY_VAR
Beispiel: NODE_ENV für alle Jobs auf Workflow-Ebene; BUILD_TARGET nur im build-Job; temporäre Werte im Step.
Sensible Daten nie im Klartext in YAML. Secrets unter Repository Settings anlegen und referenzieren:
steps:
- name: Deploy to server
env:
SSH_KEY: ${{ secrets.SSH_KEY }}
run: |
echo "$SSH_KEY" > private.key
ssh -i private.key user@server 'deploy.sh'
Dependency-Cache: Builds beschleunigen
Hunderte npm-Pakete? Jede CI-Installation von null dauert – in einem Projekt 3 Minuten Install, 1 Minute Test: 75 % der Zeit nur für Dependencies.
setup-node bringt eingebauten Cache:
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
Erster Lauf: normale Installation, Cache wird geschrieben. Unveränderte package-lock.json: Wiederherstellung aus Cache – oft von 3 Minuten auf ~10 Sekunden.
Für pnpm/yarn: cache: 'pnpm' bzw. cache: 'yarn'.
Feiner steuerbar mit actions/cache:
- name: Cache dependencies
uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
npm-${{ runner.os }}-
key eindeutig – hier Hash der Lock-Datei. restore-keys als Fallback bei Teil-Treffer.
Hohe Trefferquote: ein Projekt von 4 auf 1,5 Minuten – bei 20 Läufen pro Tag summiert sich das.
Kapitel 3: Matrix-Strategie – parallel testen
Eine der stärksten Funktionen und Schwerpunkt dieses Artikels: ein Job wird zu vielen parallelen Jobs – verschiedene Versionen, verschiedene OS. Ein Push, viele Builds gleichzeitig; Gesamtzeit oft deutlich unter serieller Ausführung.
Was ist eine Matrix?
Sie müssen Node 16, 18 und 20 testen. Klassisch: drei Jobs oder eine Version nach der anderen – redundant oder langsam.
Die Matrix ist eine Tabelle: Achsen = Versionen und OS, jede Zelle ein Job. GitHub Actions erzeugt alle Kombinationen parallel.
strategy:
matrix:
node: [16, 18, 20]
os: [ubuntu-latest, windows-latest]
Sechs Jobs – Gesamtzeit ≈ langsamster Job, nicht Summe aller.
Versions-Matrix: mehrere Node-Versionen
Ein Bug: lokal Node 20, Nutzer meldet Fehler unter Node 18 – API-Verhalten unterschiedlich. Frühere Mehrfachversionen-Tests hätten das verhindert.
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: [16, 18, 20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test
matrix.node-version: Liste der Versionen${{ matrix.node-version }}im Stepfail-fast: false: ein Fehler stoppt nicht die anderen – sinnvoll für Kompatibilitätstests
include und exclude für feine Steuerung:
strategy:
matrix:
node-version: [16, 18, 20]
os: [ubuntu-latest, windows-latest]
exclude:
- node-version: 16
os: windows-latest
include:
- node-version: 20
os: macos-latest
OS-Matrix: plattformübergreifend
Für CLI-Tools oder plattformabhängigen Code:
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [18, 20]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test
Plattformunterschiede: Pfade (\ vs /), Tool-Verhalten. Kosten: Linux 2.000 Min/Monat gratis; Windows Faktor 2, macOS Faktor 10. macOS nur wenn nötig; optional separates Workflow mit workflow_dispatch; öffentliche Repos unbegrenzt.
Performance-Tipps
Parallele Jobs sind begrenzt – max-parallel steuern:
strategy:
max-parallel: 4
matrix:
node-version: [16, 18, 20, 22]
Bei vielen Kombinationen schont das das Freikontingent.
Cache pro Matrix-Job – setup-node mit cache reicht meist.
Lint braucht selten jede Node-Version:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm run lint
test:
needs: lint
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test
Lint einmal, Test in drei Versionen.
Messung: drei Versionen seriell ~12 Minuten, Matrix parallel ~4 Minuten – grob 8 Minuten gespart pro Durchlauf.
Kapitel 4: Praxis und Fehlersuche
Konfiguration steht – hier eine Checkliste zu Sicherheit, Performance und typischen Fehlern.
Sicherheit
| Praxis | Erklärung | Beispiel |
|---|---|---|
| permissions explizit | Nicht auf Defaults verlassen | permissions: { contents: read } |
| Secrets für Secrets | Keine Keys im Klartext | ${{ secrets.API_KEY }} |
| Branches einschränken | CI nicht auf jedem Branch | branches: [main] |
| Actions per SHA pinnen | Tags sind veränderbar | actions/checkout@b4ffde65f46336ab88eb53be808477a39b6bc2b1 |
| timeout setzen | Hänger verbrauchen Minuten | timeout-minutes: 15 |
Action-Tags wie @v4 sind bequem, aber theoretisch umdeutbar. Produktion: SHA-Pin – Upgrade-Aufwand, mehr Sicherheit.
Performance
| Tipp | Effekt | Konfiguration |
|---|---|---|
| Dependency-Cache | oft >50 % bei Install | cache: 'npm' |
| npm ci | schneller, deterministisch | run: npm ci |
| timeout-minutes | kein Minuten-Fresser | timeout-minutes: 15 |
| Matrix parallel | Gesamtzeit oft −60 %+ | strategy.matrix |
| concurrency | nur letzter Build pro Branch | concurrency.group: ${{ github.ref }} |
concurrency: fünf schnelle Pushes → ohne Config fünf Builds; mit cancel-in-progress: true laufen nur die letzten.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Häufige Fehler
| Meldung | Ursache | Lösung |
|---|---|---|
Permission denied | zu wenig Rechte | permissions prüfen |
Cache not found | Key passt nicht | key, package-lock.json |
npm ERR! network | Timeout Registry | Timeout erhöhen oder Mirror |
Out of memory | Node-Heap zu klein | NODE_OPTIONS=--max_old_space_size=4096 |
EACCES permission denied | Dateirechte | chmod +x script.sh |
Error: Cannot find module | Install unvollständig | npm ci-Log prüfen |
Netzwerk: langsames npm – Mirror in .npmrc:
- name: Configure npm registry
run: echo "registry=https://registry.npmmirror.com" > .npmrc
Speicher:
env:
NODE_OPTIONS: --max_old_space_size=4096
Cache: erster Lauf ohne Cache normal; package-lock.json für npm ci; cache zum Paketmanager passend.
Fazit
Kernpunkte: eine YAML-Datei für CI; minimale permissions; Umgebungsvariablen in Ebenen; Cache halbiert Install oft; Matrix macht Mehrfachversionen einfach.
Template aus Kapitel 1 kopieren, Node-Version und Befehle anpassen – CI läuft. Erst starten, dann verfeinern. Matrix mit zwei Node-Versionen zeigt den Effekt paralleler grüner Häkchen.
Probleme mit GitHub Actions? Kommentieren Sie – häufige Fälle fließen in die Tabelle von Kapitel 4 ein.
GitHub Actions CI-Pipeline einrichten
Von null bis zur vollständigen CI-Pipeline mit automatischem Build und Test
⏱️ Estimated time: 30 min
- 1
Step 1: Workflow-Verzeichnis anlegen
Im Projektroot das Verzeichnis `.github/workflows/` erstellen – dort liegen alle Workflow-Dateien. - 2
Step 2: Basis-CI-Konfiguration schreiben
Datei `ci.yml` anlegen: Trigger (push/PR), Berechtigungen (Minimalprinzip), Job-Schritte (checkout, setup-node, install, test, build). - 3
Step 3: Dependency-Cache aktivieren
Beim Schritt `setup-node` den Parameter `cache: 'npm'` setzen – npm-Abhängigkeiten werden automatisch gecacht. - 4
Step 4: Matrix für Mehrfachversionen konfigurieren
`strategy.matrix` ergänzen und Node-Versionen angeben (z. B. [16, 18, 20]) für parallele Tests. - 5
Step 5: Committen und Build-Ergebnis prüfen
Konfiguration committen, nach GitHub pushen und auf der Actions-Seite Status und Logs kontrollieren.
FAQ
Wie hoch ist das monatliche Freikontingent bei GitHub Actions?
Auf welchen Branches soll die CI laufen?
Warum npm ci statt npm install in der CI?
Wie viel Zeit spart die Matrix-Strategie?
Warum greift der Cache manchmal nicht?
Wie nutze ich sensible Daten (API Keys, SSH-Schlüssel) in der CI?
8 Min. Lesezeit · Veröffentlicht am: 6. Apr. 2026 · Aktualisiert am: 9. Juli 2026
GitHub Actions Komplettleitfaden
Wenn du über die Suche hier gelandet bist, kommst du am schnellsten weiter, indem du zum vorherigen oder nächsten Beitrag dieser Serie springst.
Vorheriger
GitHub Actions Einstieg: YAML-Workflow-Grundlagen und Trigger-Konfiguration
GitHub Actions YAML-Workflow-Einstieg: name, on, jobs und steps im Detail, 8 Trigger-Konfigurationen, kopierbare YAML-Vorlagen und Fehler-Checkliste.
Teil 1 von 10
Nächster
GitHub Actions Cache-Strategie: CI/CD-Pipeline 5× beschleunigen
Praxisleitfaden zur GitHub Actions Cache-Strategie: vollständige Konfigurationsbeispiele von npm bis Docker, Best Practices für Cache-Keys und Performance-Vergleiche. Cache-Mechanismus beherrschen, CI/CD 5× schneller, Build-Kosten senken.
Teil 3 von 10
Ähnliche Beiträge
GitHub Actions Matrix-Build: Parallele Multi-Version-Tests in der Praxis

GitHub Actions Matrix-Build: Parallele Multi-Version-Tests in der Praxis
GitHub Actions Matrix-Build: Parallele Tests auf mehreren Plattformen und Versionen


Kommentare
Melde dich mit GitHub an, um einen Kommentar zu hinterlassen