Skip to content

Release: minor

Release: minor #159

Workflow file for this run

name: Release
run-name: |
${{ (inputs.dryrun && 'Dry run')
|| format('Release: {0}', (inputs.version == 'custom' && inputs.custom) || inputs.version) }}
on:
workflow_dispatch:
inputs:
dryrun:
description: 'Dry run (no npm publish)'
required: false
type: boolean
default: true
version:
description: 'Version component to update (or "custom" to provide exact version)'
required: true
type: choice
options:
- patch
- minor
- major
- prepatch
- preminor
- premajor
- prerelease
- custom
custom:
description: 'Custom version'
required: false
default: ''
jobs:
setup:
name: Setup
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
contents: write
packages: write
actions: read
outputs:
dryrun: ${{ steps.dryrun.outputs.dryrun }}
publish: ${{ steps.publish.outputs.publish }}
ref: ${{ steps.tag.outputs.tag || github.ref_name || github.event.repository.default_branch }}
tag: ${{ steps.tag.outputs.tag || '' }}
steps:
- name: Validate Workflow Inputs
if: ${{ inputs.version == 'custom' && inputs.custom == '' }}
shell: bash
run: |
echo '::error::No custom version number provided'
exit 1
- id: dryrun
name: Validate Dry Run Event
if: ${{ inputs.dryrun }}
shell: bash
run: echo dryrun=true | tee -a $GITHUB_OUTPUT
- id: publish
name: Validate Publish Event
if: ${{ !inputs.dryrun }}
shell: bash
# Publishing authenticates via npm OIDC trusted publishing, which is
# configured on npmjs.com for this repo + release.yml — no NPM_TOKEN
# secret is required. See the publish job below.
run: echo publish=true | tee -a $GITHUB_OUTPUT
- uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1.12.0
id: app-token
with:
app-id: ${{ vars.PUBLISHER_APP_ID }}
private-key: ${{ secrets.PUBLISHER_SECRET_KEY }}
# Least privilege: the token is only used to checkout and
# `git push --follow-tags` in the Tag Release step below.
permission-contents: write
- name: Checkout Code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
fetch-depth: 0
token: ${{ steps.app-token.outputs.token }}
- name: Setup Neon Environment
uses: ./.github/actions/setup
with:
use-rust: false
- name: Tag Release
if: ${{ !inputs.dryrun }}
id: tag
shell: bash
env:
# Bind the resolved version to an env var so it never expands into the
# shell body — guards against template-injection via `${{ }}` in
# `run:` (a `custom` value could otherwise break out of the quotes).
# Keep this guard in sync with the Update Version steps in build.yml.
VERSION_INPUT: ${{ (inputs.version == 'custom' && inputs.custom) || inputs.version }}
run: |
git config --global user.name $ACTIONS_USER
git config --global user.email $ACTIONS_EMAIL
# Allowlist gate: only npm `version` bump keywords or strict semver
# (with optional `v` prefix and pre-release suffix) get through.
case "$VERSION_INPUT" in
patch|minor|major|prepatch|preminor|premajor|prerelease) ;;
v[0-9]*.[0-9]*.[0-9]*|[0-9]*.[0-9]*.[0-9]*) ;;
v[0-9]*.[0-9]*.[0-9]*-*|[0-9]*.[0-9]*.[0-9]*-*) ;;
*)
echo "Invalid version input: '$VERSION_INPUT' (expected an npm bump keyword or semver)" >&2
exit 1
;;
esac
npm version -m 'v%s' "$VERSION_INPUT"
git push --follow-tags
echo tag=$(git describe --abbrev=0) | tee -a $GITHUB_OUTPUT
build:
name: Build
needs: [setup]
permissions:
contents: write
uses: ./.github/workflows/build.yml
with:
ref: ${{ needs.setup.outputs.ref }}
tag: ${{ needs.setup.outputs.tag }}
update-version: ${{ !!needs.setup.outputs.dryrun }}
version: ${{ (inputs.version == 'custom' && inputs.custom) || inputs.version }}
github-release: ${{ !!needs.setup.outputs.publish }}
publish:
name: Publish
if: ${{ needs.setup.outputs.publish }}
needs: [setup, build]
# GitHub-hosted (not Blacksmith): npm only accepts provenance attestations
# from github-hosted runners (self-hosted is rejected with E422). This job
# only publishes prebuilt tarballs, so it doesn't need Blacksmith — the
# build matrix above stays on Blacksmith.
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # Required for npm OIDC trusted publishing
steps:
- name: Checkout Code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
ref: ${{ needs.setup.outputs.ref }}
persist-credentials: false
# OIDC trusted publishing needs Node >= 22.14 and npm >= 11.5.1, and must
# NOT have a token .npmrc. Use setup-node WITHOUT registry-url (the Neon
# setup action sets registry-url, which writes a //registry/:_authToken
# line that shadows OIDC) — this job only publishes prebuilt tarballs, so
# it needs no Rust toolchain or npm install.
- name: Install Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
- name: Upgrade npm for OIDC trusted publishing
run: npm install -g npm@^11.5.1
- name: Fetch
uses: robinraju/release-downloader@c39a3b234af58f0cf85888573d361fb6fa281534 # v1.10
with:
tag: ${{ needs.setup.outputs.tag }}
fileName: "*.tgz"
out-file-path: ./dist
- name: Publish
shell: bash
# No NODE_AUTH_TOKEN — authenticate via OIDC trusted publishing.
# --provenance generates a signed provenance attestation; the repo is
# public and every package sets repository.url, which provenance needs.
run: |
for p in ./dist/*.tgz ; do
npm publish --access public --provenance "$p"
done