Skip to content

Prepare release

Prepare release #1

name: Prepare release
# Manually-triggered: bumps every version-bearing file and writes the
# CHANGELOG.md entry (from conventional-commit subjects since the previous
# tag) on a release/vX.Y.Z branch, then opens a PR against main. main is
# ruleset-protected, so this cannot push or tag directly — merging the PR is
# the approval gate. Once merged, .github/workflows/release-publish.yml tags
# the merge commit and creates the GitHub Release automatically.
on:
workflow_dispatch:
inputs:
version:
description: 'New version, semver without a leading "v" (e.g. 0.3.0)'
required: true
type: string
permissions:
contents: write
pull-requests: write
concurrency:
group: release
cancel-in-progress: false
jobs:
prepare:
runs-on: ubuntu-latest
steps:
- name: Ensure running from main
run: |
if [ "${{ github.ref }}" != "refs/heads/main" ]; then
echo "::error::Run this workflow from the main branch (got ${{ github.ref }})."
exit 1
fi
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
fetch-tags: true
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '22'
- name: Validate version and compute previous tag
run: |
VERSION="${{ inputs.version }}"
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::version must be semver X.Y.Z with no leading 'v' (got '$VERSION')."
exit 1
fi
if git rev-parse "v$VERSION" >/dev/null 2>&1; then
echo "::error::tag v$VERSION already exists."
exit 1
fi
if git ls-remote --exit-code --heads origin "release/v$VERSION" >/dev/null 2>&1; then
echo "::error::branch release/v$VERSION already exists on origin."
exit 1
fi
PREV_TAG="$(git describe --tags --abbrev=0 2>/dev/null || true)"
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
echo "PREV_TAG=$PREV_TAG" >> "$GITHUB_ENV"
echo "Preparing v$VERSION (previous tag: ${PREV_TAG:-none})"
- name: Generate changelog section
run: |
node .github/scripts/generate-changelog-entry.mjs "$PREV_TAG" "$VERSION" > /tmp/section.md
cat /tmp/section.md
- name: Insert changelog section
run: |
node .github/scripts/insert-changelog-entry.mjs CHANGELOG.md /tmp/section.md "$VERSION" "${{ github.repository }}"
- name: Bump package versions
run: |
for dir in . dashboard .github/actions/report; do
(cd "$dir" && npm version "$VERSION" --no-git-tag-version --allow-same-version)
done
- name: Update README action-usage pins
run: |
sed -i -E "s#(\.github/actions/report@v)[0-9]+\.[0-9]+\.[0-9]+#\1${VERSION}#g" \
README.md .github/actions/report/README.md
- name: Commit release changes
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git checkout -b "release/v$VERSION"
git add \
package.json package-lock.json \
dashboard/package.json dashboard/package-lock.json \
.github/actions/report/package.json .github/actions/report/package-lock.json \
CHANGELOG.md README.md .github/actions/report/README.md
git commit -m "chore(release): v$VERSION"
git push origin "release/v$VERSION"
- name: Open release PR
env:
GH_TOKEN: ${{ github.token }}
run: |
gh pr create \
--base main \
--head "release/v$VERSION" \
--title "chore(release): v$VERSION" \
--body-file /tmp/section.md