Repository navigation
S0349-astm-10: publish a dependency inventory with each release - #89
Merged
Merged
Conversation
Produce a CycloneDX inventory of what a build was made from, refuse it unless it is true of that build, and attach it to the version's GitHub release as a downloadable asset. scripts/check-dependency-inventory.ts reads the package identity from package.json and the resolved set from pnpm-lock.yaml, writes the artifact into the gitignored dist-artifacts/, then grades it: missing, empty, unparseable, identity-less, version-mismatched or short of a resolved dependency are each refused by name with a non-zero status, and a produce-side refusal removes any stale artifact rather than leaving one to be read as this build's. The guard runs in prepublishOnly, before the registry upload, so a bad inventory costs a failed run instead of a published version nothing describes. The attach is a second job in this repo's release workflow, because the shared pipeline attaches a fixed two-name asset list and declares no workflow_call outputs; it runs after the publish because the release does not exist before one, finds the release from the tag at the published commit, and fails its run rather than skipping quietly when the asset does not arrive. No runtime source changes, so no per-directory coverage gate moves and no exported value, type or emitted byte is touched.
…tern CodeQL js/redos on scripts/check-dependency-inventory.ts. The repeated group opened with [-+] while its own character class also carried -, so a near miss such as 0.0.0+ followed by repetitions of -- backtracked exponentially: 1.2ms to reject at 27 characters, 9.0ms at 35, 99ms at 39, 704ms at 43, and a 59-character input did not finish in three minutes. That is reachable rather than theoretical. The text comes from a lockfile key, which is to say from a registry, and this script runs in the publishing path. Each tail is now optional rather than repeated, and the prerelease class can no longer swallow the +, so the split is decided by the first + and there is nothing to backtrack over. Flat at 0.017ms on a 2007-character input, and it accepts and rejects identically on every input that matters. No test added: the subject is performance rather than a criterion, and CodeQL already holds it.
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.
Spec:
pipeline/active/S0349-astm-10/spec.md(umbrella)Each published version now carries a machine-readable inventory of what that build was made from,
produced and graded by this repo, and retrievable from that version's release page without cloning
anything.
What is here
scripts/check-dependency-inventory.tsproduces a CycloneDX 1.6 document into the gitignoreddist-artifacts/dependency-inventory.cdx.jsonand then grades it. The resolved set is read frompnpm-lock.yamlrather than from the manifest's two lists, because the manifest states rangeswhile a build resolves versions. No subprocess, no network call, no registry credential.
missing,empty,unparseable,identity,version,incomplete. A produce-side refusal also removes any stale artifact at that path, soan older inventory can never be attached as this build's.
prepublishOnlygainspnpm check:dependency-inventory. That is the side of the npm publishwhere a refusal keeps the version off the registry.
pnpm checkgains the same command, so producing and grading it is reachable from a checkout..github/workflows/release.ymlattaches the artifact to the release the sharedpipeline cut. It is a job here because that pipeline attaches a fixed two-name asset list and
declares no
workflow_calloutputs; it finds the release from the tag at the published commit,uploads with
--clobberso a re-run attaches to the same release without republishing, reads theasset back, and fails the run rather than skipping quietly if it did not arrive.
test/dependency-inventory.test.ts, 26 cases, each naming the criterion it grades and eachdriving the real script as a subprocess in a throwaway tree.
What is deliberately not here
No runtime source changes, so no
src/directory joins the per-directory coverage gate and noexported value, type, warning code or emitted byte moves. No new dependency of any kind. No
signing, attestation or provenance work: npm provenance remains what it already was. No gate on
what the dependency set contains: this grades that the set is stated truthfully, never that it is
approved.
Field discipline
The artifact ships on a public release page, so it carries the package identity, the component
names, their versions, a
purlper component and the format declaration, and nothing else. Notimestamp, no serial number, no producing-tool record, no path, no integrity hash, no registry URL.
Generation is byte-for-byte deterministic for a given commit.
Gates
pnpm check,pnpm test(71 files, 1246 passed, 4 skipped),pnpm lint,pnpm typecheck,pnpm format:check,pnpm check:no-emdash,pnpm check:no-internal-refsandpnpm phi-scanareall green. A Changeset and a
CHANGELOG.md[Unreleased]entry are included, and the pending-setbookkeeping in
documentation/release-readiness.mdis updated so its gate stays green.Three criteria (the asset on a real release page, a real re-run after a failed attach, and the
observed ordering on a real publish) can only be graded on a publish this change does not trigger.