Repository navigation
ci(publish): build the Lambda handler zip in a read-only job and verify its hash before release - #7495
Conversation
…fy its hash before release The handler zip build runs dependency install and bundling code. It moves out of the publish job into its own job with `contents: read`, no secrets and no persisted git credentials. The publish job downloads the artifact, checks its sha256 against the build job's output, then pins and attaches it as before. A retried run still reuses the zip already on the release. Refs #7485 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Verdict: REQUEST CHANGES · 1 blocker · 1 important · 0 nits · head 9744856
Required CI / Test is red on this head: Test (support) fails 2 tests in scripts/publish-workflow.test.mjs. Details ↓ inline.
Scope
Read publish.yml end to end, plus pin-handler-zip.ts, build-zip.ts, root build, and the CI log for run 42805033787. The root bun run build does not create packages/aws-lambda/dist/handler.zip, so pinHandlerZip cannot rename an unverified zip over the verified one. No prior reviews on this PR.
— Genesis
… hash check The publish workflow test still looked for the old "Build Lambda handler zip" step. It now checks the build job's read-only permissions and the publish job's dependency on it, and runs the pin step for the retry, matching-hash, mismatched-hash and empty-hash cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Verdict: APPROVE — 2 resolved, 0 open, 0 new · 9744856 → 2493438
The workflow is unchanged since 9744856. The 7 tests pass locally, and removing the hash check fails test 7. On this head, run 42830547446 failed CLI smoke with an npm ETARGET for @puppeteer/browsers@3.2.7, which this PR doesn't touch. The newer run, 42830585502, is fully green.
— Genesis
What
The Lambda handler zip is now built in its own job,
lambda-handler-zip, with a read-only token, no secrets and no stored git credentials. The publish job checks the zip's sha256 against the build job's output before it pins the zip and attaches it to the release.Why
Building the zip runs dependency install and bundling code. Before this change it ran inside the publish job, which has
contents: writeandid-token: write. The checkout there also leaves the job token in.git/config, so the zip build could read that token even withoutGH_TOKENin the step's env. #7485 locked the zip's runtime install. This PR moves the zip's own build (build-zip.tsand that runtime install) out of the publish job.Scope limit: the publish job still runs
bun installandbun run buildfor the npm packages, with those same permissions and the stored checkout token. That's unchanged frommainand not addressed here.Related work
Refs #7485
How
lambda-handler-zip:permissions: contents: read, noenvironment, no secrets, and the checkout usespersist-credentials: false.bun install --frozen-lockfile,bun run buildandbuild:zip. The runtime lock from fix(aws-lambda): the handler ZIP installs its runtime from a committed lockfile with scripts off #7485 still installs withnpm ci --ignore-scripts.handler.zipas an artifact and exposes its sha256 as a job output.publishjob:needsthe new job and downloads the artifact.pin-handler-zip.tsas before.gh release downloadretry path stays in this job. A rebuilt zip would not be byte-identical, so a retried run must still pin the zip that's already on the release.Test plan
scripts/publish-workflow.test.mjs(7/7) checks that the build job has read-only permissions, has no secrets and doesn't persist credentials, and that the publish job needs it. It also runs the pin step for four cases: retry, matching hash, mismatched hash and empty hash. If the hash check is removed, the test fails.actionlinton the newpublish.ymlreports no errors;main's version also reports none.packages/aws-lambdaandexamples/aws-lambda:prebuilt/handler-zip.jsonand the.sha256file pin the artifact's hash;::error::, nothing pinned;attached=true, and the pin matches the release asset, not the artifact.workflow_dispatchor dry-run path; it only fires on a mergedrelease/v*PR or a prerelease tag push. I didn't cut a release to test it, so whoever runs the next release should watch theLambda handler zipandPublishjobs.Claude Opus 5.5
Things I checked before splitting the job
pin-handler-zip.tsmovespackages/aws-lambda/dist/handler.ziponly if that file exists. The publish job'sbun run build(build.mjs) does not create a zip, so the verified artifact atdist/hyperframes-lambda-handler.zipis what gets hashed and pinned.build-zip.tsresolves workspace packages from source through esbuild aliases and stages files from the build output. No package build script reads git history, so the build job's shallow checkout is enough.pnpm publishin the publish job, and the runtime lock usesnpm ci, which comes with setup-node.bun install --frozen-lockfileandbun run buildas before. Only the zip build moved out.— Rames Jusso
🤖 Generated with Claude Code