gh-actions-lock 0.2.0 升级后要处理的坑:粘性锁、更严的 --verify 与本地 action 迁移
0.2.0(2026-10-12)的发布说明是一串变更条目,公开预览公告讲的是它能做什么。这篇按升级顺序走一遍实际会遇到的行为变更、报错和对应命令,面向已经在用这个扩展的仓库。
项目信息:
- 仓库:(MIT,public preview,需要 gh CLI,GHES 不支持)
- 锁文件格式库:
- 文档:
升级与第一次写入
gh extension install github/gh-actions-lock
gh extension upgrade gh-actions-lock
gh actions-lock
锁文件固定在 .github/workflows/actions.lock,schema 现在是 v0.0.3。升级后第一次写入会改掉文件里的 version: 行,这个改动只发生一次。
锁文件结构大致是:
version: v0.0.3
workflows:
# workflow path -> 扁平的传递依赖 pin key 列表
.github/workflows/release.yml:
- actions/checkout@v6.0.2
dependencies:
# pin key -> 解析到的 action 元数据
actions/checkout@v6.0.2:
ref: v6.0.2
commit: sha1-de0fac2e...
owner_id: 44036562
repo_id: 197814629
pin key 是 OWNER/REPO@REF,同一个 key 会同时出现在 workflows(扁平传递列表)和 dependencies(去重后的图条目,带 uses: 链接到直接依赖)里。
普通 run 变了:粘性锁
这是升级后最容易误解的一点。普通 run 只解析 lockfile 还没记录的 ref,已有 pin 不会被顺手刷新。每个已锁 pin(包括传递依赖)都会按 runner 在 job 启动时的检查方式复查:
- 仓库没有被改名或转移;
- pin 的 commit 仍然存在;
- full-version tag(如
v4.2.1)仍指向这个 commit。
任何一项失败都会阻塞整次 run。--rescan 已经移除,由这套粘性锁加 runner parity 检查替代;仓库改名现在会被跟随。
写入是全或无的:一次 run 里只要有它自己修不了的错误,workflow 和 lockfile 一个字节都不改,哪怕其它 workflow 是好的。
--verify 变严,CI 会开始红
gh actions-lock --verify
--verify 只检查不写。0.2.0 之后它会额外报两类错:
- lockfile 里存在没有任何 workflow 使用的条目;
- 存在没有 lockfile 条目的 workflow。
它还会检查在 branch 或 partial version(main、v4)下锁定的 commit 是否仍在该 ref 的历史里。
修法就是跑一次 gh actions-lock 并提交结果。
CI 里的最小接入:
name: lockfile
on: [pull_request]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: gh extension install github/gh-actions-lock
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: gh actions-lock --verify
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
运行账户需要对 workflow 用到的仓库有读权限。
--verify-local 不再迁移本地引用
--verify-local 离线运行、从不写盘,只检查每个 ref 是否有 lockfile 条目,不检查条目是否可信。所以 CI 该用的是 --verify,不是它。
升级后它把 ./… 报成 local-action findings,不再在磁盘上做迁移。
--relock 和 --accept-moved 的区别
pin 到 branch 或 partial version 的条目不会因为上游移动自动前进。--relock 重解析合法移动的 ref 并改写为新 SHA:
gh actions-lock --verify # 先看报什么
gh actions-lock --relock
git diff .github/workflows/actions.lock
如果扩展报 tag 现在指向上游另一个 commit,先看上游仓库历史,确认移动合法再 relock。
原来锁的 commit 在上游完全不可达(force-push 或删除)时,--relock 仍会把它留作错误,这时才用:
gh actions-lock --relock --accept-moved
本地路径 action:onboarding 被跳过
已进入 lockfile 的 workflow 不能使用 local-path action,这类 workflow 会被跳过 onboarding。典型报错是 skipped because local path actions aren't supported,含义是该 workflow 里有 uses: ./… 没解析到真实 action 文件。
注意解析基准:本地路径从 repository root 解析,不是从引用它的那个文件所在目录解析。看起来挨着的路径可能解析不到,这是升级后最常见的困惑点。
$/ 与自动迁移
$/… 指向与定义文件同一仓库的 action 或可复用 workflow,按 running commit 解析,天然 pin,不需要 lockfile 条目:
steps:
- uses: $/actions/my-action
jobs:
call:
uses: $/.github/workflows/reusable.yml
带尾部 @ref 会被拒绝(如 $/actions/my-action@v1),ref 永远是 running commit。
fix run 时,同仓库的 ./… composite action 引用会自动改写成 $/…,改写范围包括 workflow 里的 ./… step 和仓库内 composite action 的 action.yml;只有能解析到仓库内 action 文件的 ./… 才会被改写。--verify 和 --verify-local 从不迁移。
要保留 ./… 不动:
gh actions-lock --no-migrate-local-actions
没有 .git 的部分 checkout
在 relock 一个没有 .git 目录的部分 checkout 时,用 GH_ACTIONS_LOCK_REPO_ROOT 指向仓库根:
GH_ACTIONS_LOCK_REPO_ROOT=/path/to/repo gh actions-lock --relock
allowlist 按 SHA 校验
workflow 接入后,allowlist 按锁定的 commit SHA 校验,因为 tag 可以移动而锁定的 SHA 不能。形如 actions/checkout@v6 的 tag 条目不再匹配,要改用 wildcard 或完整 commit SHA。提交前先看一遍仓库/组织/企业的 allowlist 配置。
Dependabot:只改已接入的条目
Dependabot 为已接入 workflow 的 action 开版本更新时,会在同一个 PR 里重新生成对应 lockfile 条目,workflow 与 lockfile 不会漂移。它不会替你接入 workflow——在没有 lockfile 条目的 workflow 里升依赖,只会提示需要 onboarding。
schema 这块要留意:RELEASING.md 写着 Dependabot 钉住 CLI 版本与二进制校验和,目前只接受 lockfile schema v0.0.2;CLI 输出新 schema 版本前要先在 dependabot-core 那边加支持。所以升级到 v0.0.3 后 Dependabot 是否正常协同,需自行验证。
GHES 与 data residency
GHES 不支持这个扩展。
Data residency(GHE.com)下:
gh auth login --hostname octocorp.ghe.com
# 从 repository checkout 运行
gh actions-lock
没有冲突的环境覆盖时,CLI 从 repository remote 推断 host,使用 gh 为该 host 存的凭据,不必每次导 token 或传 --hostname。账号需要对 workflow 用到的 tenant 仓库有读权限。
hostname 字段在 v0.0.3 里是可选的,规则比较绕:
- 省略表示绑定 home host——github.com 上是
github.com,GHE.com data residency 实例上是该 tenant。 - 生产者对 home host 必须省略
hostname。唯一显式写github.com的场景,是在 GHE.com 实例上跑但 pin 绑github.com。 - 生产者从不写
*.ghe.com。 - github.com 上
hostname必须省略或为github.com。 - GHE.com data residency 只接受
v0.0.3lockfile。v0.0.1/v0.0.2用省略表示github.com,生产者要迁移成v0.0.3并给每个依赖显式写github.com。
解析器能读 v0.0.1/v0.0.2,在内存里把 hostname 默认成 github.com;v0.0.1 的 tag/branch 字段与 :algo-hex 后缀 pin key 会被规范化到 v0.0.3 的 File 结构,解析不会改写源文件。
0.2.0 的其它行为变更
uses:中的表达式被拒绝。$/action 内的 remote ref 收窄。- 对使用可变 Docker image tag 的 workflow 告警。
- scoped run 会清理被移除的依赖;全目录 run(不带路径参数)会清掉已删除 workflow 的 lockfile 条目及其孤立依赖,指定具体 workflow 的 scoped run 不动范围外条目。
- Dependabot 配置加入 cooldown;在 Dependabot 代理下 fail closed。
- 支持 hostname-aware lockfile;无依赖的 workflow 也会记录进 lockfile。
- 直接
uses的 owner/repo 大小写不敏感匹配。 repo-hijacked分类改名为repo-replaced。
提交前 review 什么
扩展改的不只是 lockfile,它还会把 workflow 的 uses 引用改写成解析到的具体版本,例如 octo-org/deploy-action@v3 变成 octo-org/deploy-action@v3.1.0——更具体,但不改变解析到的 commit。
lockfile diff 里 commit 变了,就是 workflow 要跑的代码变了,按依赖版本升级对待。owner_id 或 repo_id 变了很少见,说明这个名字背后的仓库不是你最初锁的那个,合并前要查。
创建 lockfile 时是按当前 branch/tag 引用钉住依赖的,所以先确认这些就是你要锁的版本。workflow 调用另一仓库的可复用 workflow 时,那个可复用 workflow 的依赖归它被定义的那个仓库的 lockfile 管,建议先把共享 workflow 仓库接入。
lockfile 看着不对,就改 workflow 文件重新生成,不要手改 lockfile。
附:在 Go 里读锁文件
go get github.com/github/actions-lockfile/go/pkg/lockfile
lockfile.Path // .github/workflows/actions.lock
file, err := lockfile.Parse(contents)
keys := file.LookupWorkflow(".github/workflows/release.yml")
这个包只做格式基础设施,不解析 action、不更新 pin、也不评估漏洞。