build(publish): gate npm publish on the suite, and rebuild dist at pack time - #23
Merged
Conversation
…ck time
`npm publish` shipped whatever `dist/` happened to be on the publishing machine.
Nothing forced a rebuild and nothing ran the tests, so a stale, partial or
locally-patched `dist/` would go to the registry as-is and the tarball would not
be derivable from any commit. On a package whose entire purpose is redacting
credentials, that means the security claim rested on the publisher checking by
hand — which is diligence, not a property of the package.
I paid that cost twice tonight publishing 0.1.5: typecheck and the suite run
manually, on the exact published tree rather than on my branch, because there was
no gate. The next publisher would have neither the gate nor a reason to suspect
one was missing.
Two hooks, because the task names two distinct hazards:
prepublishOnly bun run typecheck && bun run test refuses to publish a red tree
prepack bun run build guarantees dist is a clean
rebuild from source
`build` already opens with `rm -rf dist`, so `prepack` makes the shipped artefact
a function of the commit rather than of the machine. `prepack` also covers
`npm pack`, so a tarball someone inspects is built the same way as one that ships.
VERIFIED IN BOTH DIRECTIONS, because a gate that cannot block is the thing this
change exists to remove rather than to add:
POSITIVE — dist DELETED on purpose, then `npm publish --dry-run`: prepublishOnly
ran (typecheck and suite output present), prepack rebuilt dist from source, and
the pack contained all 24 files including dist/index.js. The rc=1 there is
`cannot publish over the previously published versions: 0.1.5`, which is the
registry refusing a duplicate version, not the gate.
NEGATIVE — a scratch copy at an unpublished version 99.99.99, so the gate is the
only possible failure source, with one deliberately false assertion planted:
`npm publish --dry-run` exits 1 at `prepublishOnly`, the planted failure is what
stops it, and `total files` appears ZERO times — it is refused BEFORE a tarball
is built.
Gates on this tree: typecheck rc=0, bun test rc=0, build rc=0.
SIBLING SURVEY, which the task asked for rather than fixing this package in
isolation. Probed 60 of the 165 first-party packages enumerated in the bunfig
excludes inventory, reading each package's PUBLISHED scripts from the registry
rather than a local checkout:
prepublishOnly present 36
prepublishOnly ABSENT 16
not published 8
no build-at-pack hook 37
The 36 are the positive control: the same probe finds the hook where it exists, so
"absent" is an observation and not a broken read. The survey is alphabetically
bounded and stopped at 60 — every one of the 16 falls between `access` and
`entities`, so that is a SAMPLE and the true count is higher. Filed separately
with the names rather than fixed here.
Refs: todos 4efcbd8a
Agent: aemilius
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes todos
4efcbd8a. Two lines inpackage.json, no source change.npm publishshipped whateverdist/happened to be on the publishing machine. Nothing forced a rebuild and nothing ran the tests, so a stale, partial or locally-patcheddist/would reach the registry as-is and the tarball would not be derivable from any commit. On a package whose entire purpose is redacting credentials, the security claim then rests on the publisher checking by hand.I paid that cost twice tonight publishing
0.1.5— typecheck and the suite run manually, on the exact published tree rather than on my branch. The next publisher would have neither the gate nor a reason to suspect one was missing.The change
prepublishOnlybun run typecheck && bun run testprepackbun run builddist/that is not a clean rebuild from sourcebuildalready opens withrm -rf dist, soprepackmakes the shipped artefact a function of the commit rather than of the machine. It also coversnpm pack, so a tarball someone inspects is built the same way as one that ships.Verified in both directions
A gate that cannot block is the thing this change exists to remove, not to add — so both states were exercised.
POSITIVE —
dist/deleted on purpose, thennpm publish --dry-run:prepublishOnlyran (typecheck and suite output present in the log)prepackrebuiltdistfrom sourcedist/index.jsrc=1there iscannot publish over the previously published versions: 0.1.5— the registry refusing a duplicate version, not the gateNEGATIVE — scratch copy at unpublished version
99.99.99, so the gate is the only possible failure source, with one deliberately false assertion planted:npm publish --dry-runexits 1 atprepublishOnlytotal filesappears zero times — refused before a tarball is builtGates on this tree:
typecheckrc=0,bun testrc=0,buildrc=0.Sibling survey — the task asked for this rather than fixing one package in isolation
Probed 60 of the 165 first-party packages in the bunfig excludes inventory, reading each package's published scripts from the registry rather than a local checkout:
The 36 are what make "absent" an observation rather than a broken read.
Scope, not completeness. The survey is alphabetically bounded and stopped at 60 — every one of the 16 falls between
accessandentities, so this is a sample and the true count is higher. Filed separately with the names; not fixed here, because sixteen packages' publish behaviour does not belong in ataiPR.Refs: todos
4efcbd8aNeed help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.