Skip to content

Publish Package to NPM #165

Publish Package to NPM

Publish Package to NPM #165

Workflow file for this run

name: Publish Package to NPM
# Tag-driven publish. The release is cut by a human (or Claude via the
# release skill) running scripts/release.sh on the target stable branch
# — that script bumps package.json, updates CHANGELOG.md, commits,
# tags vX.Y.Z, and pushes both the branch commit and the tag. This
# workflow fires on the tag push, sanity-checks the tag matches
# package.json, builds, publishes to npm, and creates the GitHub
# Release. It never bumps or tags by itself.
on:
workflow_dispatch:
push:
tags:
- "v*"
permissions:
contents: write
id-token: write
jobs:
publish:
runs-on: ubuntu-latest
environment: Publish
steps:
- name: Checkout tag
uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"
- run: npm ci
- name: Verify tag matches package.json version
run: |
TAG_VERSION="${GITHUB_REF_NAME#v}"
PKG_VERSION="$(node -p "require('./package.json').version")"
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
echo "Tag ($TAG_VERSION) and package.json ($PKG_VERSION) disagree — refusing to publish." >&2
echo "Re-cut the release via scripts/release.sh so the tag and the committed version match." >&2
exit 1
fi
echo "Tag $GITHUB_REF_NAME matches package.json $PKG_VERSION."
- run: npm run build
- name: Publish to npm
run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
NOTES="$(awk -v ver="$GITHUB_REF_NAME" '
$0 ~ "^## \\[?" substr(ver, 2) {capture=1; next}
capture && /^## / {exit}
capture {print}
' CHANGELOG.md)"
if [ -z "$NOTES" ]; then
NOTES="Release $GITHUB_REF_NAME"
fi
gh release create "$GITHUB_REF_NAME" \
--title "$GITHUB_REF_NAME" \
--notes "$NOTES"