Skip to content

ci: stage releases on npm for 2FA approval instead of publishing directly - #52

Merged
chhoumann merged 2 commits into
mainfrom
ci/staged-publishing
Oct 24, 2026
Merged

chhoumann merged 2 commits into
mainfrom
ci/staged-publishing

Conversation

@chhoumann

Copy link
Copy Markdown
Owner

Switches obsidian-e2e to npm staged publishing, the same change as chhoumann/obsidian-test-kit#7.

What changes:

  • Release script. release is now npm stage publish --provenance instead of changeset publish. CI uploads each version privately with a provenance attestation, and it goes public only after a maintainer runs npm stage approve <stage-id> with 2FA. The stage ID is in the Release workflow log under "Stage on npm". A compromised workflow run can therefore stage a version but never publish one.
  • Skip guard. The publish job skips when package.json's version is already on npm. changeset publish did that check itself, and staging an existing version is a hard error, so without the guard every push to main with no pending changesets would fail.
  • npm version. The job uses the npm bundled with Node 24 (11.19.1 on the current 24.22.1). npm stage shipped in 11.15.0.
  • README. The README and .changeset/README.md now describe the approval step and the stage-only trusted publisher.
  • bin path. A separate commit changes the bin path from ./dist/runner/bin.mjs to dist/runner/bin.mjs. npm normalizes to that form anyway, and it warned on every publish that the bin entry was "invalid and removed". The message is misleading, since npm keeps the entry, and the installed binary is the same.

I ran pnpm run release:check locally and it passes: vp check is clean and 404 tests pass. A local npm stage publish --provenance --dry-run with an empty userconfig packs the expected 30 files and errors on the already-published 0.15.0, which is the case the guard handles.

This only takes effect once the npmjs.com setting changes. On the obsidian-e2e package's Trusted Publisher, untick "Allow npm publish". Until then, CI stages and the publisher could still publish directly.

npm normalizes bin paths without it and warned on every publish that the
entry was invalid. The installed binary is unchanged.
…ctly

The trusted publisher should only allow npm stage publish, so a release
from CI stays private until a maintainer approves it with 2FA. A
compromised workflow run can no longer put a version in front of users.
Staging an existing version is an error, so the job skips versions
already on npm. Mirrors chhoumann/obsidian-test-kit#7.
@chhoumann
chhoumann merged commit f47aee8 into main Oct 24, 2026
1 check passed
@chhoumann
chhoumann deleted the ci/staged-publishing branch October 24, 2026 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant