GitHub Actions Workflow Lockfiles: Warum uses@SHA allein nicht genügt

Wer GitHub Actions mit vollständigen Commit-SHAs referenziert, fixiert den Quellcode an diesem Einstiegspunkt. Doch was passiert, wenn eine so fixierte Composite Action intern example-org/upload@v1 verwendet? Die äußere SHA bleibt gleich, während das untergeordnete Tag auf einen anderen Commit zeigen kann. Die Workflow-YAML allein verrät nicht, welche Drittanbieter-Actions letztlich ausgeführt werden.

Mit den Workflow Lockfiles in der Public Preview führt GitHub .github/workflows/actions.lock ein. Die Datei dokumentiert direkte und transitive Action-Abhängigkeiten einschließlich Commit und Repository-Identität.

Bereits alles auf uses@SHA gepinnt? Erst den Abhängigkeitsgraphen prüfen, dann eine Migration entscheiden. Der Mehrwert liegt in nachvollziehbaren transitiven Pins und der Prüfung der Repository-Identität, nicht im doppelten Fixieren derselben Action.

Ausgangslage im CIEmpfehlungBegründung
Wenige direkte Actions, alle mit vollständiger SHAErst inventarisieren, flächendeckende Migration verschiebenDer Zusatznutzen kann geringer als der Pflegeaufwand sein
Composite Actions referenzieren weitere Actions mit @v1 oder @mainEinen unkritischen Workflow pilotierenTransitive Abhängigkeiten werden sichtbar und fixiert
Mehrere Repositories verwenden einen Reusable WorkflowVerantwortung von Aufrufer und definiertem Workflow klärenDie internen Actions gehören zum Lockfile des aufgerufenen Repositories
Organization Allowed Actions oder SHA-Richtlinien sind aktivRichtlinien vor dem Piloten prüfenBeim Lockfile können die fixierten Commit-SHAs für die Freigabe maßgeblich sein

Die Fälle schließen sich nicht aus. Grundlage sind die GitHub-Dokumentation und der festgelegte Stand gh-actions-lock v0.2.0.

Der fixierte Einstiegspunkt ist nicht der gesamte Abhängigkeitsgraph

Nehmen wir einen hypothetischen Workflow ci.yml: Er referenziert example-org/build mit voller SHA. In dessen action.yml steht jedoch example-org/upload@v1. Die oberste Action bleibt unverändert, das untergeordnete Tag kann wandern.

AbhängigkeitDirekte SHA-FixierungWorkflow Lockfile
Externe Action im WorkflowFixiert diesen VerweisSpeichert Commit und Repository-ID
Weitere Actions innerhalb einer Composite ActionPinnt die inneren Tags nicht automatischErfasst transitive Action-Abhängigkeiten
Externer Reusable WorkflowFixiert den AufrufDer Aufrufer fixiert seinen Verweis; interne Actions verwaltet das definierende Repository
Gleicher Repository-Kontext mit uses: $/…Bindet an den laufenden Repository-CommitBereits inhärent fixiert; kein eigener Pin nötig
Downloads in run: oder veränderliche Container-TagsNicht abgedecktAuch nicht allein durch actions.lock geschützt

Diese Grenze ist entscheidend. Laut GitHub-Konzeptdokumentation deckt das Lockfile die Workflows ab, die im jeweiligen Repository definiert sind. Die Actions innerhalb eines externen Reusable Workflow werden durch das Lockfile seines definierenden Repositories verwaltet. Wer den Aufruf eines gemeinsamen Deployment-Workflows fixiert, hat damit nicht automatisch jede Action im anderen Repository geprüft.

Was tatsächlich in actions.lock steht

Unter workflows stehen die Workflows und ihre benötigten Pins. dependencies enthält unter anderem ref, commit, owner_id und repo_id; bei verschachtelten Actions kann außerdem uses auftauchen. Das folgende vollständige YAML stammt aus der fest verankerten offiziellen Parser-Testfixture benchV003. Es zeigt Schema v0.0.3. Die wiederholten a/b-SHAs sind synthetische Testwerte, keine produktiv erzeugten Pins.

version: v0.0.3
workflows:
  .github/workflows/ci.yml:
    - actions/checkout@v4
    - actions/setup-go@v5
    - actions/cache@v4
dependencies:
  actions/checkout@v4:
    hostname: github.com
    ref: v4
    commit: sha1-11bd71901bbe5b1630ceea73d27597364c9af683
    owner_id: 44036562
    repo_id: 197814629
  actions/setup-go@v5:
    hostname: github.com
    ref: v5
    commit: sha1-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    owner_id: 44036562
    repo_id: 249058325
  actions/cache@v4:
    hostname: github.com
    ref: v4
    commit: sha1-bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
    owner_id: 44036562
    repo_id: 251882839
    uses:
      - actions/checkout@v4

Die Fixture enthält ausdrücklich hostname: github.com. Bei Dateien, die für den Standardhost github.com erzeugt werden, kann dieses optionale Feld fehlen. Die uses-Beziehung innerhalb von dependencies und die Pin-Liste unter workflows sind unterschiedliche Sichten auf die Abhängigkeiten.

Auch der fixierte Go-Quellcode state_marshal.go serialisiert diese Felder:

a := file.Dependencies[k]
entry := &yaml.Node{Kind: yaml.MappingNode}
// Hostname-Zweig hier ausgelassen
if a.Ref != "" {
    addQuotedField(entry, "ref", a.Ref)
}
if a.Commit != "" {
    addQuotedField(entry, "commit", a.Commit)
}
addIntField(entry, "owner_id", a.OwnerID)
addIntField(entry, "repo_id", a.RepoID)

Die Commit-SHA benennt ein Git-Objekt; numerische Owner- und Repo-IDs identifizieren das Repository hinter einem potenziell veränderlichen Namen. Im älteren Konzeptbeispiel steht noch version: v0.0.2, während die Release-Notizen zu v0.2.0 und die Format-README v0.0.3 beschreiben. CLI-Version und Lockfile-Schema sind unabhängig zu betrachten.

Migration: zuerst den tatsächlichen Diff prüfen

Ich würde mit einem umkehrbaren Testbranch und einem unkritischen Workflow beginnen. Voraussetzung sind eine installierte, authentifizierte GitHub CLI und Leserechte für die betroffenen Repositories. Die Befehle verwenden bewusst die hier geprüfte Erweiterungsversion:

# Die geprüfte Erweiterungsversion installieren
gh extension install github/gh-actions-lock --pin v0.2.0
gh actions-lock .github/workflows/ci.yml

# Workflow, lokale Actions und neue Dateien prüfen
git status --short
git diff
cat .github/workflows/actions.lock

# Nur den Pilot-Workflow verifizieren
gh actions-lock --verify .github/workflows/ci.yml

Der Pfadparameter ist durch root.go, verify.go und die Tests des fixierten Quellstands gedeckt. Die gemeinsame actions.lock muss weiterhin gültig sein, aber die Prüfung einer einzelnen Datei registriert nicht automatisch alle übrigen Workflows.

Das Tool erzeugt nicht nur eine neue Datei. Ein semantisches Versions-Tag kann auf eine konkrete Version eingegrenzt werden; eine lokale Action mit gültiger action.yml kann von ./actions/build nach $/actions/build wechseln:

 steps:
-  - uses: ./actions/build
+  - uses: $/actions/build

$/ bindet den Verweis an den laufenden Commit des eigenen Repositories. Falsche lokale Pfade werden dadurch nicht repariert. Eine neue, noch unversionierte actions.lock erscheint zudem nicht in der normalen Ausgabe von git diff. Deshalb auch git status --short und den Dateiinhalt prüfen.

Die Organization-Richtlinie Allowed Actions ist ein weiterer möglicher Stolperstein. Bei Lockfile-Workflows erfolgt die Freigabe anhand der fixierten Commit-SHA. Eine bisherige Tag-Regel wie actions/checkout@v6 kann dann nicht mehr passen. Besser die konkret geprüften Commits zulassen als die Beschränkung für alle Drittanbieter-Actions aufzuheben.

Offline- und Online-Prüfung haben unterschiedliche Aufgaben:

gh actions-lock --verify-local .github/workflows/ci.yml
gh actions-lock --verify .github/workflows/ci.yml

--verify-local kontrolliert ohne Netzwerk, ob Referenzen im Lockfile erfasst sind. Die tatsächliche Repository-Identität wird dabei nicht online überprüft. Dafür dient --verify, etwa als PR-Gate. Erst nach der vollständigen Registrierung aller Workflows ist ein Aufruf ohne Dateipfad als Repository-weite Prüfung sinnvoll. Während eines einzelnen Piloten würden noch nicht registrierte Workflows oder ungenutzte Pins Fehler auslösen.

Zur Fehleranalyse hilft --json=valid,findings. Exit-Code 1 steht für blockierende Findings, 2 für Befehls-, I/O- oder Netzwerkfehler. Im festen Finding-Katalog stehen unter anderem not-pinned, stale, local-action, repo-replaced und unreachable-pin.

Ein begrenzter Pilot in fünf Schritten:

  1. Inventarisieren: direkte uses-Einträge, innere Composite Actions und externe Reusable Workflows erfassen. Die Eigentümer der aufgerufenen Workflows bestätigen die Zuständigkeit für ihre internen Pins.
  2. Auf dem Testbranch generieren: fixierte Version verwenden und Änderungen an Workflow, action.yml und actions.lock vergleichen.
  3. Richtlinien abgleichen: die fixierten Commits mit Allowed Actions vergleichen und alles über einen normalen PR überprüfen.
  4. Zweistufig prüfen: erst --verify-local, danach --verify. Bei not-pinned, stale oder local-action die lokalen Dateien prüfen; bei repo-replaced oder unreachable-pin Herkunft und Git-Historie untersuchen, bevor gemergt wird.
  5. Rückweg offenhalten: bei nicht lösbaren Parser- oder Policy-Problemen die Änderungen des Testbranches verwerfen. Eine Ausweitung erst nach einem stabilen Piloten vornehmen.

Abhängigkeiten aktualisieren: Sticky Pins und Release Cooldown

Welcher Commit beim ersten Onboarding gewählt wird, hängt vom ursprünglichen uses-Verweis und der Auflösung ab. Die Version v0.2.0 erzwingt keine pauschale Wartezeit von sieben Tagen. Ein positiver Wert cooldown.default-days für github-actions in .github/dependabot.yml hat Vorrang, danach folgt das benutzerspezifische cooldown_days. Ohne solche Vorgaben wird nicht nach Veröffentlichungsalter gefiltert; neue Tags unter drei Tagen erhalten nur einen nicht blockierenden fresh-tag-Hinweis. Siehe Konfigurationsauflösung und Hinweislogik. Entscheidend sind die erzeugten ref-, commit- und Workflow-Diffs.

Vorhandene Pins sind sticky: Ein erneutes gh actions-lock ersetzt nicht stillschweigend die gespeicherte SHA, nur weil upstream main oder v3 weitergewandert ist. Für eine bewusste Übernahme neuer Versionen wird gh actions-lock --relock verwendet und der Diff geprüft. Ist ein alter Commit nach einer Umschreibung der Git-Historie nicht mehr erreichbar, ist --relock --accept-moved eine eigenständige Vertrauensentscheidung und kein allgemeines Mittel gegen rote CI-Jobs.

Dependabot kann Lockfile-Einträge für bereits registrierte Workflows aktualisieren, registriert aber keine bisher unbekannten Workflows automatisch. GitHubs Enforcement-Anleitung empfiehlt einen begrenzten Test und eine CODEOWNERS-Prüfung für actions.lock, bevor Require lockfile organisationsweit aktiv wird. Plan und Berechtigungen müssen passen. Die fixierte README weist außerdem darauf hin, dass GitHub Enterprise Server (GHES) in dieser Vorschau noch nicht unterstützt wird; Enterprise Cloud ist eine andere Umgebung.

Ein Lockfile bestimmt, welcher Action-Code ausgeführt werden soll. Es bewertet weder dessen Sicherheit noch Downloads innerhalb von run:, veränderliche Images, Paketabhängigkeiten oder die Berechtigungen des CI-Tokens. Ein erfolgreicher Pilot macht beantwortbar: Welche inneren Actions wurden neu fixiert, wer hat ihre Repository-Identität geprüft, und wer pflegt die Pins in gemeinsam genutzten Reusable Workflows? Zur anderen Frage, warum ein Sicherheitshinweis nicht automatisch einen Merge verhindert, gibt es den GitHub-AI-Scan-Beitrag.


Hinweis zur Quellenlage und Zeit: GitHub stellte die Public Preview am 14. Oktober 2026 vor. Geprüft wurden der feste Quellstand gh-actions-lock v0.2.0 (d5dca22a06ff8590d50b41612038996800cfb336) und das Format-Repository (ac158834765237ee94c36606cfc7d87316aa49ab) am 18. Oktober. Das YAML ist ein Parser-Test mit synthetischen Digests. Es wurden keine echten Runner-, CLI-Migrations- oder Tag-Umleitungsversuche ausgeführt. Die Verfügbarkeit hängt vom Tarif und der Kontokonfiguration ab.