1- name : 🚀 Release — Tag & Update Version
1+ name : 🚀 Release — Version & Tag
22
3- # Runs when a release/* branch is merged into main.
4- # Reads the version from package.json, updates index.html,
5- # commits the change, tags main, and pushes — triggering
6- # the publish and deploy- docs workflows .
3+ # Merging a release/X.Y.Z branch into main releases X.Y.Z: the version comes from the branch
4+ # name, so nothing is bumped by hand. The workflow sets package.json to that version, dates the
5+ # CHANGELOG heading, commits to main and pushes the tag vX.Y.Z, which runs the publish workflow
6+ # (gate, npm, GitHub Release, docs). It can also be run from the Actions tab with a version typed in .
77
88on :
99 pull_request :
1010 types : [closed]
1111 branches : [main]
12+ workflow_dispatch :
13+ inputs :
14+ version :
15+ description : ' Version to release, e.g. 3.0.1'
16+ required : true
1217
1318jobs :
14- tag :
15- if : github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/')
19+ release :
20+ if : >-
21+ github.event_name == 'workflow_dispatch' ||
22+ (github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/'))
1623 runs-on : ubuntu-latest
1724 permissions :
1825 contents : write
1926 steps :
20- - name : Checkout
27+ - name : Checkout main
2128 uses : actions/checkout@v4
2229 with :
2330 ref : main
@@ -29,40 +36,45 @@ jobs:
2936 with :
3037 node-version : 22
3138
32- - name : Read version from package.json
39+ - name : Version from the branch name (or the input)
3340 id : version
41+ env :
42+ HEAD_REF : ${{ github.event.pull_request.head.ref }}
43+ INPUT_VERSION : ${{ github.event.inputs.version }}
3444 run : |
35- VERSION=$(node -p "require('./package.json').version")
36- echo "Version: $VERSION"
37- if [ -z "$VERSION" ]; then echo "ERROR: version is empty" && exit 1; fi
45+ if [ -n "$INPUT_VERSION" ]; then VERSION="$INPUT_VERSION"; else VERSION="${HEAD_REF#release/}"; fi
46+ VERSION="${VERSION#v}"
47+ if ! echo "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'; then
48+ echo "ERROR: '$VERSION' is not a version. Name the branch release/X.Y.Z." && exit 1
49+ fi
50+ if git ls-remote --exit-code --tags origin "v$VERSION" >/dev/null 2>&1; then
51+ echo "ERROR: tag v$VERSION already exists" && exit 1
52+ fi
53+ echo "Releasing $VERSION"
3854 echo "version=$VERSION" >> "$GITHUB_OUTPUT"
3955
40- - name : Update version in index.html
56+ - name : Set package.json version and date the changelog
4157 run : |
4258 VERSION="${{ steps.version.outputs.version }}"
43- sed -i "s/\"softwareVersion\": \"[^\"]*\"/\"softwareVersion\": \"$VERSION\"/" index.html
59+ npm version "$VERSION" --no-git-tag-version --allow-same-version
60+ # the heading "## 3.0.0 (unreleased …)" or "## Unreleased" becomes "## 3.0.0 (2026-10-02)"
61+ TODAY=$(date -u +%F) VERSION="$VERSION" perl -i -pe \
62+ 's/^## (?=.*unreleased)(?:v?\Q$ENV{VERSION}\E|\[?Unreleased\]?).*$/## $ENV{VERSION} ($ENV{TODAY})/i' CHANGELOG.md
4463
45- - name : Check for changes
46- id : diff
47- run : |
48- if git diff --quiet; then
49- echo "changed=false" >> "$GITHUB_OUTPUT"
50- else
51- echo "changed=true" >> "$GITHUB_OUTPUT"
52- fi
53-
54- - name : Commit version update
55- if : steps.diff.outputs.changed == 'true'
64+ - name : Commit to main
5665 run : |
5766 git config user.name "github-actions[bot]"
5867 git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
5968 git remote set-url origin https://x-access-token:${{ secrets.GH_PAT }}@github.com/${{ github.repository }}
60- git add index.html
61- git commit -m "chore: update version to ${{ steps.version.outputs.version }}"
62- git push
69+ if git diff --quiet; then
70+ echo "package.json and CHANGELOG.md already at ${{ steps.version.outputs.version }}"
71+ else
72+ git add package.json package-lock.json CHANGELOG.md
73+ git commit -m "release: ${{ steps.version.outputs.version }}"
74+ git push origin main
75+ fi
6376
64- - name : Create and push tag
77+ - name : Tag
6578 run : |
66- git remote set-url origin https://x-access-token:${{ secrets.GH_PAT }}@github.com/${{ github.repository }}
6779 git tag "v${{ steps.version.outputs.version }}"
6880 git push origin "v${{ steps.version.outputs.version }}"
0 commit comments