Bring the seed's workflow templates up to the seeded repos' zizmor hygiene
seed/.github/workflows/*.yml.tmpl, rendered with placeholder values and audited by zizmor 1.30.0 (--persona regular), produce 93 findings on main today (97 before #14 removed the five self-repository ones). A freshly seeded SDK therefore fails its own actions audit on its first CI run, and then someone re-does by hand what hey-sdk, basecamp-sdk and fizzy-sdk each already did in their own workflows. This PR brings the templates up to what those repos run, so the seed stops drifting from them.
Originally stacked on #11 and #14; both have merged, so this is now two commits against main. #17 was closed as a duplicate of #11 and is folded away: the only edit to #11's smithy-verify.yml.tmpl is a trailing # zizmor: ignore[unpinned-uses] on its basecamp/sdk/actions/smithy-verify@main line, and test.yml.tmpl keeps #11's inline smithy-verify job (the composite action run directly, as #11's header comment says) with the hygiene applied to it.
Before / after
Rendered templates (.tmpl stripped, placeholders filled), zizmor --no-progress --persona regular, default policy:
| rule | main (0a453bc) | this PR |
|---|---|---|
| unpinned-uses (high) | 46 | 0 (5 ignored inline) |
| artipacked | 22 | 0 (1 ignored inline) |
| excessive-permissions | 9 | 0 |
| cache-poisoning (high) | 7 | 0 (7 ignored inline) |
| template-injection | 7 | 0 |
| adhoc-packages | 2 | 0 (1 ignored inline) |
| total | 93 | 0 |
actionlint (1.7.12) on the same rendered tree: clean, with the added seed/.github/actionlint.yaml (hey-sdk's file) naming the exact $/ reusable-workflow call actionlint predates. The repo's own gate from #11 — hack/render-seed.sh, then actionlint and zizmor --config hack/zizmor-seed.yml --min-severity high over the render — is green, and the render is also clean under the default policy, so every exception hack/zizmor-seed.yml records "until the template it names is re-extracted" is now unnecessary; that file can shrink to the four basecamp/sdk/actions/* entries or go entirely, since the inline ignores cover those. Left for a follow-up rather than folded in here.
What changed, per finding class
Each change is the seeded repos' version of the same line; hey-sdk is the reference, basecamp-sdk where hey-sdk has no Kotlin, Ruby, Swift or TypeScript.
- unpinned-uses — every
uses:pinned to a full commit SHA with its# vX.Y.Zcomment, copied from the Dependabot-maintained pins in hey-sdk and basecamp-sdk and each verified against the upstream tag:actions/checkoutv7.0.1,actions/setup-gov7.0.0,actions/setup-javav6.0.0,actions/setup-nodev7.0.0,gradle/actions/setup-gradlev6.3.0,ruby/setup-rubyv1.321.0,aquasecurity/trivy-actionv0.36.0,github/codeql-action/upload-sarifv4.37.9,rubygems/configure-rubygems-credentialsv2.1.0. The seed's own composite actions (basecamp/sdk/actions/*@main) stay onmainby design and carry the ignore hey-sdk wrote for it. - excessive-permissions —
permissions: {}at the top of every workflow;contents: readper job, including the jobs that call the reusable workflow;id-token: write,packages: writeandsecurity-events: writeonly on the job that publishes or uploads. - artipacked —
persist-credentials: falseon every checkout except the Go tag job, which pushes and carries hey-sdk's ignore. - cache-poisoning — caches kept, with the seeded repos' two reasons:
cache is branch-isolated; fork PRs cannot write to this cacheon release-job setups,cached deps are for testing, not release artifact generationon test-job setups. - template-injection —
${{ steps.*.outputs.* }}and${{ github.event_name }}hoisted intoenv:. - adhoc-packages —
npm install -g npm@latestat release time is gone: the npm publish job runs on Node 24, whose bundled npm already supports OIDC trusted publishing (basecamp-sdk's move, with its comment).gem install bundler-auditstays, with basecamp-sdk's reason inline.govulncheck@latestis pinned to v1.1.4, the newest release that builds on the seed's Go floor:go.mod.tmplsaysgo 1.23, the templates select the toolchain withgo-version-file: go/go.mod(as the seeded repos do), setup-go v7 exportsGOTOOLCHAIN=local, and every govulncheck release from v1.2.0 requires Go 1.25 (v1.8.0: 1.26). hey-sdk and fizzy-sdk pin v1.1.4; basecamp-sdk's v1.8.0 works there only because its go.mod is 1.26. The pin moves withgo.mod.tmpl.
Two consequences of the pin bumps, both following basecamp-sdk: gradle/actions/setup-gradle v6 defaults to its commercial enhanced cache provider, so the templates set cache-provider: basic (what v5 did); rubygems/configure-rubygems-credentials moves v1.0.0 → v2.1.0, the only SHA the seeded repos pin (the step takes no inputs).
Left in place, with reasons inline
All 14 ignored findings carry a # zizmor: ignore[rule] -- reason copied from the seeded repos: 5 unpinned-uses (the seed's own actions on @main), 7 cache-poisoning, 1 artipacked (Go tag push), 1 adhoc-packages (bundler-audit). Under --persona pedantic the rendered tree still reports concurrency-limits, undocumented-permissions and anonymous-definition, none of which the seeded repos' default-persona CI enforces either.
Merges
Two commits on main, no merge conflicts. Against #15 (rustS2/seed-rust), git merge-tree reports two add/add conflicts: .github/workflows/ci.yml, which #15 already has against main (it is based on #11's pre-merge branch), and seed/.github/workflows/smithy-verify.yml.tmpl, which this PR causes — #15 re-adds #11's file verbatim and this PR's copy differs by the one trailing ignore comment. Whichever lands second takes #11's file plus that comment.
Not done here
- No
lint-actionsjob (actionlint + zizmor) intest.yml.tmpl. Every seeded repo has one; it is what would keep a seeded SDK honest after day one, but it is a new job rather than a fix to an existing finding. Worth its own PR. persist-credentials: falsefollowed bygit fetch origin mainworks because the seeded repos are public (hey-sdk's release-go ran green with this pattern today). A private SDK would need that one step's credentials back.- Raising the seed's Go floor from 1.23 to 1.26 (what all three seeded repos run today) would allow govulncheck v1.8.0; that is a seed-wide change for a separate decision.