Start / Cheat Sheets

Cheat Sheet

GitHub Actions: Betrieb und Lieferkette — Cheat Sheet

Stand: · GitHub Actions in der Praxis

GitHub ActionsOIDCSupply ChainDeployment

Der Spickzettel zur zweiten Hälfte des Seminars GitHub Actions in der Praxis: Welcher Runner wofür taugt, wie ein Image benannt und veröffentlicht wird, wo ein Geheimnis hingehört, wie OIDC gespeicherte Zugangsschlüssel ersetzt und woran die Herkunft eines Artefakts nachweisbar wird. Alles, was vorher in der Workflow-Datei steht, findet sich auf dem ersten Blatt: GitHub Actions: Workflows und Pipelines.

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

Runner: gehostet oder selbst betrieben

GitHub-hostedself-hosted
Bereitstellungvon GitHub, frisch je Jobselbst betrieben
Umgebungvorinstalliert, immer sauberfrei, aber selbst gepflegt
AbrechnungMinuten, öffentlich freieigene Infrastruktur
Zugangnur über das Internetauch ins interne Netz

Für öffentliche Repositories rät GitHub von self-hosted Runnern ab — fremder Code auf eigener Hardware.

Plattformöffentliche Reposprivate Repos
Linux4 CPUs, 16 GB RAM2 CPUs, 8 GB RAM
Windows4 CPUs, 16 GB RAM2 CPUs, 8 GB RAM
macOS ARM3 CPUs, 7 GB RAMgleiche Ausstattung

Alle Standard-Runner bringen 14 GB SSD mit. Larger Runners lohnen für mehr CPU, Speicher und Plattenplatz, für statische IP-Adressen und für ARM- oder GPU-Zielarchitekturen — sie kosten mehr je Minute, der Gewinn muss also an der Laufzeit messbar sein. Ein fehlender Cache wird davon nicht besser.

Module: Runner, Administration und Skalierung · Continuous Integration und Delivery verstehen

Persistent oder ephemer

persistenter Runnerephemerer Runner
Lebensdauerdauerhaftein Job
Rückständebleiben liegenverschwinden
Startzeitsofort verfügbarAufbau je Job
Eignungvertrauenswürdige Repossensible Workloads

Just-in-Time-Runner registrieren sich für genau einen Job und werden danach verworfen. Runner Groups begrenzen, welche Repositories eine Maschine überhaupt benutzen dürfen; ohne sie steht sie der ganzen Organisation offen.

Modul: GitHub Actions sicher betreiben

Image-Tags und Releases

TagEntsteht ausTaugt für
latestletzter Stand von mainlokales Ausprobieren
2.4.1Git-Tag der VersionProduktion, Rollback
main-a1b2c3dBranch und CommitFehlersuche, Staging
pr-482Pull-Request-NummerVorschauumgebung

Für ein Deployment zählt am Ende der Digest — Tags lassen sich verschieben, ein Digest nicht.

permissions:
  contents: read
  packages: write
steps:
  - uses: docker/login-action@v3
    with:
      registry: ghcr.io
      username: ${{ github.actor }}
      password: ${{ secrets.GITHUB_TOKEN }}
  - id: meta
    uses: docker/metadata-action@v5
    with:
      images: ghcr.io/${{ github.repository }}
  - id: push
    uses: docker/build-push-action@v6
    with:
      push: true
      tags: ${{ steps.meta.outputs.tags }}
      labels: ${{ steps.meta.outputs.labels }}

Ohne packages: write scheitert erst der Push — die Anmeldung selbst gelingt noch. Der Push-Schritt liefert unter outputs.digest den Digest, an dem später die Attestation hängt. Ein Release entsteht aus einem Tag, nicht aus einem Branch, und enthält Versionsnummer, Release Notes aus Sicht der Nutzenden, die installierbaren Artefakte und den Verweis auf das zugehörige Image.

Modul: Container-Images, Packages und Releases

Environments und Schutzregeln

RegelWirkungGrenze
Required Reviewerswartet auf Freigabebis zu 6 Personen oder Teams
Wait Timerverzögert den Startin Minuten festgelegt
Deployment Branchesnur genannte Branches und TagsMuster je Umgebung
Custom RulesPrüfung durch eine GitHub AppApp muss installiert sein

Eine Freigabe genügt, auch wenn mehrere Prüfende eingetragen sind; Selbstfreigabe lässt sich unterbinden.

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: produktion
      url: https://beetkarte.example
    steps:
      - run: ./rollout.sh
        env:
          TOKEN: ${{ secrets.DEPLOY_TOKEN }}

Denselben Secret-Namen kann jedes Environment mit einem eigenen Wert belegen — der Workflow bleibt gleich. Der Weg zur Produktion führt vom Merge auf main über ein automatisches Staging und die Freigabe zur Produktion; die Freigabe wird an der Umgebung geregelt, nicht im Workflow verhandelt.

Modul: Deployments und Environments

Wo ein Wert hingehört

OrtSichtbar fürTypischer Inhalt
Organization Secretausgewählte Repositoriesgemeinsamer Registry-Zugang
Repository Secretalle Workflows des ReposDienstschlüssel des Projekts
Environment SecretJobs nach erfüllten RegelnProduktionszugang
Variablealle, im KlartextRegistry-Name, Node-Version

Strukturierte Werte wie JSON gehören nie in ein Secret — die Maskierung greift dort nicht zuverlässig, und sie ist ohnehin eine Notbremse, kein Schutzkonzept. Ein Personal Access Token hängt an einer Person und verschwindet mit ihr; eine GitHub App hat eigene, fein einstellbare Rechte, überlebt Personalwechsel und stellt kurzlebige Token je Lauf aus. Für alles innerhalb des Repositories genügt ohnehin das GITHUB_TOKEN.

permissions: {}
jobs:
  veroeffentlichen:
    permissions:
      contents: read
      packages: write
      id-token: write

Grundsatz oben, Ausnahme am Job: Rechte am einzelnen Job halten den Schaden lokal. Ein Token mit Schreibrecht auf contents kann den Workflow selbst verändern. Seit September 2026 gibt es zusätzlich vulnerability-alerts für den Zugriff auf Dependabot-Meldungen.

Modul: Secrets, Tokens und OIDC

OIDC statt gespeicherter Schlüssel

permissions:
  id-token: write
  contents: read
steps:
  - uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: ${{ vars.DEPLOY_ROLE_ARN }}
      aws-region: eu-central-1

Ohne id-token: write kann der Job das OIDC-Token gar nicht erst anfordern — ein Fehler, der leicht für ein Problem der Cloud-Rolle gehalten wird.

Die Vertrauensbeziehung eng schneiden: Der Claim sub bindet den Zugang an Repository und Branch oder Environment, etwa repo:gartenwerk/beetkarte:ref:refs/heads/main. Für Produktion an das Environment binden, nicht an den Branch allein — ein zu weit gefasster Claim erlaubt jedem Fork-Branch den Zugriff auf die Cloud. Und nach dem Umstieg den alten Zugangsschlüssel widerrufen, nicht nur unbenutzt liegen lassen.

Modul: Secrets, Tokens und OIDC

Herkunft nachweisen: Attestations und SBOM

permissions:
  id-token: write
  attestations: write
  packages: write
- uses: actions/attest@v4
  with:
    subject-name: ghcr.io/${{ github.repository }}
    subject-digest: ${{ steps.push.outputs.digest }}
    push-to-registry: true

Der Nachweis hängt am Digest, nicht am Tag — deshalb bleibt er gültig, wenn ein Tag verschoben wird. Er belegt, welcher Workflow aus welchem Commit dieses Artefakt gebaut hat; er verhindert nicht, dass ein Build fehlerhaften Code enthält. Sein Wert bemisst sich an der Absicherung des Workflows, der ihn ausstellt.

gh attestation verify ./dist/beetkarte.tgz \
  -R gartenwerk/beetkarte
gh attestation verify \
  oci://ghcr.io/gartenwerk/beetkarte:2.4.1 \
  -R gartenwerk/beetkarte

Schlägt die Prüfung fehl, endet der Befehl mit einem Fehler — im Deployment-Job hält das den Lauf an, sofern kein continue-on-error daneben steht. Die SBOM entsteht beim Build, wo die tatsächlichen Stände bekannt sind; sie beantwortet bei einer neuen Schwachstelle ohne Suche, welche Stände betroffen sind. Die Signatur- und Transparenzinfrastruktur dahinter stellt Sigstore.

Modul: Software Supply Chain und Artifact Attestations

Governance und Kennzahlen

actions/checkout@v6
gartenwerk/*
!gartenwerk/experiment@*
gartenwerk/cicd/.github/workflows/ci.yml@v2

So sieht eine Auswahlliste erlaubter Actions aus; lokale Actions und Reusable Workflows des eigenen Repositories sind immer erlaubt. Governance muss vier Fragen beantworten: welche fremden Actions in die Pipelines dürfen, welche Standardrechte das GITHUB_TOKEN in neuen Repositories bekommt, wer Workflows von Fork-Beiträgen freigibt und welche Vorlage neue Projekte als Golden Path erhalten.

KennzahlWarnzeichenErste Maßnahme
Laufzeit bis Rückmeldungüber 15 MinutenPrüfungen aufteilen
Wartezeit auf Runnersteigt zu StoßzeitenKapazität, Läufe filtern
Fehlerquote ohne Codefehlerüber 5 Prozentinstabile Tests isolieren
Minuten je Wochewächst ohne neue Projektedoppelte Läufe abstellen

Ohne Ausgangsmessung lässt sich später nicht belegen, ob eine Änderung geholfen hat.

Modul: Governance, Monitoring und KI-Unterstützung

Typische Fallen

  • Ereigniswert direkt interpoliert. ${{ github.event.issue.title }} in einem run wird zum Kommando; der Wert gehört über env als Daten in den Schritt.
  • Fork-Code mit Secrets ausgeführt. pull_request_target plus Checkout des Beitrags gibt das Repository preis.
  • Action folgt einem Branch. Ohne SHA-Pin landet ein fremder Commit ungeprüft in der Pipeline — und ein gepinnter SHA, den nie jemand aktualisiert, hält Sicherheitskorrekturen draußen.
  • write-all als Reparatur. Gesetzt, weil ein Schritt scheiterte; danach erbt jeder Job alles. Entfernte Schritte lassen ihre Rechte zurück.
  • Produktionszugang als Repository-Secret. Damit steht er jedem Workflow offen, statt an der Umgebung zu hängen.
  • Staging auf der Produktionsdatenbank. Zwei Umgebungen, ein Datenbestand — die Trennung existiert dann nur auf dem Papier.
  • Environment ohne Schutzregel. Vorhanden, aber ohne Reviewer, Branch-Muster oder Timer — die Freigabe ist damit reine Dekoration.
  • Rollback nie erprobt. Beschrieben ist er, ausgeführt nicht; ein Tag, der inzwischen auf einen anderen Stand zeigt, macht ihn wertlos.
  • Deployment baut neu. Statt das geprüfte Image zu ziehen, entsteht ein zweites Artefakt — geprüft wurde dann etwas anderes als ausgeliefert wird.
  • Nur latest am Image. Später weiß niemand, welcher Commit darin steckt.
  • Attestation vor dem Push. Sie bezieht sich dann auf einen anderen Digest; ebenso wertlos ist ein Nachweis, den nie jemand prüft.
  • Runner im Produktionsnetz. Er erreicht Systeme, die kein Build braucht — und ein Job hinterlässt Zugangsdaten, die der nächste findet.
  • KI-Vorschlag ungeprüft übernommen. Erfundene Actions sehen plausibel aus, und write-all funktioniert immer; grün heißt nicht geprüft.

Zum Seminar GitHub Actions in der Praxis