Entwickler-Workflows mit GitHub Actions automatisieren
Praktische GitHub-Actions-Muster für CI/CD, Code-Qualitätsprüfungen, Dependency-Updates und Release-Workflows — mit wiederverwendbaren Workflows.

GitHub Actions begann als einfaches CI-Tool, ist aber inzwischen eine vollwertige Plattform zur Workflow-Automatisierung. Über das Ausführen von Tests hinaus nutzen Teams es, um Codequalität durchzusetzen, Releases zu automatisieren, Dependencies aktuell zu halten und Multi-Service-Deployments zu koordinieren. Entscheidend ist, die Muster zu verstehen, die Workflows auch beim Wachsen wartbar halten.
Die meisten Teams starten mit einer einzigen Workflow-Datei, die alles erledigt. Das funktioniert — bis es nicht mehr funktioniert. Dieser Guide behandelt die Muster, die skalieren.
Basis-CI-Pipeline
Jedes Repository braucht eine CI-Pipeline, die bei Pull Requests läuft. Fang einfach an und füge Komplexität nur hinzu, wenn sie nötig ist.
# .github/workflows/ci.yml
name: CI
on:
pull_request:
branches: [main]
push:
branches: [main]
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:
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 test -- --coverage
- uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/Lint und Test laufen parallel — schlägt das Linting fehl, siehst du das sofort, ohne auf die Tests zu warten. Beide Jobs cachen node_modules über den eingebauten Cache der setup-node-Action.
Matrix-Builds für Tests über mehrere Umgebungen
Teste mit Matrix-Strategien über mehrere Node-Versionen, Betriebssysteme oder Datenbankversionen hinweg.
# ❌ Separate jobs for each environment — repetitive and hard to maintain
jobs:
test-node-18:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- run: npm ci && npm test
test-node-20:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci && npm test# ✅ Matrix strategy — one job definition, multiple environments
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node-version: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
fail-fast: false # Don't cancel other jobs if one fails
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm testfail-fast: false ist wichtig — ohne diese Option bricht ein Fehler in einer Kombination alle laufenden Jobs ab. Du willst alle Fehler auf einmal sehen, nicht einen nach dem anderen beheben.
Wiederverwendbare Workflows
Wenn mehrere Repositories dieselbe CI-Pipeline brauchen, verteilt sich dupliziertes YAML über die Repos und läuft auseinander. Wiederverwendbare Workflows lösen dieses Problem.
# .github/workflows/reusable-node-ci.yml (in a shared repository)
name: Reusable Node CI
on:
workflow_call:
inputs:
node-version:
required: false
type: string
default: '20'
run-e2e:
required: false
type: boolean
default: false
secrets:
NPM_TOKEN:
required: false
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: 'npm'
registry-url: 'https://registry.npmjs.org'
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- run: npm ci
- run: npm run build
- run: npm test
e2e:
if: ${{ inputs.run-e2e }}
runs-on: ubuntu-latest
needs: build-and-test
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: 'npm'
- run: npm ci
- run: npx playwright install --with-deps
- run: npm run test:e2e# .github/workflows/ci.yml (in consuming repositories)
name: CI
on:
pull_request:
branches: [main]
jobs:
ci:
uses: my-org/shared-workflows/.github/workflows/reusable-node-ci.yml@main
with:
node-version: '20'
run-e2e: true
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}Änderungen am gemeinsamen Workflow werden an alle Repositories weitergegeben, die ihn referenzieren. Pinne ihn in Produktions-Repos für Stabilität auf einen bestimmten SHA oder Tag.
Automatisierter Release-Workflow
Automatisiere Version-Bumps und Changelog-Generierung auf Basis von Conventional Commits.
# .github/workflows/release.yml
name: Release
on:
push:
branches: [main]
permissions:
contents: write
pull-requests: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Need full history for changelog
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm run build
- run: npm test
- name: Determine version bump
id: version
run: |
# Check commit messages since last tag
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
COMMITS=$(git log ${LAST_TAG}..HEAD --pretty=format:"%s")
if echo "$COMMITS" | grep -q "^feat!:\|^BREAKING CHANGE:"; then
echo "bump=major" >> "$GITHUB_OUTPUT"
elif echo "$COMMITS" | grep -q "^feat:"; then
echo "bump=minor" >> "$GITHUB_OUTPUT"
else
echo "bump=patch" >> "$GITHUB_OUTPUT"
fi
- name: Bump version and create tag
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
npm version ${{ steps.version.outputs.bump }} -m "chore: release v%s"
git push --follow-tags
- name: Publish to npm
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}Bedingte Workflows mit Pfad-Filtern
Große Monorepos sollten nicht bei jeder Änderung alle Checks ausführen. Pfad-Filter sorgen dafür, dass nur relevante Workflows ausgelöst werden.
# ❌ Every PR runs the full pipeline regardless of what changed
on:
pull_request:
branches: [main]# ✅ Only run when relevant files change
on:
pull_request:
branches: [main]
paths:
- 'src/**'
- 'package.json'
- 'package-lock.json'
- '.github/workflows/ci.yml'
# Also useful: ignore paths
on:
pull_request:
branches: [main]
paths-ignore:
- 'docs/**'
- '*.md'
- '.vscode/**'Verwende für Monorepo-Services separate Workflow-Dateien mit Pfad-Filtern pro Service. Eine Änderung an services/auth/** löst nur die Pipeline des Auth-Services aus.
Caching und Performance
CI-Geschwindigkeit wirkt sich direkt auf die Entwicklerproduktivität aus. Cache aggressiv und parallelisiere alles, was möglich ist.
jobs:
install:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
# Cache the entire node_modules for downstream jobs
- uses: actions/cache/save@v4
with:
path: node_modules
key: modules-${{ hashFiles('package-lock.json') }}
lint:
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
with:
path: node_modules
key: modules-${{ hashFiles('package-lock.json') }}
- run: npm run lint
test-unit:
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
with:
path: node_modules
key: modules-${{ hashFiles('package-lock.json') }}
- run: npm run test:unit
test-integration:
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
with:
path: node_modules
key: modules-${{ hashFiles('package-lock.json') }}
- run: npm run test:integrationEinmal installieren, dann parallel auf Lint, Unit-Tests und Integrationstests verteilen. Die Aufteilung in cache/save und cache/restore vermeidet, die Dependencies dreimal herunterzuladen.
Wichtigste Erkenntnisse
- Trenne Zuständigkeiten in parallele Jobs — Lint, Test und Build sollten parallel laufen, nicht sequenziell
- Nutze Matrix-Builds für Tests über mehrere Umgebungen und setze
fail-fast: false, um alle Fehler zu sehen - Extrahiere wiederverwendbare Workflows, wenn mehrere Repos dieselbe Pipeline-Logik teilen
- Nutze Pfad-Filter, um in Monorepos keine irrelevanten Workflows auszuführen
- Cache aggressiv — installiere Dependencies einmal und teile sie über den Cache zwischen parallelen Jobs
- Automatisiere Releases mit Conventional Commits und Version-Bump-Workflows


