Skip to content

Release

Release #6

Workflow file for this run

name: Release
on:
workflow_dispatch:
inputs:
increment:
description: "Version increment. Leave empty to infer it from the conventional commits since the last tag."
required: false
default: ""
type: choice
options:
- ""
- patch
- minor
- major
dry-run:
description: "Run release-it without publishing, pushing or tagging."
required: false
default: false
type: boolean
permissions:
contents: write
pull-requests: write
jobs:
release:
name: Publish to npm
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
# conventional-changelog needs the tags and every commit since the
# last one to work out the bump and the changelog entries.
fetch-depth: 0
- uses: pnpm/action-setup@v4
# No `registry-url` here on purpose: it writes an `.npmrc` holding a
# literal `${NODE_AUTH_TOKEN}`, which the package-manager probes behind
# `cache:` choke on. The Release step below writes the token itself.
- uses: actions/setup-node@v7
with:
node-version-file: .nvmrc
cache: pnpm
# `prepare` builds, so this already produces `build/` once.
- run: pnpm install --frozen-lockfile
- run: pnpm run lint
- run: pnpm run format
- run: pnpm run typecheck
- run: pnpm run test
- run: pnpm run build
# Publishes to npm, pushes the annotated tag and creates the GitHub
# release. The version bump commit stays local, see .release-it.cjs.
- name: Release
id: release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
INCREMENT: ${{ inputs.increment }}
DRY_RUN: ${{ inputs.dry-run }}
run: |
git config user.email "gabrielstaveira@gmail.com"
git config user.name "Gabriel Taveira"
npm config set //registry.npmjs.org/:_authToken "$NPM_TOKEN"
args="--ci"
if [ -n "$INCREMENT" ]; then
args="$args --increment=$INCREMENT"
fi
if [ "$DRY_RUN" = "true" ]; then
args="$args --dry-run"
fi
pnpm run release $args
echo "version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT"
# master requires status checks and a fresh commit has none, so the bump
# has to arrive as a PR. Merge commit, not squash: the tag points at the
# bump commit, and squashing would rewrite it and leave the tag off
# master's history, which breaks the next release's changelog range.
#
# v1.0.11 needed its two check runs approved by hand before auto-merge
# would fire. GitHub held them as `action_required` because
# `github-actions[bot]` had no merged PR here yet and the fork-PR approval
# policy was `first_time_contributors`. The policy is now
# `first_time_contributors_new_to_github` and the bot has a merged PR, so
# this shouldn't recur. If a release PR sits with no checks reported, that
# is what happened: approve the runs on the Actions tab, or
# `gh api -X POST repos/OWNER/REPO/actions/runs/RUN_ID/approve`.
# npm, the tag and the GitHub release are already out at that point, so
# only the bump on master is waiting.
- name: Land the version bump on master
if: ${{ !inputs.dry-run }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.release.outputs.version }}
BASE: ${{ github.ref_name }}
REPO: ${{ github.repository }}
run: |
branch="chore/release-v$VERSION"
git push origin "HEAD:refs/heads/$branch"
cat > /tmp/pr-body.md <<BODY
Version bump and changelog for [v$VERSION](https://github.com/$REPO/releases/tag/v$VERSION), opened by the release workflow. npm and the tag are already out; this lands the commit the tag points at.
Auto-merges as a merge commit once CI and CodeQL pass. A squash would rewrite the commit and leave the tag outside master's history, which breaks the changelog range for the next release.
BODY
# npm and the tag are already out by this point, so a failure here
# leaves master a version behind the registry. The usual cause is
# "Allow GitHub Actions to create and approve pull requests" being
# off, and the GITHUB_TOKEN has no scope to read that setting, so say
# what to do rather than let a bare GraphQL error stand.
if ! url=$(gh pr create --base "$BASE" --head "$branch" \
--title "chore(release): v$VERSION" --body-file /tmp/pr-body.md 2>&1); then
echo "$url"
echo "::error::v$VERSION is on npm and tagged, but the bump PR could not be opened, so master is behind. The branch $branch is pushed: open a PR from it and merge with a merge commit, not a squash. If the error mentions Actions not being permitted to create pull requests, turn that on under Settings > Actions > General."
exit 1
fi
number="${url##*/}"
echo "opened $url"
# The merge commit lands on master too, so it needs a conventional
# subject. `.release-it.cjs` filters `chore(release)` out of the
# changelog, so neither this nor the bump commit shows up next time.
gh pr merge "$number" --auto --merge --delete-branch \
--subject "chore(release): v$VERSION (#$number)" --body ""