Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 39 additions & 13 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: Release
# Publishes a GitHub release with a zip and a tar.gz of the server.
# - On master: when package.json has a version that has no release yet (merge a "Release x.y.z" PR).
# - On a v* tag pushed by hand: releases that tag (package.json must match it).
on:
push:
branches: [master]
tags: ['v*']
permissions:
contents: write
Expand All @@ -9,28 +13,50 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Work out the version
id: version
env:
GH_TOKEN: ${{ github.token }}
run: |
version="v$(node -p "require('./package.json').version")"
echo "tag=$version" >> "$GITHUB_OUTPUT"
if [ "$GITHUB_REF_TYPE" = "tag" ]; then
test "$version" = "$GITHUB_REF_NAME" \
|| { echo "package.json says $version, tag is $GITHUB_REF_NAME"; exit 1; }
echo "publish=true" >> "$GITHUB_OUTPUT"
elif gh release view "$version" > /dev/null 2>&1; then
echo "$version is already released, nothing to do."
echo "publish=false" >> "$GITHUB_OUTPUT"
else
echo "publish=true" >> "$GITHUB_OUTPUT"
fi
- uses: actions/setup-node@v7
if: steps.version.outputs.publish == 'true'
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run lint
- run: npm test
- name: Check that package.json matches the tag
run: |
test "v$(node -p "require('./package.json').version")" = "$GITHUB_REF_NAME" \
|| { echo "package.json says $(node -p "require('./package.json').version"), tag is $GITHUB_REF_NAME"; exit 1; }
- if: steps.version.outputs.publish == 'true'
run: npm ci && npm run lint && npm test
- name: Build the archive
if: steps.version.outputs.publish == 'true'
env:
TAG: ${{ steps.version.outputs.tag }}
run: |
git archive --format=zip --prefix="MCScript-${GITHUB_REF_NAME}/" -o "MCScript-${GITHUB_REF_NAME}.zip" "$GITHUB_REF_NAME"
git archive --format=tar.gz --prefix="MCScript-${GITHUB_REF_NAME}/" -o "MCScript-${GITHUB_REF_NAME}.tar.gz" "$GITHUB_REF_NAME"
git archive --format=zip --prefix="MCScript-${TAG}/" -o "MCScript-${TAG}.zip" HEAD
git archive --format=tar.gz --prefix="MCScript-${TAG}/" -o "MCScript-${TAG}.tar.gz" HEAD
- name: Take the release notes from CHANGELOG.md
run: node scripts/release-notes.js "${GITHUB_REF_NAME#v}" > notes.md
if: steps.version.outputs.publish == 'true'
env:
TAG: ${{ steps.version.outputs.tag }}
run: node scripts/release-notes.js "${TAG#v}" > notes.md
- name: Publish the release
if: steps.version.outputs.publish == 'true'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.version.outputs.tag }}
run: |
flags=""
case "$GITHUB_REF_NAME" in *-*) flags="--prerelease" ;; esac
gh release create "$GITHUB_REF_NAME" MCScript-*.zip MCScript-*.tar.gz \
--title "MCScript ${GITHUB_REF_NAME#v}" --notes-file notes.md $flags
case "$TAG" in *-*) flags="--prerelease" ;; esac
# creates the tag on this commit when it doesn't exist yet
gh release create "$TAG" MCScript-*.zip MCScript-*.tar.gz \
--target "$GITHUB_SHA" --title "MCScript ${TAG#v}" --notes-file notes.md $flags
30 changes: 16 additions & 14 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Releasing a new version

Every version is published as a GitHub release with a zip and a tar.gz of the server, the way MCGalaxy does
it. The release workflow (`.github/workflows/release.yml`) does the work once a version tag is pushed.
it. The release workflow (`.github/workflows/release.yml`) does the work when a new version reaches `master`.

## Version numbers

Expand All @@ -17,23 +17,25 @@ update check doesn't announce them to servers on a final release.
## Steps

1. Make sure CI is green on `master`.
2. In `CHANGELOG.md`, rename the `## Unreleased` section to the new version and date, for example
`## 2.1.0 (2026-11-02)`, and start a new empty `## Unreleased` section above it.
2. On a new branch, rename the `## Unreleased` section of `CHANGELOG.md` to the new version and date, for
example `## 2.2.0 (2026-11-02)`, and start a new empty `## Unreleased` section above it.
3. Update the version in `package.json` and `package-lock.json`:
```bash
npm version 2.1.0 --no-git-tag-version
```
4. Commit both files with the message `Release 2.1.0` and push to `master`.
5. Tag the commit and push the tag:
```bash
git tag v2.1.0
git push origin v2.1.0
npm version 2.2.0 --no-git-tag-version
```
4. Commit both files as `Release 2.2.0`, open a pull request and merge it once CI passes.

That's it. When `master` gets a `package.json` version that has no release yet, the release workflow runs
the lint and tests, creates the `v2.2.0` tag on that commit, builds `MCScript-v2.2.0.zip` and `.tar.gz`
(without the tests and GitHub files) and publishes the release with the changelog section as its notes. The
release appears under **Releases** a couple of minutes after the merge. Merges that don't change the version
don't publish anything.

Pushing a `v*` tag by hand also works: the workflow then releases that tag, as long as `package.json` has the
same version.

The workflow then runs the lint and tests, checks that the tag matches `package.json`, builds
`MCScript-v2.1.0.zip` and `.tar.gz` (without the tests and GitHub files) and creates the release with the
changelog section as its notes. If something fails, fix it, delete the tag (`git push --delete origin v2.1.0`,
`git tag -d v2.1.0`) and tag again.
If the workflow fails, fix the cause and merge the fix; the next push to `master` tries again, since that
version still has no release.

Servers running an older version print a message in the console with a link to the new release when they start
(unless `checkForUpdates` is off).
Loading