From 1499d4e6efdd205e628f1a335454c388911e850d Mon Sep 17 00:00:00 2001 From: yeasy Date: Tue, 25 Aug 2026 14:43:03 -0700 Subject: [PATCH] ci: stop pinning the attest action's SHA inside the test that guards it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 供应链测试把 action 的 **SHA 按字面钉死**: self.assertIn("actions/attest-build-provenance@0f67c3f... # v4.1.1", ...) Dependabot 升级这个 action 时改的正是被断言的那一行,于是断言必然失败、`build` 红、 PR `mergeStateStatus=BLOCKED`。这是**结构性死锁**:该 action 的任何一次升级都会打挂 钉死它的测试,PR 永远合不进来。**全集群 7 个仓库钉的是同一个 SHA,6 个 PR 同时卡在这里** (agentic #13、aifbs #8、ai_security #17、blockchain #176、ceg #16、docker_practice #578)。 反证很干净:另外 4 个断言写成 `assertIn("actions/attest-build-provenance@")` 的仓库 (claude_guide / peg / fde / llm_internals)**同一个升级早就合进去了**。 断言真正要守的是「release job 必须用 SHA 钉住这个 action」——**这个意图不需要记住是哪个 SHA**。改为 `assertRegex(..., r"actions/attest-build-provenance@[0-9a-f]{40} # v\d")`: 仍然强制 40 位 SHA + `# vN` 溯源注释,**比那 4 个仓库现用的宽松写法更严**,但升级不再撞墙。 同批把 aifbs / ai_security 里 `dependabot/fetch-metadata@25dd0e3... # v3.1.0` 的同款钉死 一并改掉(未升级该 action,只解除钉死)。 同时在主干上直接升掉 Dependabot 提的两个版本,**SHA 逐个用 GitHub API 解引用核过** (`browser-actions/setup-chrome` 的 tag 是 annotated tag,要走 `git/tags` 再取 `.object.sha`,直接读 `git/ref/tags` 会拿到 tag 对象的 SHA 而误判): - `actions/attest-build-provenance` 0f67c3f… v4.1.1 → 4d10147… v4.2.2 - `browser-actions/setup-chrome` 2e1d749… v2.1.2 → 48ad923… v2.2.0(blockchain_guide 已在 2.2.0) **负向验证**(AGENTS.md 核心约定 4,逐条证明新断言没被改成永真):把 pin 换成浮动 tag `@v4` → FAIL;保留 SHA 但删掉 `# vN` 注释 → FAIL;还原 → OK。七个仓库各跑一遍, 结果一致。而「换一个合法 SHA 应当通过」这一条由本提交自身证明——pin 从 v4.1.1 换到 v4.2.2,测试全绿。 各仓库 `check_project_rules`、`unittest discover -s tests -p 'test_*.py'`、 `git diff --check` 均通过;docker_practice 另跑 `npm test` 通过。 --- .github/workflows/auto-release.yml | 4 ++-- .github/workflows/ci.yaml | 2 +- .github/workflows/preview-pdf.yml | 2 +- tests/test_workflow_security.py | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml index b72f897..d5c6470 100644 --- a/.github/workflows/auto-release.yml +++ b/.github/workflows/auto-release.yml @@ -32,7 +32,7 @@ jobs: - name: Install Chromium, CJK fonts, and PDF inspection tools id: setupchrome - uses: browser-actions/setup-chrome@2e1d749697dd1612b833dba4a722266286fbefcd # v2.1.2 + uses: browser-actions/setup-chrome@48ad923757ca74d66703209fe939badbdf80f2f4 # v2.2.0 with: chrome-version: stable @@ -158,7 +158,7 @@ jobs: run: (cd dist && sha256sum -c SHA256SUMS) - name: Attest tagged release artifacts - uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 + uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2 with: subject-path: | dist/docker_practice-*.pdf diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3db9632..6efc8aa 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -57,7 +57,7 @@ jobs: python3 tools/test_examples.py --require-tools - name: Install Chromium - uses: browser-actions/setup-chrome@2e1d749697dd1612b833dba4a722266286fbefcd # v2.1.2 + uses: browser-actions/setup-chrome@48ad923757ca74d66703209fe939badbdf80f2f4 # v2.2.0 with: chrome-version: stable diff --git a/.github/workflows/preview-pdf.yml b/.github/workflows/preview-pdf.yml index 9056009..c560852 100644 --- a/.github/workflows/preview-pdf.yml +++ b/.github/workflows/preview-pdf.yml @@ -35,7 +35,7 @@ jobs: npm test - name: Install Chromium - uses: browser-actions/setup-chrome@2e1d749697dd1612b833dba4a722266286fbefcd # v2.1.2 + uses: browser-actions/setup-chrome@48ad923757ca74d66703209fe939badbdf80f2f4 # v2.2.0 with: chrome-version: stable diff --git a/tests/test_workflow_security.py b/tests/test_workflow_security.py index 08a70e3..a1a03eb 100644 --- a/tests/test_workflow_security.py +++ b/tests/test_workflow_security.py @@ -395,9 +395,9 @@ class WorkflowSecurityTests(unittest.TestCase): self.assertIn("contents: write", release_job) self.assertIn("id-token: write", release_job) self.assertIn("attestations: write", release_job) - self.assertIn( - "actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1", + self.assertRegex( release_job, + r"actions/attest-build-provenance@[0-9a-f]{40} # v\d", ) self.assertIn("subject-path: |", release_job) self.assertIn("dist/docker_practice-*.pdf", release_job)