Start / Cheat Sheets

Cheat Sheet

GitHub Actions: Workflows und Pipelines — Cheat Sheet

Stand: · GitHub Actions in der Praxis

GitHub ActionsCI/CDReusable WorkflowsMatrix

Der Spickzettel zur ersten Hälfte des Seminars GitHub Actions in der Praxis: Wie eine Workflow-Datei aufgebaut ist, welcher Auslöser wann greift, wie Werte zwischen Schritten und Jobs wandern, wann ein Cache und wann ein Artefakt richtig ist und wie sich Schrittfolgen wiederverwenden lassen. Alles, was danach beim Ausrollen, Absichern und Betreiben passiert, steht auf dem zweiten Blatt: GitHub Actions: Betrieb und Lieferkette.

Maßgeblich für Schlüsselnamen und Versionsdetails ist die GitHub-Actions-Dokumentation; dieses Blatt trifft eine Auswahl — die Entscheidungsraster, die einen Versionssprung überleben.

Continuous Integration, Delivery und Deployment

StufeBauen und PrüfenAusrollen
Continuous Integrationautomatischvon Hand
Continuous Deliveryautomatischauf Knopfdruck
Continuous Deploymentautomatischautomatisch

Der Sprung zu Continuous Deployment ist keine technische Frage, sondern eine der Testabdeckung. Wer Continuous Delivery verspricht, das Ausrollen aber weiterhin aus einem Handbuch bedient, steht auf der ersten Stufe.

Modul: Continuous Integration und Delivery verstehen

Schlüssel eines Schritts

SchlüsselBedeutungBeispiel
usesfertige Action einbindenactions/checkout@v6
runKommando in der Shellnpm test
withEingaben an die Actionnode-version: 22
nameAnzeigename im LogTests ausführen
idReferenz für Outputsbuild

uses und run schließen sich in einem Schritt gegenseitig aus. Jeder Schritt startet in einer eigenen Shell — ein cd wirkt nicht im nächsten Schritt.

jobs:
  pruefen:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v7
        with:
          node-version: 22
      - run: npm ci
      - run: npm test

npm ci statt npm install — es installiert exakt die Stände aus dem Lockfile und schlägt bei Abweichung fehl.

Modul: Den ersten Workflow erstellen

Auslöser und Filter

EreignisStartet beiTypisch für
pushCommits auf Branch oder TagBauen, Release
pull_requestEröffnen und AktualisierenPrüfungen vor dem Merge
workflow_dispatchKlick oder API-AufrufDeployment, Wartung
scheduleZeitplan in Cron-SyntaxNachtläufe, Aufräumen
releaseVeröffentlichter ReleaseArtefakte publizieren

Zeitgesteuerte Läufe starten nicht auf die Minute genau, rechnen in UTC und pausieren in inaktiven Repositories. workflow_dispatch wird erst sichtbar, wenn die Datei auf dem Standardbranch liegt.

on:
  push:
    branches: [main]
    tags: ['v*']
  pull_request:
    branches: [main]
    paths-ignore:
      - 'docs/**'
      - '**.md'

paths und paths-ignore schließen sich gegenseitig aus. branches greift nicht bei Tags und tags nicht bei Branches — ein Tag-Push löst sonst nichts aus. Wer Pfade filtert, muss den Required Status Check mitdenken: ausgelassen ist nicht grün.

Eingaben eines manuellen Laufs nehmen die Typen string, boolean, number, choice und environment an — choice statt Freitext erspart die Prüfung im Workflow.

Modul: Ereignisse, Filter und Bedingungen

Bedingungen und Läufe aus Forks

jobs:
  deploy:
    if: github.ref == 'refs/heads/main'
    steps:
      - run: ./deploy.sh
      - name: Bericht sichern
        if: always()
        run: ./bericht.sh

In if steht der Ausdruck ohne geschweifte Klammern. Eine als Zeichenkette geschriebene Bedingung ist immer wahr. failure() und cancelled() sind verschiedene Fälle, always() deckt beide ab.

Bei pull_request aus einem Fork bekommt der Lauf nur Leserechte und keine Secrets. pull_request_target läuft dagegen im Kontext des Zielrepositories — mit Secrets und Schreibrechten. Wer darin den Fork-Code auscheckt und ausführt, gibt das Repository preis. Sichere Reihenfolge: prüfen ohne Secrets, danach in einem getrennten Lauf veröffentlichen.

Modul: Ereignisse, Filter und Bedingungen

Kontexte und Outputs

KontextEnthältBeispiel
githubLauf und Ereignisgithub.ref, github.sha
envgesetzte Variablenenv.REGISTRY
varsKonfigurationswertevars.NODE_VERSION
secretsGeheimnissesecrets.GITHUB_TOKEN
needsOutputs vorheriger Jobsneeds.build.outputs.version
matrixWerte der aktuellen Kombinationmatrix.node

Kontexte sind nicht überall verfügbar — auf Workflow-Ebene stehen nur github, inputs und vars bereit.

    steps:
      - id: version
        run: |
          V=$(node -p "require('./package.json').version")
          echo "wert=$V" >> "$GITHUB_OUTPUT"
    outputs:
      version: ${{ steps.version.outputs.wert }}

Outputs sind auf 1 MB je Job begrenzt; alles Größere gehört in ein Artefakt. Der Folgejob sieht sie nur, wenn er den Vorgänger unter needs führt. Die drei Wege im Vergleich: Outputs für einzelne Werte wie Version, Digest oder Image-Tag; Artefakte für Dateien, die ein späterer Job unverändert braucht; Caches für nichts davon — sie dürfen jederzeit fehlen. Werte aus GITHUB_ENV gelten nur innerhalb desselben Jobs.

echo "::warning file=src/plan.ts,line=42::Fehlender Fall"
echo "::add-mask::$TOKEN"
echo "### Testlauf Beetkarte" >> $GITHUB_STEP_SUMMARY

Annotationen mit file und line erscheinen direkt an der betroffenen Zeile im Pull Request. add-mask muss vor der ersten Ausgabe stehen, sonst schützt es zu spät.

Modul: Daten zwischen Schritten und Jobs austauschen

Matrix und Nebenläufigkeit

SchlüsselWirkungWann sinnvoll
includeergänzt Kombinationen oder WerteSonderfall mit Extra-Flag
excludeentfernt Kombinationenunnötige Paarung sparen
fail-fastbricht alle Jobs beim ersten Fehler abschnelles Signal
max-parallelbegrenzt gleichzeitige Jobsknappe Runner-Kapazität

fail-fast steht standardmäßig auf true — für eine vollständige Fehlerübersicht auf false setzen. Die Matrix wächst schneller als gedacht: drei Listen zu je vier Werten ergeben 64 Jobs.

concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true
concurrency:
  group: deploy-produktion
  queue: max

Zwei Muster, zwei Absichten: Prüfläufe am Branch dürfen abgebrochen werden, nur der letzte Stand zählt. Deployments dürfen es nicht — sonst bleibt eine Umgebung halbfertig; dort wartet queue: max (bis zu 100 Läufe). Der Gruppenschlüssel entscheidet über die Wirkung: zu grob blockiert, zu fein schützt nicht. Enthält er den Lauf selbst, ist er immer eindeutig und die Gruppe wirkt nie. timeout-minutes je Job verhindert, dass ein hängender Lauf die Gruppe blockiert.

Innerhalb eines Jobs steuern fünf Schlüssel parallele Schritte: background startet einen Schritt und läuft weiter, wait wartet auf benannte Hintergrundschritte, wait-all auf alle vorherigen, cancel beendet einen Hintergrundschritt, parallel führt eine Gruppe gemeinsam aus. Die Ausgabe eines Hintergrundschritts erscheint erst, wenn er abgeschlossen ist — und background wartet nicht auf Bereitschaft, nur auf den Start.

Modul: Jobs parallelisieren und Build-Zeiten optimieren

Cache oder Artefakt

CacheArtefakt
ZweckLaufzeit sparenErgebnis weitergeben
Verlässlichkeitdarf fehlenmuss da sein
SichtbarkeitBranch und Elternbranchim ganzen Lauf, danach Download
Aufbewahrung7 Tage ohne Zugriffkonfigurierbar, Standard 90 Tage
Grenze10 GB je RepositorySpeicherkontingent

Ist das Kontingent erschöpft, löscht GitHub die am längsten nicht genutzten Caches zuerst.

- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: npm-${{ hashFiles('package-lock.json') }}
    restore-keys: npm-

Der Key trägt den Lockfile-Hash, sonst bleiben alte Abhängigkeiten ewig liegen; in einer Matrix gehört zusätzlich runner.os hinein. Gecacht wird das Verzeichnis des Paketmanagers, nicht node_modules — plattformabhängige Pakete brechen sonst.

- uses: actions/upload-artifact@v4
  with:
    name: beetkarte-bundle
    path: dist/
    retention-days: 7
- uses: actions/download-artifact@v4
  with:
    name: beetkarte-bundle

Als Artefakt lohnen das gebaute Bundle (damit Test und Deployment dieselbe Datei verwenden), Testberichte und Coverage-Daten sowie Protokolle fehlgeschlagener Oberflächentests — nicht aber Zwischenstände, die schneller neu gebaut als übertragen sind.

Modul: Abhängigkeiten, Caches und Artefakte

Testumgebung in der Pipeline

Service ContainerTestcontainers
Definiert inWorkflow-DateiTestcode
Lokal gleichnein, dort andersja, identisch
Lebensdauerganzer Jobje Testlauf
Version steuertWorkflow-AutorEntwicklerteam

Testcontainers hält Test und Umgebung zusammen — der Workflow muss dann nur Docker bereitstellen.

    services:
      db:
        image: postgres:18
        env:
          POSTGRES_PASSWORD: test
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready

Ohne Health-Check startet der Test womöglich, bevor die Datenbank Verbindungen annimmt.

Modul: Tests und Qualitätsprüfungen automatisieren

Reusable Workflow oder Composite Action

Reusable WorkflowComposite Action
Ersetzt einen oder mehrere JobsErsetzt mehrere Schritte
Liegt in .github/workflowsLiegt in beliebigem Verzeichnis
Eigene Runner je JobLäuft auf dem Runner des Aufrufers
Kann Environments und Matrix nutzenKein eigener Runner, keine Matrix
jobs:
  ci:
    uses: gartenwerk/cicd/.github/workflows/ci.yml@v2
    with:
      node-version: '22'
    secrets: inherit

Der Aufruf steht bei den Jobs, nicht bei den Schritten. secrets: inherit gilt nur innerhalb derselben Organisation, sonst wird jedes Secret einzeln übergeben. Bis zu zehn Ebenen lassen sich verketten, Schleifen nicht. Berechtigungen lassen sich in der Kette senken, aber niemals anheben, und der Schlüssel environment steht in workflow_call nicht zur Verfügung. Inputs nehmen dort string, number und boolean an.

runs:
  using: composite
  steps:
    - uses: actions/setup-node@v7
      with:
        node-version: ${{ inputs.node-version }}
        cache: npm
    - run: npm ci
      shell: bash

Ein run-Schritt ohne shell lässt die Action gar nicht erst laden. Outputs einer Composite Action brauchen zusätzlich ein value mit dem Verweis auf den Schritt. Und in beiden Fällen gilt: Der Aufruf zeigt auf einen Tag, nicht auf main — sonst bricht eine fremde Änderung alle Repositories gleichzeitig.

Modul: Workflows und Actions wiederverwenden

Bauarten einer eigenen Action

BauartGeeignet fürPreis
Skript im Workfloweinmalige Logikkeine Wiederverwendung
CompositeSchrittfolgen ohne eigene Logiknur was der Runner kennt
JavaScriptLogik, API-Aufrufe, FehlerfälleBuild und Abhängigkeiten
Containerfremde Werkzeuge, feste Umgebungnur Linux, langsamer Start

Die Reihenfolge ist auch die Empfehlung — die einfachste Bauart, die trägt, gewinnt. Inputs erreichen den Code als Umgebungsvariablen mit dem Präfix INPUT und dem Namen in Großbuchstaben.

runs:
  using: composite
  steps:
    - shell: bash
      run: |
        test -f "$INPUT_MANIFEST" || {
          echo "::error::Manifest fehlt"; exit 1; }

Ohne exit 1 gilt der Schritt als erfolgreich — auch wenn die Fehlermeldung im Log steht.

Modul: Eigene Actions entwickeln

Typische Fallen

  • Datei am falschen Ort. .github/workflow ohne s wird nie ausgeführt; ein Tabulator in der Einrückung lässt den Lauf gar nicht erst starten.
  • Checkout vergessen. Ohne actions/checkout findet npm keine package.json.
  • Doppelte Läufe. push und pull_request auf demselben Branch lassen jeden Commit zweimal laufen.
  • Muster mit zwei Sternen. docs/** trifft nicht docs selbst.
  • Output ohne id. Ein Schritt ohne id liefert keinen adressierbaren Wert; mehrzeilige Werte brauchen einen Begrenzer.
  • Wert aus dem Log zurücklesen. Werte gehören über GITHUB_OUTPUT weiter, nicht über ein echo und die Log-Auswertung.
  • Secret im Job Summary. Was dort landet, ist dauerhaft sichtbar — vor jeder Ausgabe prüfen, ob ein Geheimnis enthalten sein könnte.
  • Cache als Voraussetzung. Ein Lauf, der ohne Cache-Treffer scheitert, ist kaputt; der Cache darf jederzeit fehlen.
  • Artefakt mit .env. Damit ist jede Zugangsinformation herunterladbar; in einer Matrix kollidieren zudem gleiche Artefaktnamen.
  • Required Check zeigt ins Leere. Ein umbenannter Job oder eine anders gebildete Matrix lässt jeden Pull Request hängen.
  • Neu bauen statt weiterreichen. Baut der Testjob selbst neu, prüft er etwas anderes als das, was ausgeliefert wird.
  • Der Linter mit Beruhigungsflag. Ein Flag, das Fehler zu Warnungen macht, oder ein continue-on-error entschärft die Prüfung dauerhaft.

Zum Seminar GitHub Actions in der Praxis