Skip to content
chornous.dev

Type two or more letters. Esc closes.

Index of sheets
Theme

Sheet 03 · Writing

All notes

GitHub Actions gets lockfiles: gh actions-lock pins every action, including transitive ones, to a commit

GitHub put workflow dependency lockfiles into public preview on October 14, 2026. The gh actions-lock CLI extension writes .github/workflows/actions.lock, runners re-check each pin at job start, and a Require lockfile policy lets admins enforce it.

Pl. 92 · section drawing generated from the slug “github-actions-workflow-lockfiles”

GitHub announced workflow dependency lockfiles for Actions in public preview on October 14, 2026, for Enterprise Cloud (with and without data residency), Team and Free plans. The tool behind it is gh actions-lock, a GitHub CLI extension that writes .github/workflows/actions.lock. A companion Require lockfile policy, also in preview, lets enterprise, organization or repository admins make the file mandatory.

uses: actions/checkout@v4 resolves a tag at run time. Anyone with push access to that action's repository can move the tag, and your next run executes whatever it points at. Teams have pinned full commit SHAs by hand for years to avoid that. Hand-pinning covers the actions you name and misses the ones they call. The lockfile records direct dependencies, transitive ones and reusable workflows.

Set it up

gh extension install github/gh-actions-lock

# From the repository root: pin resolvable actions and write the lockfile
gh actions-lock

git add .github/workflows/actions.lock
git commit -m "ci: add actions lockfile"

The command scans .github/workflows/, resolves each reference to a SHA and updates actions.lock. You onboard one workflow at a time. Run it again whenever a workflow adds or removes a uses line. A run over the whole directory also prunes entries for workflows you deleted. A run scoped to one workflow doesn't prune.

The extension is pre-1.0. The README warns that the lockfile format, flags and behavior can change between releases, so pin the extension version in CI too.

What the runner checks

Once a workflow has entries in the lockfile, its runs use the recorded commits even after a tag or branch moves. At job start, the runner re-checks the locked pins, transitive ones included:

  • the repository still has the same identity, with no rename or transfer
  • the commit still exists, and lives on the branch or in the history of the ref it was locked under
  • full-version tags still point at the pinned commit

Any failed check blocks the run. The branch-history check makes impostor-commit attacks harder, where someone pushes a commit to a fork and references it by SHA through the parent repository.

Flags for CI and upgrades

gh actions-lock modes
CommandWrites?Use it for
gh actions-lockyesonboarding, and after adding or removing actions
gh actions-lock --verifynoCI check against the network, confirms locked commits sit in their refs
gh actions-lock --verify-localnooffline check that each ref has an entry; it doesn't judge the entries
gh actions-lock --relockyesre-resolve refs that moved for a legitimate reason
gh actions-lock --relock --accept-movedyesalso re-resolve pins whose commit left the ref

Use --verify in CI. --verify-local runs faster and offline, but it proves no more than that the file is complete. A run that hits an error it can't fix changes nothing, neither the workflows nor the lockfile.

--accept-moved deserves a pause before you type it. A commit that vanished from its tag's history is the exact event the lockfile exists to catch. Find out why the maintainer moved it first.

Local actions get a new syntax

Workflows in the lockfile can't use ./ local-path actions. The extension rewrites same-repository composite references to a $/ prefix on fix runs, unless you pass --no-migrate-local-actions:

steps:
  - uses: $/actions/my-action          # same-repo action, pinned to the running commit
jobs:
  call:
    uses: $/.github/workflows/reusable.yml  # same-repo reusable workflow

A $/ reference resolves to the commit that's running, so it needs no lockfile entry. A trailing ref such as $/actions/my-action@v1 fails. The README calls the local-path gap short-term.

Limits

GitHub Enterprise Server isn't supported. Locking proves which code runs. GitHub's announcement says it doesn't prove that code is safe, so review an action before you lock it. Support for the extension is best-effort, through GitHub issues.

This week

  1. Pick one repository with a deploy workflow, run gh actions-lock, and commit actions.lock.
  2. Add gh actions-lock --verify as a required check so a pull request can't add an unlocked uses line.
  3. Grep your workflows for uses: ./ and decide whether to accept the $/ migration or wait for local-path support.
  4. Hold off on the Require lockfile policy at the organization level until a few repositories have run with the file for a week. The preview can still change.

Volodymyr Chornous