Skip to content

Pin and modernize GitHub Actions references - #1891

Merged
jar-stripe merged 8 commits into
masterfrom
jar/sat-28956-pin-workflows
Aug 27, 2026
Merged

Pin and modernize GitHub Actions references#1891
jar-stripe merged 8 commits into
masterfrom
jar/sat-28956-pin-workflows

Conversation

@jar-stripe

@jar-stripe jar-stripe commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Why?

Pins this repo's actions to commit hashes so a moved tag cannot change what CI runs, then brings the pinned versions current. Same approach as stripe/stripe-mock#1643.

What?

  • pins extractions/setup-just, actions/checkout, actions/setup-python, actions/upload-artifact, actions/download-artifact, and pypa/gh-action-pypi-publish to full commit hashes, each with its resolved version in a trailing comment
  • sets persist-credentials: false on all three checkouts, so the token no longer stays in .git/config
  • upgrades setup-just v2 to v4, actions/checkout v3 to v7.0.1, actions/setup-python v4 to v7.0.0, actions/upload-artifact v4 to v7.0.1, and actions/download-artifact v4 to v8.0.1. Every job on master warns today that checkout@v3, setup-python@v4, upload-artifact@v4, and setup-just@v2 are being force-migrated to a newer Node runtime; that warning is gone on this branch
  • adds .github/zizmor.yml with a ref-pin policy scoped to the stripe namespace, which keeps stripe/openapi/actions/* on @master

Verification. zizmor 1.29.0 over .github/workflows/: 15 reportable findings to zero — 12 high unpinned-uses, 3 medium artipacked. Every hash was resolved against its claimed tag through the GitHub API, and zizmor's ref-version-mismatch audit independently validates each version comment. CI is green on the branch across all 12 jobs, including windows and all three pypy versions, with Publish skipped as tag-gated; runs were dispatched manually because jar/* branches are not in this workflow's push trigger list.

See Also

jar-stripe and others added 7 commits August 25, 2026 16:44
Actions under stripe/* are first-party and tracked on a branch on purpose,
so requiring a commit hash for them would be churn without a security gain.
Scoping the policy to that namespace keeps the blanket hash requirement in
force for every third-party action.

This lands before the pins so the auto-fixer honours the policy and leaves
stripe/openapi/actions/* alone rather than hash-pinning them for a revert.

Committed-By-Agent: claude
A tag is a mutable pointer, so any action referenced by tag can change what
CI executes without a commit here. Pinning to a full commit hash makes the
reference immutable and the version comment auditable.

Thirteen of the fourteen pins came from the auto-fixer; every hash was then
resolved against its claimed tag through the GitHub API before committing.

pypa/gh-action-pypi-publish was pinned by hand because the auto-fixer cannot
resolve a version for a branch reference. It tracked release/v1, whose head is
currently tag v1.14.2, so the pin is both immutable and current. Dependabot
would be the mechanism to keep it moving.

Also sets persist-credentials: false on all three checkouts. The default leaves
the workflow token in .git/config for the rest of the job, where any later step
can read it; none of these jobs push, so nothing needs it retained.

Committed-By-Agent: claude
Pinning froze these at the versions master happened to reference, and four of
the five were on a Node runtime GitHub force-migrates, which every job warns
about today:

  extractions/setup-just  v2.0.0 -> v4.0.0
  actions/checkout        v3.7.0 -> v7.0.1   (node16 -> node24)
  actions/setup-python    v4.9.1 -> v7.0.0   (node16 -> node24)
  actions/upload-artifact v4.6.2 -> v7.0.1   (node20 -> node24)
  actions/download-artifact v4.3.0 -> v8.0.1 (node20 -> node24)

The artifact pair moves together on purpose: build uploads dist and publish
downloads it, and upload v7 / download v8 are the majors upstream ships as a
pair. download-artifact v5's breaking change is scoped to downloads by ID; this
one downloads by name, so it does not apply. v8 skips decompression based on
Content-Type, which only diverges when the uploader sets archive: false, and
this workflow does not.

setup-python's cache input has no default in v7, unlike setup-node's
package-manager-cache from v5 onward, so the upgrade adds no cache surface to
audit. v7 drops the pip-install input, which this workflow never set.

All five majors require Actions runner 2.327.1 or later, which the
GitHub-hosted runners this workflow uses already satisfy.

Committed-By-Agent: claude
v8 fails the job on an artifact digest mismatch where v4 only logged a
warning. The publish job is tag-gated, so CI never exercises it — the
first person to see this failure will be mid-release, and the escape
hatch should be next to the code rather than in a PR body.

Committed-By-Agent: claude
Committed-By-Agent: codex
Co-authored-by: codex <noreply@openai.com>
Committed-By-Agent: codex
Co-authored-by: codex <noreply@openai.com>
Committed-By-Agent: codex
Co-authored-by: codex <noreply@openai.com>
@jar-stripe
jar-stripe marked this pull request as ready for review August 27, 2026 18:59
@jar-stripe
jar-stripe requested a review from a team as a code owner August 27, 2026 18:59
@jar-stripe
jar-stripe requested review from xavdid and removed request for a team August 27, 2026 18:59
@jar-stripe
jar-stripe enabled auto-merge (squash) August 27, 2026 21:43
@jar-stripe
jar-stripe merged commit 98a1e87 into master Aug 27, 2026
20 checks passed
@jar-stripe
jar-stripe deleted the jar/sat-28956-pin-workflows branch August 27, 2026 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants