Skip to content

Publish

Publish #6

Workflow file for this run

name: Publish
on:
workflow_dispatch:
inputs:
version:
description: "Version to publish, for example 0.1.1 or v0.1.1"
required: true
type: string
release_notes:
description: "Optional GitHub Release notes"
required: false
type: string
permissions:
contents: write
id-token: write
concurrency:
group: publish-${{ inputs.version }}
cancel-in-progress: false
jobs:
publish:
name: Tag, release, and publish to npm
runs-on: ubuntu-latest
environment: npm
steps:
- name: Checkout main
uses: actions/checkout@v4
with:
ref: main
fetch-depth: 0
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
registry-url: https://registry.npmjs.org/
- name: Resolve and validate version
env:
INPUT_VERSION: ${{ inputs.version }}
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
VERSION="${INPUT_VERSION#v}"
TAG="v${VERSION}"
PACKAGE_NAME="$(node -p "JSON.parse(require('node:fs').readFileSync('package.json', 'utf8')).name")"
PACKAGE_VERSION="$(node -p "JSON.parse(require('node:fs').readFileSync('package.json', 'utf8')).version")"
if ! VERSION="${VERSION}" node -e "const v = process.env.VERSION; if (!/^[0-9]+\\.[0-9]+\\.[0-9]+(?:-[0-9A-Za-z.-]+)?$/.test(v)) process.exit(1)" ; then
echo "Invalid version: ${INPUT_VERSION}. Use a semver version such as 0.1.1."
exit 1
fi
if [ "${PACKAGE_VERSION}" != "${VERSION}" ]; then
echo "package.json version ${PACKAGE_VERSION} does not match requested version ${VERSION}."
exit 1
fi
if git ls-remote --exit-code --tags origin "refs/tags/${TAG}" >/dev/null 2>&1; then
echo "Git tag ${TAG} already exists."
exit 1
fi
if gh release view "${TAG}" >/dev/null 2>&1; then
echo "GitHub Release ${TAG} already exists."
exit 1
fi
if npm view "${PACKAGE_NAME}@${VERSION}" version --registry https://registry.npmjs.org/ >/dev/null 2>&1; then
echo "npm package ${PACKAGE_NAME}@${VERSION} already exists."
exit 1
fi
{
echo "VERSION=${VERSION}"
echo "TAG=${TAG}"
echo "PACKAGE_NAME=${PACKAGE_NAME}"
} >> "${GITHUB_ENV}"
- name: Install
run: pnpm install --frozen-lockfile
- name: Check and build
run: pnpm check
- name: Verify package contents
run: pnpm pack:dry-run
- name: Create and push git tag
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git tag -a "${TAG}" -m "${PACKAGE_NAME}@${VERSION}"
git push origin "${TAG}"
- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
RELEASE_NOTES: ${{ inputs.release_notes }}
run: |
set -euo pipefail
if [ -n "${RELEASE_NOTES}" ]; then
NOTES_FILE="$(mktemp)"
printf '%s\n' "${RELEASE_NOTES}" > "${NOTES_FILE}"
gh release create "${TAG}" --verify-tag --title "${TAG}" --notes-file "${NOTES_FILE}"
else
gh release create "${TAG}" --verify-tag --title "${TAG}" --generate-notes
fi
- name: Publish to npm
run: npm publish --access public --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}