Skip to content

Publish Package to NPM #172

Publish Package to NPM

Publish Package to NPM #172

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.
#
# Stable tags such as v0.39.2 publish to npm's latest dist-tag.
# Prerelease tags such as v0.40.0-clarke.1 publish to a matching
# channel dist-tag (clarke) and create a GitHub prerelease.
# Prereleases must never become latest.
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 and resolve npm dist-tag
id: version
run: |
if [ "${GITHUB_REF_TYPE:-}" != "tag" ]; then
echo "Publish must run from a git tag. Current ref type: ${GITHUB_REF_TYPE:-unknown}" >&2
exit 1
fi
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
IS_PRERELEASE=false
NPM_DIST_TAG=latest
if [[ "$TAG_VERSION" == *-* ]]; then
IS_PRERELEASE=true
PRERELEASE_SUFFIX="${TAG_VERSION#*-}"
PRERELEASE_SUFFIX="${PRERELEASE_SUFFIX%%+*}"
NPM_DIST_TAG="${PRERELEASE_SUFFIX%%.*}"
if [ -z "$NPM_DIST_TAG" ] || [ "$NPM_DIST_TAG" = "latest" ]; then
echo "Invalid prerelease npm dist-tag: '$NPM_DIST_TAG'" >&2
exit 1
fi
if [[ "$NPM_DIST_TAG" =~ ^v?[0-9] ]]; then
echo "Invalid prerelease npm dist-tag '$NPM_DIST_TAG': dist-tags must not look like versions." >&2
exit 1
fi
fi
echo "Tag $GITHUB_REF_NAME matches package.json $PKG_VERSION."
echo "npm dist-tag: $NPM_DIST_TAG"
echo "is_prerelease=$IS_PRERELEASE" >> "$GITHUB_OUTPUT"
echo "npm_dist_tag=$NPM_DIST_TAG" >> "$GITHUB_OUTPUT"
- run: npm run build
- name: Publish to npm
run: npm publish --provenance --access public --tag "${{ steps.version.outputs.npm_dist_tag }}"
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_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
NOTES="$NOTES
npm install -g genlayer@${{ steps.version.outputs.npm_dist_tag }}"
RELEASE_FLAGS=()
if [ "${{ steps.version.outputs.is_prerelease }}" = "true" ]; then
RELEASE_FLAGS+=(--prerelease)
fi
gh release create "$GITHUB_REF_NAME" \
--title "$GITHUB_REF_NAME" \
--notes "$NOTES" \
"${RELEASE_FLAGS[@]}"