From dad50151caa7e4beaf853df67fdf64231e624e2f Mon Sep 17 00:00:00 2001 From: Christian Bager Bach Houmann Date: Sat, 24 Oct 2026 16:03:12 +0200 Subject: [PATCH 1/2] build: drop the leading ./ from the bin path npm normalizes bin paths without it and warned on every publish that the entry was invalid. The installed binary is unchanged. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5b553bb..14eb62a 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "url": "git+https://github.com/chhoumann/obsidian-e2e.git" }, "bin": { - "obsidian-e2e": "./dist/runner/bin.mjs" + "obsidian-e2e": "dist/runner/bin.mjs" }, "files": [ "dist" From 0565e02070507e0cccef4ea8d2622032757cfe59 Mon Sep 17 00:00:00 2001 From: Christian Bager Bach Houmann Date: Sat, 24 Oct 2026 16:03:12 +0200 Subject: [PATCH 2/2] ci: stage releases on npm for 2FA approval instead of publishing directly 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. --- .changeset/README.md | 4 +++- .github/workflows/release.yml | 10 ++++++++-- README.md | 7 +++++-- package.json | 2 +- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/.changeset/README.md b/.changeset/README.md index e8a9155..0c591c3 100644 --- a/.changeset/README.md +++ b/.changeset/README.md @@ -6,4 +6,6 @@ Add a changeset with: vp exec changeset ``` -Merging the resulting release PR on `main` is what triggers the publish workflow. +Merging the resulting release PR on `main` makes the publish workflow stage the +new version on npm. It goes public once a maintainer approves it with +`npm stage approve ` (2FA), using the stage ID from the workflow log. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 784b3f6..2b55fa1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -76,5 +76,11 @@ jobs: - name: Validate release run: pnpm run release:check - - name: Publish to npm - run: pnpm run release + - name: Stage on npm + run: | + version="$(node -p "require('./package.json').version")" + if [ -n "$(npm view "obsidian-e2e@$version" version 2>/dev/null)" ]; then + echo "obsidian-e2e@$version is already published" + exit 0 + fi + pnpm run release diff --git a/README.md b/README.md index 054a724..96b0fa8 100644 --- a/README.md +++ b/README.md @@ -896,12 +896,15 @@ At a high level: `.obsidian-e2e-artifacts` so maintainers can inspect the same failure snapshots produced locally. - Releases go through Changesets PRs. Merge the version PR that - Changesets opens, then let the release workflow publish to npm. + Changesets opens, and the release workflow stages the version on npm. It + goes public once a maintainer approves it with `npm stage approve + ` (2FA). Maintainer setup notes: - Configure npm trusted publishing for this package and repository so the - GitHub release workflow can publish without a long-lived npm token. + GitHub release workflow can stage releases without a long-lived npm token. + Allow only `npm stage publish` on the trusted publisher, not `npm publish`. - Grant the publish job `id-token: write` so GitHub can mint the OIDC token npm expects, and keep the release workflow permissions aligned with the write actions it needs, such as `contents: write` and `pull-requests: write` for diff --git a/package.json b/package.json index 14eb62a..20eab09 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "check": "vp check", "changeset": "changeset", "dev": "vp pack --watch", - "release": "changeset publish", + "release": "npm stage publish --provenance", "release:check": "vp check && vp test && vp pack", "test": "vp test", "typecheck": "tsc --noEmit",