Skip to content

Commit 7a96e6c

Browse files
authored
Validate npm OIDC publishing with a prerelease lane (#8)
Add a release-driven publish workflow that uses GitHub OIDC, verifies the release tag against package.json, and routes prerelease versions to the npm next dist-tag. Bump the package version to 0.1.35-rc.0 so the pipeline can be exercised without moving latest. Constraint: Branch protection requires release validation to flow through the normal PR and main branch path Rejected: Publish 0.1.35 directly to latest | no consumer-facing package change yet Rejected: Skip real publish and rely on dry-run only | does not validate trusted publisher OIDC Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep prerelease versions on the next dist-tag until a consumer-visible package change is ready for latest Tested: npm run build; npm test; npm pack --dry-run Not-tested: End-to-end GitHub Release triggered npm publish via OIDC until merged and released from main
1 parent d37f54c commit 7a96e6c

File tree

3 files changed

+67
-3
lines changed

3 files changed

+67
-3
lines changed

.github/workflows/publish.yml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Publish
2+
3+
on:
4+
release:
5+
types:
6+
- published
7+
8+
permissions:
9+
contents: read
10+
id-token: write
11+
12+
jobs:
13+
publish:
14+
name: Publish package to npm
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v5
19+
20+
- name: Setup Node.js
21+
uses: actions/setup-node@v5
22+
with:
23+
node-version: 22
24+
registry-url: https://registry.npmjs.org
25+
cache: npm
26+
27+
- name: Install dependencies
28+
run: npm ci
29+
30+
- name: Verify release tag matches package version
31+
run: |
32+
node --input-type=module -e "
33+
import { readFileSync } from 'node:fs';
34+
const pkg = JSON.parse(readFileSync('package.json', 'utf8'));
35+
const expected = 'v' + pkg.version;
36+
const actual = process.env.RELEASE_TAG;
37+
if (actual !== expected) {
38+
console.error('Release tag mismatch:', { actual, expected });
39+
process.exit(1);
40+
}
41+
"
42+
env:
43+
RELEASE_TAG: ${{ github.event.release.tag_name }}
44+
45+
- name: Build
46+
run: npm run build
47+
48+
- name: Test
49+
run: npm test
50+
51+
- name: Select npm dist-tag
52+
id: publish_meta
53+
run: |
54+
VERSION=$(node -p "JSON.parse(require('node:fs').readFileSync('package.json', 'utf8')).version")
55+
if [[ "$VERSION" == *-* ]]; then
56+
echo "dist_tag=next" >> "$GITHUB_OUTPUT"
57+
echo "publish_args=--provenance --tag next" >> "$GITHUB_OUTPUT"
58+
else
59+
echo "dist_tag=latest" >> "$GITHUB_OUTPUT"
60+
echo "publish_args=--provenance" >> "$GITHUB_OUTPUT"
61+
fi
62+
63+
- name: Publish to npm
64+
run: npm publish ${{ steps.publish_meta.outputs.publish_args }}

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-devtool-cli",
3-
"version": "0.1.34",
3+
"version": "0.1.35-rc.0",
44
"description": "Agent-first CLI for React component tree inspection, snapshot-aware node debugging, and profiler analysis through a Playwright-managed browser session.",
55
"license": "MIT",
66
"type": "module",

0 commit comments

Comments
 (0)