Skip to content

Release release/0.5.8 #36

Release release/0.5.8

Release release/0.5.8 #36

Workflow file for this run

# Auto-release to npm from version tags or release-branch merges on main.
#
# The workflow publishes in three ways:
# 1. A merged PR from a `release/vX.Y.Z` branch into `main` (the normal
# path — branch name and `package.json` are both validated against
# each other). `gh release create` pushes the tag as a side effect;
# the subsequent tag-push run is short-circuited by the "already on
# npm" check, so there is no infinite loop.
# 2. A `vX.Y.Z` tag push to `main` (escape hatch / re-publish path —
# tag must match `package.json`).
# 3. A manual `workflow_dispatch` (re-publish / same-version dry test).
#
# PR pushes to a `release/v*` branch, force-pushes, and merges of any
# other branch do NOT publish.
#
# Required repo secret: NPM_TOKEN (npm "Automation" access token with publish
# rights for the `orbcode` package).
name: Release
# Per-run title:
# - tag push → "Release v0.3.1"
# - PR merge → "Release release/v0.3.1"
# - dispatch → "Release v0.3.1" if `version` input set, else "Release manual"
# `run-name` only sees github.* and inputs.* — package.json can't be read here.
run-name: >-
Release ${{
github.event_name == 'push' && github.ref_name ||
github.event_name == 'pull_request' && github.event.pull_request.head.ref ||
(inputs.version && format('v{0}', inputs.version)) || 'manual'
}}
on:
push:
tags:
- "v*"
pull_request:
types:
- closed
branches:
- main
workflow_dispatch:
inputs:
version:
description: "Version to publish (must match package.json). Leave empty to read from package.json."
required: false
type: string
permissions:
contents: write # create the GitHub Release
id-token: write # npm --provenance (requires a public GitHub repo)
concurrency:
group: release
cancel-in-progress: false
jobs:
release:
runs-on: ubuntu-latest
if: |
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) ||
(github.event_name == 'pull_request'
&& github.event.pull_request.merged == true
&& github.event.pull_request.base.ref == 'main'
&& startsWith(github.event.pull_request.head.ref, 'release/v')) ||
(github.event_name == 'workflow_dispatch')
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org
cache: npm
- name: Install
run: npm ci
- name: Resolve and verify version
id: version
run: |
set -euo pipefail
PKG_VERSION=$(node -p "require('./package.json').version")
NAME=$(node -p "require('./package.json').name")
EVENT="${{ github.event_name }}"
if [ "$EVENT" = "push" ]; then
# Tag push: REF is refs/tags/vX.Y.Z
TAG_VERSION=${GITHUB_REF#refs/tags/v}
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
echo "::error::Tag v$TAG_VERSION does not match package.json version $PKG_VERSION."
echo "::error::Update package.json (and this tag) to publish a coherent release."
exit 1
fi
VERSION="$TAG_VERSION"
elif [ "$EVENT" = "pull_request" ]; then
# Merged release branch: derive version from head_ref (release/vX.Y.Z)
# and require it to match the bumped package.json.
HEAD_REF="${{ github.event.pull_request.head.ref }}"
BRANCH_VERSION=${HEAD_REF#release/v}
if [ -z "$BRANCH_VERSION" ] || [ "$BRANCH_VERSION" = "$HEAD_REF" ]; then
echo "::error::PR head ref '$HEAD_REF' is not a release/vX.Y.Z branch."
exit 1
fi
if [ "$BRANCH_VERSION" != "$PKG_VERSION" ]; then
echo "::error::Branch version $BRANCH_VERSION does not match package.json version $PKG_VERSION."
echo "::error::Rename the branch to release/v$PKG_VERSION (or update package.json) so they agree."
exit 1
fi
VERSION="$BRANCH_VERSION"
else
# Manual dispatch: prefer the input, fall back to package.json.
VERSION="${{ inputs.version }}"
if [ -z "$VERSION" ]; then
VERSION="$PKG_VERSION"
fi
if [ "$VERSION" != "$PKG_VERSION" ]; then
echo "::error::Input version $VERSION does not match package.json version $PKG_VERSION."
exit 1
fi
fi
echo "name=$NAME" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Typecheck & build
run: |
npm run typecheck
npm run build
- name: Check whether this version is already on npm
id: check
run: |
NAME="${{ steps.version.outputs.name }}"
VERSION="${{ steps.version.outputs.version }}"
if npm view "$NAME@$VERSION" version >/dev/null 2>&1; then
echo "Version $VERSION already published — skipping."
echo "publish=false" >> "$GITHUB_OUTPUT"
else
echo "publish=true" >> "$GITHUB_OUTPUT"
fi
- name: Publish to npm
if: steps.check.outputs.publish == 'true'
# Drop --provenance if the repository is private (provenance needs a
# public repo and a `repository` field in package.json).
run: npm publish --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Create GitHub Release
if: steps.check.outputs.publish == 'true'
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.version.outputs.version }}
run: |
TARGET_SHA="${{ github.sha }}"
# For tag pushes, also publish from the tagged commit itself.
if [ "${{ github.event_name }}" = "push" ]; then
TARGET_SHA="$GITHUB_REF"
fi
gh release create "v$VERSION" \
--title "orbcode v$VERSION" \
--generate-notes \
--target "$TARGET_SHA" \
|| echo "Release v$VERSION already exists."