GitHub Actions workflow lockfiles are now GA: Trying out how to prevent missed updates and forgotten onboarding with CI, Dependabot, and policies

GitHub Actions workflow lockfiles are now GA: Trying out how to prevent missed updates and forgotten onboarding with CI, Dependabot, and policies

GitHub Actions workflow lockfiles are now GA. I tested where CI --verify, Dependabot, and Require lockfile catch missed updates and forgotten onboarding, and outline alternatives for the Free plan.
2026.11.03

This page has been translated by machine translation. View original

Hello! I'm Yuji Nishimura from the Operations Department!

GitHub Actions workflow lockfile became generally available on October 28, 2026. It records the commits of the actions a workflow references, and of the actions called within them, in .github/workflows/actions.lock, and fetches those commits at run time. Besides generating the lockfile, the GA announcement introduces three more things: detecting a stale lockfile in CI, updates via Dependabot, and the Require lockfile policy that makes a lockfile mandatory.

If you only want to create a lockfile, running gh actions-lock once is enough. The documentation calls registering a workflow in the lockfile “onboarding”. To run it in practice, though, you need to decide where to catch a missed lockfile update and how to stop workflows that were never onboarded. On top of that, Require lockfile is not enforced depending on your plan and the repository's visibility. This article combines CI, Dependabot, and Require lockfile, and also sorts out how to use them alongside SHA pinning enforcement in environments where Require lockfile is not enforced.

I checked this on November 2, 2026. The environment was as follows.

  • A repository created under a Free plan account (created as private, then changed to public to try Require lockfile)
  • GitHub-hosted ubuntu-latest runner
  • gh 2.103.2 and gh actions-lock v0.4.0 locally (installed with gh extension install github/gh-actions-lock)

I did not try the following.

  • Policy settings in an Organization, and enforcement in private repositories. The scope of enforcement is a judgment based on the on-screen notice and the documentation
  • Restricting the Require lockfile target to some workflows, and the Evaluate mode that only records violations. This article does not tell you the steps for a gradual rollout
  • Reusable workflows located in another repository
  • How merges get blocked when the verify check is made required with branch protection or a ruleset
  • Dependabot security updates and grouping

I covered how the lockfile itself works in an earlier article during the public preview.

From these results, the following combination looks good.

Mechanism Role Settings and notes
lockfile (gh actions-lock) Pins actions and their inner dependencies by commit Onboard with the latest gh actions-lock. Onboard new workflows yourself
--verify in CI Shows mismatches between the lockfile and workflows, and missed onboarding, as a PR check Raise the official sample's --pin v0.2.0 to --pin v0.4.0, the latest at the time of checking
Dependabot Updates the lockfile together in version update PRs Just configure github-actions
Require lockfile policy Stops every workflow that has not been onboarded before it starts With “All workflows”, even workflows that use no actions must be onboarded
SHA pinning enforcement Stops references that are not full SHAs (tags or branches) in workflows that have not been onboarded Onboarded workflows pass even with tag references

Require lockfile is enforced in public repositories and in private repositories on GitHub Team or GitHub Enterprise (based on the documentation and the on-screen notice). How you stop missed onboarding depends on whether it is enforced.

  • Public repositories, and private repositories on Team or higher: combine Require lockfile with the lockfile, --verify in CI, and Dependabot
  • Free private repositories: enable SHA pinning enforcement instead of Require lockfile. Workflows written with full SHAs run even if not onboarded, so catch them with --verify in CI

There were two pitfalls. One is that when a PR forgets to update the lockfile and an onboarded workflow fails to start, that failure does not appear in the PR's check list. The other is that the official sample CI is pinned to gh actions-lock v0.2.0, and the --verify of v0.2.0 can let through a lockfile that will fail at run time. Both were caught by running --verify in CI with the latest gh actions-lock.

The following diagram is a conceptual diagram I made myself, not an official architecture diagram. The left is the entry points of changes, the center is PR checks, and the right is the results at run time.

A self-made conceptual diagram of where checks apply in lockfile operations. On the left there are three entry points: changing the workflow and lockfile together with gh actions-lock, a Dependabot update PR, and forgetting to update the lockfile. In the center, verify-lockfile (CI) shows mismatches as a PR check with gh actions-lock --verify. If pinned to v0.2.0, it lets through a lockfile that is missing references inside a composite action. The right side, at run time, splits into three. If it matches the lockfile, it is fetched at the lockfile's commit and satisfies SHA enforcement even with tags. If the lockfile is stale, it becomes startup_failure and does not appear in the PR's check list. If not onboarded, it is startup_failure when Require lockfile is enforced, and with SHA enforcement alone, a tag reference fails at Set up job. At the bottom it says that Require lockfile is enforced in public repositories and in private repositories on GitHub Team and Enterprise, and is not enforced in Free private repositories, so SHA pinning enforcement is used instead

Setting up CI, verify, and Dependabot in the test repository

I placed three things in the test repository: ci.yml for CI, verify-lockfile.yml from the gh actions-lock official sample, and the Dependabot configuration.

.github/workflows/ci.yml
name: ci
on:
  push:
    branches: [main]
  pull_request:
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - run: echo "build"
.github/dependabot.yml
version: 2
updates:
  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: daily

I used the official sample from the v0.4.0 tag as is.

.github/workflows/verify-lockfile.yml
# Fails when .github/workflows/actions.lock is out of sync with the
# workflows or a locked pin no longer verifies upstream.

name: verify-lockfile

on:
  pull_request:
  push:
    branches:
      - main

permissions:
  contents: read

jobs:
  verify:
    runs-on: ubuntu-latest
    env:
      GH_TOKEN: ${{ github.token }}
    steps:
      - uses: actions/checkout@v7.0.1
        with:
          persist-credentials: false
      - run: gh extension install github/gh-actions-lock --pin v0.2.0
      - run: gh actions-lock --verify

When I ran gh actions-lock locally without arguments, both workflows were onboarded. This time, @v6 in ci.yml was rewritten to the full version tag @v6.1.0.

gh actions-lock
Scanning 2 workflows
Planning pins
Pinned 2 actions across 2 workflows
  actions/checkout@v6.1.0 (d23441a)
    └─ .github/workflows/ci.yml
  actions/checkout@v7.0.1 (3d3c42e)
    └─ .github/workflows/verify-lockfile.yml

After pushing the workflows and the lockfile, both ci and verify-lockfile succeeded.

In a PR with a stale lockfile, only the verify failure shows up in the checks

I added an actions/cache@v4 step to ci.yml and opened a PR without updating the lockfile. At this point, I had already changed the repository to public, but neither Require lockfile nor SHA pinning enforcement was enabled yet.

Looking with gh pr checks, the only thing that appeared in the PR's checks was the verify-lockfile failure. gh pr view --json statusCheckRollup also shows just the one verify entry. I did not check the PR screen.

gh pr checks 2
verify	fail	6s	https://github.com/ynishimura/blog-verify-lockfile-ops/actions/runs/41453374622/job/125303855861

The verify-lockfile log points out the action that is not recorded in the lockfile.

1 of 2 workflows failed
✗ Not pinned actions/cache@v4
  used in workflow but not pinned in lockfile (actions/cache@v4)

On the other hand, the run of the modified ci.yml itself was startup_failure. No jobs were created, and it did not appear in the PR's checks either. It does remain in the Actions run list, though.

gh run list --branch add-cache-without-lock --json workflowName,event,conclusion --jq '.[]|[.workflowName,.event,.conclusion]|@tsv'
ci	pull_request	startup_failure
verify-lockfile	pull_request	failure

In the earlier article too, a run pushed without updating the lockfile in a private repository became startup_failure. A startup failure caused by a stale lockfile happens regardless of policies or visibility. This time, verify-lockfile was the only thing that surfaced a missed lockfile update as a PR check. To block the merge, it seems you need to make the verify check required with branch protection or a ruleset, but I did not try that this time.

Raise --pin when using the official sample CI

The official sample pins the gh actions-lock version with --pin v0.2.0. The latest as of November 2, 2026 is v0.4.0. The --verify judgment changed in v0.3.0, and the release notes say “Some lockfiles that passed --verify on v0.2.0 now fail it”.

When I tried SHA pinning enforcement, a workflow using a lockfile made with v0.2.0 failed at run time with the error lockfile missing pin for actions/checkout@v7. That workflow referenced a composite action that uses actions/checkout@v7 internally. v0.2.0 recorded the actions/checkout@v7 inside the composite action as actions/checkout@v7.0.1, so it reads as though the @v7 entry could not be found at run time.

I compared --verify of v0.2.0 and v0.4.0 against this lockfile. I installed v0.2.0 by pointing the gh extension storage location (XDG_DATA_HOME) to a temporary directory, keeping it separate from the local v0.4.0.

gh actions-lock --verify .github/workflows/t13-locked.yml

v0.2.0 judged it as having no problems.

Scanning 1 workflow
All 1 workflow valid

v0.4.0 detected that the reference inside the composite action is not recorded in the lockfile (excerpt of the output).

Scanning 1 workflow
1 of 1 workflow failed
✗ Lockfile doesn't match locked manifest actions/checkout@v7
  ynishimura/blog-verify-sha-pinning/.github/actions/composite-tag@v1 at locked commit b49117c7d739 uses actions/checkout@v7, but its lockfile entry ynishimura/blog-verify-sha-pinning@v1 does not record it
  ! restore the edge from version control, or run `gh actions-lock --relock`
  see: https://github.com/github/gh-actions-lock/blob/main/docs/troubleshooting.md#incomplete-lockfile

If you keep using the sample with --pin v0.2.0, CI can let through a lockfile that is missing references inside a composite action. This time I changed it to --pin v0.4.0 and confirmed that verify-lockfile succeeds even with both Require lockfile and SHA pinning enforcement turned on, which I enable later.

.github/workflows/verify-lockfile.yml (changed part)
      - run: gh extension install github/gh-actions-lock --pin v0.4.0

A lockfile created back in the v0.2.0 days can end up with incomplete-lockfile in --verify once you raise --pin. In that case, recreate it with gh actions-lock --relock (confirmed in the article where I tried SHA pinning enforcement). If you pin the version, the judgment won't suddenly change because of a gh actions-lock update. In exchange, you will need to raise the --pin value in step with gh actions-lock releases.

Dependabot updates the lockfile in the same PR

When I placed dependabot.yml and pushed, Dependabot immediately opened a PR (#1) raising actions/checkout from 6.1.0 to 7.0.1. Two files changed: ci.yml and actions.lock. In the lockfile, the ci.yml entry changed to actions/checkout@v7.0.1, and the no-longer-used actions/checkout@v6.1.0 entry was removed. The v7.0.1 entry already existed for verify-lockfile.yml.

.github/workflows/actions.lock (excerpt of the PR #1 diff)
 workflows:
     '.github/workflows/ci.yml':
-        - 'actions/checkout@v6.1.0'
+        - 'actions/checkout@v7.0.1'
     '.github/workflows/verify-lockfile.yml':
         - 'actions/checkout@v7.0.1'
 dependencies:
-    'actions/checkout@v6.1.0':
-        ref: 'v6.1.0'
-        commit: 'sha1-d23441a48e516b6c34aea4fa41551a30e30af803'
-        owner_id: 44036562
-        repo_id: 197814629

build and verify on the PR succeeded. I describe the results with the policies enabled in a later section.

However, Locking action dependencies in a repository's workflows says “Dependabot only updates lockfile entries for workflows that are already onboarded.” Dependabot does not go as far as onboarding new workflows.

What Require lockfile stops

It is not enforced in Free private repositories

Require lockfile is a policy you create under “Settings” → “Actions” → “Policies”. When I opened this screen with the repository still private, the following notice appeared. The red frame was added by me.

The Actions policies screen of a private repository on the Free plan. A warning, “Your rulesets won't be enforced on this private repository until you move to GitHub Team organization account.”, is enclosed in a red frame

The “Who can use this feature?” section of Governing execution of GitHub Actions workflows also says “All public repositories, and private repositories on GitHub Team or GitHub Enterprise.” I did not try creating and running the policy while the repository was private. This time I changed the test repository to public and went on from there. Once it was public, this notice disappeared.

Creating the policy

From “New policy”, I gave it a name, checked “Require lockfile”, and set Enforcement status to “Active”. Target workflows was left at “All workflows”. The red frame was added by me.

The new Actions policy creation screen. The “Active” Enforcement status and the “Require lockfile” checkbox (with a Preview label) under Workflow execution protections are enclosed in red frames

The options for Enforcement status were just Active and Disabled. According to the documentation, Evaluate is available only on GitHub Enterprise Cloud. Also, on the November 2, 2026 screen, Require lockfile still carried a “Preview” label even after the GA announcement.

Workflows that are not onboarded are stopped regardless of whether they use actions or are SHA-pinned

With the policy enabled, I added two workflows that were not onboarded. One uses actions/checkout@v7.0.1, and the other uses no actions and has only a run step. Both became startup_failure. The onboarded ci.yml succeeded. The red frame was added by me.

The run screen of the not-onboarded new-run-only workflow. The Status is Startup failure, and in Annotations an error starting with “Workflow is not in the repository's lockfile. Run  in the repository and commit the result.” is shown; both are enclosed in red frames

The full text of the annotation is as follows.

Workflow is not in the repository's lockfile. Run `gh actions-lock` in the repository and commit the result. If this is a reusable workflow, the maintainer of the reusable workflow needs to run `gh actions-lock` in its repository and commit the result. Workflow file: '.github/workflows/new-run-only.yml'.

The documentation also says Require lockfile stops workflows that use no actions, “including workflows with no uses: dependencies”. The verify-lockfile that ran on the same push also pointed out the missed onboarding with ✗ Not pinned .github/workflows/new-run-only.yml / workflow has no lockfile entry.

Next, I also enabled SHA pinning enforcement (“Settings” → “Actions” → “General”, “Require actions to be pinned to a full-length commit SHA”). In this state, I added a release.yml that pins actions/checkout with a full SHA, without onboarding it. This was also startup_failure. Even if pinned with a full SHA, Require lockfile stops it unless it is onboarded.

If you target “All workflows”, you need to onboard every workflow in the repository.

Onboard new workflows yourself

To get the stopped release.yml through, I onboarded only this workflow.

gh actions-lock .github/workflows/release.yml

At this point, the full SHA reference that had the tag attached as a comment was rewritten to that tag notation.

.github/workflows/release.yml
-      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+      - uses: actions/checkout@v7.0.1

When I pushed the workflow and the lockfile in the same commit, release.yml also succeeded. When adding a workflow, the flow is to run gh actions-lock <workflow> and put the workflow and the lockfile in the same commit. References that were pinned with a full SHA become tag notation, so if you have anything that assumes SHAs are used (for example, a CI check that tests whether a reference is a SHA), you need to review it.

How to combine it with SHA pinning enforcement

According to the documentation, Require lockfile is a separate policy from SHA pinning enforcement, and it is fine to enable both during a migration. This time too, with both enabled, the following three succeeded.

  • ci.yml and verify-lockfile.yml, which are onboarded and use tag references
  • The Dependabot update job (Dependabot Updates)
  • After adding actions/setup-node@v4 to ci.yml and onboarding it, the PR (including the lockfile) that Dependabot opened to raise actions/setup-node from 4.4.0 to 7.1.0, and the checks on that PR

The policy creation screen also said that features such as Dependabot are outside the scope of this protection.

The two policies stop different things.

Policy What it stops Free private repositories
Require lockfile Workflows that are not onboarded (regardless of whether they use actions or are SHA-pinned) Not enforced
SHA pinning enforcement References that are not full SHAs in workflows that are not onboarded (fails at Set up job) Enforced (confirmed in the article where I tried SHA pinning enforcement)

In an environment where Require lockfile is enforced, it has the wider scope and can stop all workflows that were not onboarded in one go. In Free private repositories, use SHA pinning enforcement to stop tag references in workflows that were not onboarded. Workflows written with full SHAs and workflows that use no actions will run, so catch them with --verify in CI.

Summary

With the now-GA workflow lockfile, onboarding with gh actions-lock and combining it with --verify in CI and Dependabot let me manage it in the same PR as the workflow. In a PR that forgets to update the lockfile, an onboarded workflow just becomes startup_failure and does not show up in the PR's checks. Without --verify, the PR checks alone won't let you notice a missed update, so if you use the official sample, you'll want to raise --pin to the latest. Dependabot does not onboard new workflows, so run gh actions-lock <workflow> yourself.

How to stop missed onboarding depends on your plan and the repository's visibility. I plan to use Require lockfile for public repositories and private repositories on the Team plan or higher, and SHA pinning enforcement instead for Free private repositories.

I hope this helps someone.


Reference links:

Share this article