@@ -2,6 +2,17 @@ name: Publish to NPM
22on :
33 release :
44 types : [published]
5+ workflow_dispatch :
6+ inputs :
7+ dry_run :
8+ description : ' Dry run only (no actual publish)'
9+ required : false
10+ default : ' true'
11+ type : choice
12+ options :
13+ - ' true'
14+ - ' false'
15+
516permissions :
617 contents : read
718 id-token : write
@@ -16,21 +27,52 @@ jobs:
1627 egress-policy : audit
1728
1829 - uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
19- # Setup .npmrc file to publish to npm
2030 - uses : actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
2131 with :
2232 node-version : ' 24'
2333 registry-url : ' https://registry.npmjs.org'
2434 - run : npm ci
2535 - run : npm run build
2636
27- - name : Check if pre-release and publish to NPM
37+ - name : Determine dist-tag and publish
38+ env :
39+ NODE_AUTH_TOKEN : ${{ secrets.NPM_TOKEN }}
40+ DRY_RUN : ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || 'false' }}
2841 run : |
42+ set -euo pipefail
2943 VERSION=$(node -p "require('./package.json').version")
44+ PKG_NAME=$(node -p "require('./package.json').name")
45+ echo "Publishing $PKG_NAME@$VERSION"
46+
47+ # Build the publish command flags.
48+ PUBLISH_FLAGS=(--access=public)
49+ if [[ "$DRY_RUN" == "true" ]]; then
50+ PUBLISH_FLAGS+=(--dry-run)
51+ echo "DRY RUN — nothing will actually be published."
52+ fi
53+
54+ # Pre-releases (ex: 2.1.0-rc.1) get tagged as 'rc'
3055 if [[ "$VERSION" == *"-"* ]]; then
31- echo "Publishing pre-release: $VERSION"
32- npm publish --access=public --tag rc
56+ echo "Pre-release detected, publishing under 'rc' tag"
57+ npm publish "${PUBLISH_FLAGS[@]}" --tag rc
58+ exit 0
59+ fi
60+
61+ # Look up current 'latest' on NPM. If never published before,
62+ # defaults to 0.0.0 so any release (0.1.0, 1.0.0, etc.) becomes latest
63+ CURRENT_LATEST=$(npm view "$PKG_NAME" version 2>/dev/null || echo "0.0.0")
64+ echo "Current 'latest' on npm: $CURRENT_LATEST"
65+
66+ # If this version is strictly greater than the current 'latest',
67+ # it becomes latest
68+ if npx --yes semver "$VERSION" -r ">$CURRENT_LATEST" >/dev/null 2>&1; then
69+ echo "Publishing as 'latest'"
70+ npm publish "${PUBLISH_FLAGS[@]}"
3371 else
34- echo "Publishing stable release: $VERSION"
35- npm publish --access=public
72+ # Otherwise, this is a maintenance release on an older line
73+ # Tag as v<major>.<minor> so users can pin to it
74+ MAJOR_MINOR=$(echo "$VERSION" | cut -d. -f1,2)
75+ DIST_TAG="v${MAJOR_MINOR}"
76+ echo "Maintenance release detected, publishing under '$DIST_TAG' tag"
77+ npm publish "${PUBLISH_FLAGS[@]}" --tag "$DIST_TAG"
3678 fi
0 commit comments