From 30f954ceff99e3163629002063ca804a0e7344e9 Mon Sep 17 00:00:00 2001 From: Wikid82 Date: Tue, 8 Sep 2026 04:14:56 -0400 Subject: [PATCH 1/2] fix(ci): restore the toolchain pin to match main's recipe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts 6f38be5c, a stray `sync-pin-on-pr` push from the bot-authored main -> development propagation PR #1307. That job checked out the PR head branch — which for a propagation PR IS `main` — recomputed the toolchain key against the merge ref (which pulls in development's gRPC 1.83.2 bump, a toolchain-key input) and committed the resulting `caddy-crowdsec-9eb9862f44b9e769` pin directly onto `main`. `main`'s actual recipe still has `GRPC_VERSION=1.83.1`, whose key is `caddy-crowdsec-1efe7f19fa52a512` (@ sha256:6575f4c6…), the digest #1300's docker-build actually pulled. The mismatch fails `verify-toolchain-pin` on every PR against `main`. Verified on this branch: - scripts/toolchain-key.sh -> caddy-crowdsec-1efe7f19fa52a512 - imagetools inspect -> sha256:6575f4c6a9f76074870c64df9dd4c9ebee812342f37f52ae5ef8f511ba9f8f00 Claude-Session: https://claude.ai/code/session_01KXA4x9LrA2AsnLrvdHMZbS --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 987d895e6..89f0d9469 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,8 +19,8 @@ ARG CHARON_TOOLCHAIN_IMAGE=ghcr.io/wikid82/charon-toolchain # NOT Renovate-tracked (a content-hash tag has no series to follow, N7) — the # toolchain-image.yml bot owns these two lines. DIGEST is the arch-independent # manifest-list (OCI index) digest, so one pin covers linux/amd64 + linux/arm64. -ARG CHARON_TOOLCHAIN_TAG=caddy-crowdsec-9eb9862f44b9e769 -ARG CHARON_TOOLCHAIN_DIGEST=sha256:b41e571d5951bbfc3daa3dccdca033ad9dee535a8e720ac7e3b0bce338f223b2 +ARG CHARON_TOOLCHAIN_TAG=caddy-crowdsec-1efe7f19fa52a512 +ARG CHARON_TOOLCHAIN_DIGEST=sha256:6575f4c6a9f76074870c64df9dd4c9ebee812342f37f52ae5ef8f511ba9f8f00 # Stage selector — default consumes the prebuilt toolchain image (no compile). # Fork PRs / bootstrap / offline builds pass From 2e750b4eff95371775dadec952a33830994b54ca Mon Sep 17 00:00:00 2001 From: Wikid82 Date: Tue, 8 Sep 2026 04:15:45 -0400 Subject: [PATCH 2/2] fix(ci): stop sync-pin-on-pr from committing to long-lived branches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `sync-pin-on-pr` job in toolchain-image.yml pushes a recomputed TAG/DIGEST pin onto `github.event.pull_request.head.ref`. Its only guard against unwanted runs was `github.actor != 'github-actions[bot]'`, which does not fire for the main -> development auto-propagation PR (#1307): that PR's `pull_request` event runs under a non-bot actor even though the PR itself is bot-authored and its head ref is `main`. Result: the job recomputed the key against the propagation merge ref (which drags in development's gRPC bump) and committed `caddy-crowdsec-9eb9862f44b9e769` straight to `main`, breaking `verify-toolchain-pin` repo-wide (see the companion revert in this PR). Adds three guards to the job `if:`: - refuse any protected head ref (main / development / nightly / feature/beta-release) outright — this job has no business rewriting a long-lived branch in place; - also skip when the PR *author* is github-actions[bot], not just when the triggering actor is; - (existing actor guard retained). Legitimate toolchain-key moves on `development` are still handled by the `open-bump-pr` job, which opens a reviewed bot PR rather than pushing in place. No workflow-`if:` test harness exists in-tree (bats covers the scripts, not YAML guards); actionlint passes. Claude-Session: https://claude.ai/code/session_01KXA4x9LrA2AsnLrvdHMZbS --- .github/workflows/toolchain-image.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/toolchain-image.yml b/.github/workflows/toolchain-image.yml index b24938d58..c280ab440 100644 --- a/.github/workflows/toolchain-image.yml +++ b/.github/workflows/toolchain-image.yml @@ -314,10 +314,26 @@ jobs: # commit when the Dockerfile pin genuinely changes. With the deterministic # build above (same key => same digest) this essentially never fires unless a # tracked pin actually moved on the PR. + # + # Hard guards (2026-09-08 incident): this job pushes to + # `github.event.pull_request.head.ref`, so it must NEVER run when that head + # is a long-lived branch. The main -> development auto-propagation PR (#1307) + # has head ref `main`; its merge ref pulls development's gRPC bump into the + # key computation, and the resulting pin got committed straight to `main`. + # `github.actor` was not the bot on that event (propagation runs under a + # human/PAT identity), so the actor guard alone did not catch it — also + # check the PR author, and refuse any protected head ref outright. A genuine + # key move on `development` is handled by `open-bump-pr` (a reviewed bot PR), + # not by this in-place sync. if: >- github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'github-actions[bot]' && + github.event.pull_request.user.login != 'github-actions[bot]' && + github.event.pull_request.head.ref != 'main' && + github.event.pull_request.head.ref != 'development' && + github.event.pull_request.head.ref != 'nightly' && + github.event.pull_request.head.ref != 'feature/beta-release' && needs.build-toolchain.outputs.digest != '' runs-on: ubuntu-latest permissions: