diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d685dd6..b5ecf96 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,40 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 + + # Every action reference must match the org pinning rule, offline and exactly: a third-party + # action on the commit SHA of a named release, a first-party one (actions/, docker/, github/) + # floating on its current major. Whether that release is the newest is Dependabot's job and + # laranail/package-tools' verify-action-pins.py; nothing checked the *shape* until this step, + # which is how the references here drifted off it with every check staying green. + - name: Action pins match the rule + run: | + python3 - <<'PINS' + import os, re, sys + d = ".github/workflows" + files = sorted(f for f in os.listdir(d) if f.endswith((".yml", ".yaml"))) + floor = 5 + if len(files) < floor: + sys.exit(f"{len(files)} workflow files in {d}; floor is {floor}. " + "A search that stops matching must fail, not report a clean repository.") + uses = re.compile(r"uses:\s*([\w.-]+/[\w./-]+?)@([\w./-]+?)([ \t]*#[ \t]*(\S+))?\s*$", re.M) + bad, seen = [], 0 + for name in files: + for ref, at, _, note in uses.findall(open(os.path.join(d, name)).read()): + if ref.startswith("./") or "/.github/workflows/" in ref: + continue # a local action or a reusable-workflow call + seen += 1 + if ref.startswith(("actions/", "docker/", "github/")): + if not re.fullmatch(r"v\d+", at) or note: + bad.append(f"{name}: {ref}@{at} -- first-party, so float on a bare major tag") + elif not re.fullmatch(r"[0-9a-f]{40}", at): + bad.append(f"{name}: {ref}@{at} -- third-party, so pin to a commit SHA") + elif not note or re.fullmatch(r"v?\d+", note): + bad.append(f"{name}: {ref}@{at[:12]} # {note} -- name the release, not a mutable major") + print("\n".join(f" {b}" for b in bad)) + print(f"{seen} action references in {len(files)} workflow files; {len(bad)} off the rule") + sys.exit(1 if bad else 0) + PINS - uses: actions/setup-go@v7 with: go-version: "1.25" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 394d1fc..80f2c78 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -62,7 +62,7 @@ jobs: - uses: actions/setup-go@v7 with: go-version: "1.25" - - uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2 + - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 # syft powers GoReleaser's SBOM generation. - uses: anchore/sbom-action/download-syft@66cbf4bc1f1c0d2edc94016e65bc221b6bb0ad6c # v0.24.3 # QEMU + buildx build the multi-arch dockers_v2 images; login pushes to ghcr.