
GitHub Actions 现在支持 workflow lockfile 了。
由于 GitHub Actions 是从 Git 获取的,之前的建议是固定到完整的 SHA 而不是 tag。这是因为 tag 是可变的,容易受到供应链攻击,攻击者可以把原本安全的 tag 指向恶意代码。
例如,一个旧的 workflow 看起来是这样的:
name: Lint
on: [push, pull_request, workflow_dispatch]
permissions: {}
env:
FORCE_COLOR: 1
RUFF_OUTPUT_FORMAT: github
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: j178/prek-action@44924fe9ef4a6f88253c4b6b1bf11c689d3ce53d # v3.1.0
以下是我配置 lockfile 的方式。
安装
为 gh CLI 安装 gh-actions-lock 扩展:
$ gh extension install github/gh-actions-lock
✓ Installed extension github/gh-actions-lock
锁定
在你的仓库中运行:
$ gh actions-lock
✓ All 1 workflows valid
workflow 现在使用 vX.Y.Z tag,看起来是这样的:
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 946971c..3503607 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ - uses: actions/[email protected]
with:
persist-credentials: false
- - uses: j178/prek-action@44924fe9ef4a6f88253c4b6b1bf11c689d3ce53d # v3.1.0
+ - uses: j178/[email protected]
并且它会在 .github/workflows/actions.lock 生成一个 lockfile:
# This file is machine-generated by `gh actions-lock`.
# Do not edit by hand; run `gh actions-lock` to update.
# Docs: https://gh.io/actions-lockfile
version: 'v0.0.3'
workflows:
'.github/workflows/lint.yml':
- 'actions/[email protected]'
- 'j178/[email protected]'
dependencies:
'actions/[email protected]':
ref: 'v7.0.1'
commit: 'sha1-3d3c42e5aac5ba805825da76410c181273ba90b1'
owner_id: 44036562
repo_id: 197814629
'j178/[email protected]':
ref: 'v3.1.0'
commit: 'sha1-44924fe9ef4a6f88253c4b6b1bf11c689d3ce53d'
owner_id: 10510431
repo_id: 1052387486
提交修改后的 workflow 和新的 lockfile。
Renovate 和 Dependabot
好消息,两者都已经支持 lockfile!你的定期更新也会更新 lockfile。记得使用 cooldown。
验证
GitHub 还建议在 CI 中验证 lockfile,以确保它是最新的且未损坏。
他们建议将这个 verify-lockfile.yml 复制到你的仓库中。我决定把它放进我现有的 lint workflow 中,但放在单独的 job 里,这样它可以独立并行运行:
name: Lint
on: [push, pull_request, workflow_dispatch]
permissions: {}
env:
FORCE_COLOR: 1
RUFF_OUTPUT_FORMAT: github
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/[email protected]
with:
persist-credentials: false
- uses: j178/[email protected]
# Fails when .github/workflows/actions.lock is out of sync with the
# workflows or a locked pin no longer verifies upstream.
lockfile:
runs-on: ubuntu-slim
env:
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/[email protected]
with:
persist-credentials: false
- run: gh extension install github/gh-actions-lock --pin v0.4.1
- run: gh actions-lock --verify
注意我在这里使用了轻量级的 ubuntu-slim runner。另外,它固定到了 v0.4.1;我们总得在某个时候更新它,或者想办法自动化。那是以后的事了。
别忘了,我们刚刚修改了工作流中的 actions,因此需要用 gh actions-lock 重新锁定。如果只是添加到 lint.yml,实际上不会有任何变化,因为它已经锁定了 actions/checkout。但如果你创建了一个新文件,比如 verify-lockfile.yml,就需要为它重新锁定。CI 会提醒你。
zizmor
zizmor 是一个针对 GitHub Actions 的安全 linter,强烈推荐使用。如果你还没用,请务必用上。
v1.32.0 之前的版本会提示你对 actions 进行哈希固定(hash-pin),而 v1.32.0 是第一个支持 lockfile 的版本。
我在 prek 中使用 zizmor,因此在 .pre-commit-config.yaml 中添加/更新 zizmor:
- repo: https://github.com/zizmorcore/zizmor-pre-commit
rev: v1.32.0
hooks:
- id: zizmor
已锁定!
好,提交并推送!
示例
- python-pillow/Pillow#10428
- python/release-tools#477
- python/miss-islington#758
- python/cpython#161811
题图:Slaymaker Barry Co. Sprocket Locks in The Bearings(第 XII 卷第 23 期,1896 年 1 月 2 日),藏于 Smithsonian Libraries and Archives,无已知版权限制。