# gh-actions-lock Lock your workflow dependencies. > [!WARNING] > **Public preview.** gh-actions-lock is pre-1.0 and under active development. The > lockfile format, command flags, and behavior may change without notice between > releases. Use it, file issues, and expect rough edges. ## Background gh-actions-lock is part of GitHub's Workflow Dependency Pinning effort. It gives repositories a lockfile that pins every workflow dependency to a verified commit, so what runs on the runner is exactly what you locked. Development is ongoing and behavior may still change. Contributions are welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md) to get started. ## Requirements GitHub Enterprise Server (GHES) is not supported. Requires the [`gh` CLI](https://cli.github.com/). Install it first, then install the extension: ```bash gh extension install github/gh-actions-lock ``` ## Usage Scan every workflow under `.github/workflows/` directory, pin each resolvable action to a SHA, and update the lockfile: ```bash gh actions-lock ``` After the initial run to onboard workflows, you will need to run `gh actions-lock` when: - A new workflow is created that has `uses` dependencies. - An existing workflow adds or removes `uses` dependencies. A full-directory run (`gh actions-lock` with no path arguments) also prunes lockfile entries for workflows that have been deleted from `.github/workflows/`, dropping any dependencies left orphaned by the removal. Scoped runs that name specific workflows never prune out-of-scope entries. Locked pins are sticky: a normal run only re-resolves refs the lockfile does not record yet. Every locked pin, including transitive ones, is re-checked the way the runner checks it at job start: the repository was not renamed or transferred, the pinned commit still exists, and full-version tags (e.g. `v4.2.1`) still point at it. A failed check blocks the run. Writes are all or nothing: if a run finds any error it cannot fix itself, it changes no workflow and no lockfile entry, not even for workflows that are otherwise fine. To check without writing anything, for example in CI, run: ```bash gh actions-lock --verify ``` `--verify` also checks that a commit locked under a branch or partial version (e.g. `main`, `v4`) is still in that ref's history. `--verify-local` runs offline, never writes, and only checks that every ref has a lockfile entry, not that the entries are trustworthy; use `--verify` in CI for that. Pins to branches or partial versions (e.g. `main`, `v4`) are not advanced when upstream moves. To regenerate the lockfile from the current upstream commits, run: ```bash gh actions-lock --relock ``` `--relock` re-resolves refs that have legitimately moved and rewrites the lockfile to the new SHA. Suspicious pins whose recorded commit is no longer reachable upstream are left as errors — use `--accept-moved` to re-resolve those as well. ### GitHub Enterprise Cloud with data residency Authenticate `gh` to your tenant, then run the extension from your tenant repository checkout: ```bash gh auth login --hostname octocorp.ghe.com # From the repository checkout: gh actions-lock ``` With no conflicting environment overrides, the CLI infers the host from the repository remote and uses the credentials stored by `gh` for that host. You do not need to export a token or pass `--hostname` on every run. The account must have read access to the tenant repositories used by your workflows. ### Self repository actions (`$/…`) `uses: $/…` references an action or reusable workflow in the **same repository** as the defining file, resolved at the **running commit**. Because it always resolves to that repository's running SHA it is **inherently pinned** — no lockfile entry is required, and it is valid anywhere a relative `./…` reference is: ```yaml steps: - uses: $/actions/my-action # same-repo action, inherently pinned jobs: call: uses: $/.github/workflows/reusable.yml # same-repo reusable workflow ``` A trailing `@ref` (e.g. `$/actions/my-action@v1`) is rejected — the ref is always the running commit. Same-repo `./…` composite action references are automatically converted to `$/…` on fix runs. The migration rewrites `./…` steps both in your workflows and in your in-repo composite action definitions (`action.yml`). Only `./…` paths that resolve to an in-repo action file are rewritten. `--verify` and `--verify-local` never migrate; they report `./…` refs as `local-action` findings instead. To leave `./…` refs untouched on fix runs, opt out with `--no-migrate-local-actions`: ```bash gh actions-lock --no-migrate-local-actions ``` ## How it works A repo gets a lockfile (located at [`.github/workflows/actions.lock`](https://github.com/github/gh-actions-lock/blob/main/.github/workflows/actions.lock)) and workflows are onboarded to the lockfile on a per-workflow basis. Workflows that are onboarded to the lockfile enforce that all dependencies are present in the lockfile and guarantees that the locked commit for an Action is what's executed on the runner. Lockfiles are also verified for forgeries. The sha must exist in the refs it's stated to exist in. Repository identity is recorded and redirects and mismatches are blocked at runtime. Finally, locked actions must have a branch that the commit being locked exists within. This is to make impostor commit style attacks harder. ## Limitations There are currently eligibility limitations for workflows that can be onboarded to lockfiles: - Workflows in the lockfile cannot use local-path actions, these will be skipped for onboarding. This is also a short-term gap. ## License This project is licensed under the terms of the MIT open source license. See [LICENSE](./LICENSE) for the full terms. ## Maintainers gh-actions-lock is maintained by @github/actions-dispatch-reviewers. See [CODEOWNERS](./CODEOWNERS). ## Support Support is best-effort and community-based. Please file bugs and feature requests as [GitHub issues](https://github.com/github/gh-actions-lock/issues). See [SUPPORT.md](./SUPPORT.md) for details.