feat(release): publish to npm from the tag, with provenance - #157
Merged
Conversation
npm drifted from the git tags because publishing was a manual step: v0.14.1 was tagged and had a GitHub Release, but was never pushed to npm, so `npx dvalincode` served 0.14.0 until someone happened to check. The README now leads with `npx dvalincode dvalin .`, which makes that drift a user-visible break rather than an inconvenience. Pushing a version tag now publishes to npm as well. Two guards: - The tag must match package.json, so a mismatched version fails loudly instead of publishing something no release points at. - A version already on the registry is skipped with a notice rather than failing the build, so re-running a release (a moved tag, a retried job) stays green. Moving the v0.15.0 tag today would have hit exactly this. `--provenance` ties the published tarball to the workflow run, giving the npm artifact the same traceability the release archives get from the attest job. `prepublishOnly` still re-runs the build and full check first. Every publishing job is tag-gated, so `workflow_dispatch` remains a safe dry run. The header comment is updated — it described a flow where npm was someone's job to remember. Requires an NPM_TOKEN repository secret. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Summary
Publishing to npm was a manual step, and it was already missed once: v0.14.1 was tagged and had a GitHub Release, but was never published to npm, so
npx dvalincodeserved 0.14.0 for a month until it happened to get checked during the 0.15.0 release.That used to be an inconvenience. Now that the README leads with
npx dvalincode dvalin ., a missed publish means the first command on the front page is broken — so the hand-off moves into the workflow.Pushing a version tag now builds, produces the Evidence Pack, attests, publishes the GitHub Release, and publishes to npm.
Guards
Two, both of which map to things that actually happened this week:
package.json. A mismatch fails loudly rather than publishing a version no release points at. Relevant because the version lives in two separate constants (package.jsonandsrc/version.ts) —src/version.tswas still on 0.14.1 during the 0.15.0 prep and would have shipped a CLI that misreported itself.v0.15.0tag today would have hit exactly this case, since 0.15.0 was already on the registry.--provenanceties the published tarball to the workflow run, giving the npm artifact the same traceability the release archives get from theattestjob.prepublishOnlystill re-runsnpm run build && npm run checkbefore anything leaves the runner.Every publishing job is tag-gated (
startsWith(github.ref, 'refs/tags/')), soworkflow_dispatchremains a safe dry run.Testing
The two guard conditions were exercised against the live registry before wiring them in:
npm view dvalincode@0.15.0(published)npm view dvalincode@9.9.9(absent)v0.15.0vspackage.json0.15.0v0.99.0vspackage.json0.15.0Workflow YAML parses; all four jobs and their
ifgates confirmed.The publish path itself cannot be exercised without the secret and a real tag — the first live run will be the next release.
Security and AI Governance
docs/.docs/governance/AI-CHANGE-IMPACT-ASSESSMENT.md.Second box: this is release security. The workflow header documented a flow where npm was a human's job to remember, and that comment is now corrected in the same commit; no separate evidence doc covers the release runbook.
Third box, deliberately unticked: this does add an outbound flow — the release pipeline now pushes a tarball to registry.npmjs.org — and grants
id-token: writeto the new job for provenance. It involves no model, provider, or agent tool, so the assessment template does not fit, but a reviewer should weigh those two facts on their own terms.Notes — action required before this helps
Add an
NPM_TOKENrepository secret (Settings → Secrets and variables → Actions). It must be an npm Automation token; Automation tokens bypass 2FA on publish, which a CI publish requires.Until the secret exists, the npm job will fail on the next tag while everything else still succeeds.
Unrelated but urgent: the token intended for this was pasted in plaintext into a chat transcript. It should be revoked on npmjs.com and replaced with a freshly generated one before being added as a secret.