Repository navigation
ci: repack dist/ on dependabot branches without exposing a write token - #390
Conversation
|
Reviewed from the test lane (read-only on a fork head, so comment only). The job logic is sound — in particular the repack commit is pushed by the PAT owner, so the re-triggered run's
🐝 Hive Agent: — hive: agent=quality backend=copilot model=claude-fable-5.1 |
jeefy
left a comment
There was a problem hiding this comment.
The js-yaml move is correct. It's imported at runtime (config.ts:5, owners.ts:6), and dist/ is unchanged. Please split it into its own PR so it can merge now.
repack-dist has a high-severity problem: the write token sits on disk while dependency code runs.
actions/checkoutkeepsDEPENDABOT_REPACK_TOKENin.git/config, and thennpm ci(install scripts),buildandpackrun the code Dependabot just bumped.- For a github-actions bump, the workflow comes from the PR, so the bumped
checkout/setup-noderun next to the token too. - A compromised package could read that long-lived contents:write PAT. It could then push branches or a
v*tag, which triggersrelease.yml; I found no on-main check there.
If you want auto-repack:
- Job A, no secrets:
persist-credentials: false,npm ci --ignore-scripts, build, pack, then uploaddist/as an artifact. - Job B,
needs: A, holds the token: checkout at the PR head SHA, download the artifact, check that onlydist/changed, commit,git push --force-with-lease. No npm. - Use a short-lived GitHub App token instead of a PAT. Drop the unused
permissions: contents: write(Dependabot runs get a read-only GITHUB_TOKEN). Gate ongithub.event.pull_request.user.login == 'dependabot[bot]'. Consider a tag ruleset or an on-main check inrelease.yml.
The simpler alternative is to keep the drift gate and have a maintainer run npm run pack on Dependabot PRs.
Dependabot cannot run 'npm run pack', so bundled-dependency bumps always fail the dist/ drift gate. Rebuild dist/ and push it back, split across two jobs per review so the write credential never coexists with dependency code: - repack-dist holds no secrets: persist-credentials false, npm ci --ignore-scripts, build, pack, dist/ uploaded as an artifact (verified locally: the --ignore-scripts build reproduces the committed dist/ byte-for-byte) - push-repacked-dist runs no npm: it mints a short-lived App token, checks the branch has not moved since the rebuild, refuses any artifact change outside dist/, and pushes with --force-with-lease Gated on github.event.pull_request.user.login == 'dependabot[bot]' and a same-repo head. No contents:write GITHUB_TOKEN permission is requested; the push uses the App token, which is also what makes the pushed commit re-trigger build-test. The js-yaml dependency move was split into its own PR per review. Fixes cncf#171 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Bob Killen <bkillen@linuxfoundation.org>
50e0a2c to
f2fc0b7
Compare
|
Reworked per review:
|
js-yaml is a runtime import (src/utils/owners.ts:6, src/utils/config.ts:5) bundled into dist/, so it belongs in dependabot's production-dependencies group where a maintainer expects a repack to be needed. Split out of #390 per review so it can merge on its own. Ref #171 Signed-off-by: Bob Killen <bkillen@linuxfoundation.org> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/kind cleanup |
Description
Every dependabot PR that bumps an
ncc-bundled dependency permanently fails the "Verify committed dist/ matches source" gate, because dependabot never runsnpm run pack(see #167). This PR rebuildsdist/on same-repo dependabot branches and pushes the result back — reworked per review so the write credential never coexists with dependency code:repack-dist(no secrets): checks out the PR head SHA withpersist-credentials: false, installs withnpm ci --ignore-scripts, builds, packs, and uploadsdist/as an artifact only when it drifted. The bumped dependency code that runs here can read nothing.push-repacked-dist(no npm): mints a short-lived App token (actions/create-github-app-token), refuses to proceed if the branch moved since the rebuild, downloads the artifact, refuses any change outsidedist/, and pushes with--force-with-lease. Nocontents: writeis requested onGITHUB_TOKEN.Gated on
github.event.pull_request.user.login == 'dependabot[bot]'and a same-repo head.Maintainer setup required: create (or reuse) a GitHub App with
contents: write, install it on this repository, and store its id/key as the Dependabot secretsREPACK_APP_ID/REPACK_APP_PRIVATE_KEY(dependabot-triggered runs only see Dependabot secrets). Pushing with the App token is also what re-triggersbuild-teston the new commit.Follow-ups noted from review, not in this PR: a tag ruleset or an on-main check in
release.ymlto constrain what any compromised credential could ship. If the maintainers prefer the simpler route (keep the gate, hand-runnpm run pack), this PR can be dropped — #411 carries the js-yaml move independently.The js-yaml move was split out to #411 per review.
Fixes #171
Testing
npm ci --ignore-scripts && npm run build && npm run packon a clean checkout — reproduces the committeddist/byte-for-byte (git status --porcelain dist/empty), so the no-scripts rebuild is soundtest.ymlparses cleanly (js-yamlload; jobs:build-test,repack-dist,push-repacked-dist)Checklist
npm run allto lint and build my code — not applicable, workflow-onlynpm run packand committeddist/— not applicable,dist/unchangedactions/download-artifact,actions/create-github-app-token