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
16 changes: 10 additions & 6 deletions .github/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@ Recommended versioning for the next release line:

- Start the next stable release at `v0.10.0`.
- Keep the binary's embedded version in source as a normal semver such as `0.10.0`.
- Let merge-driven builds update a single rolling `prerelease` tag.
- Let merge-driven builds update a rolling `prerelease` entry using generated
immutable tags.
- Reserve stable semver tags like `v0.10.0` for protected stable releases.

### Prerelease

1. Merge to `master`.
2. The `Prerelease` workflow runs tests, builds the seven supported binaries,
assembles `gomud-ALL-datafiles.zip` and `SHA256SUMS.txt`, generates
attestations, and updates the mutable `prerelease` GitHub prerelease.
3. The workflow may move the `prerelease` tag and clobber existing prerelease
assets. This is intentional so the rolling prerelease remains mutable.
attestations, and publishes a new GitHub prerelease named `prerelease`.
3. The workflow uses a generated tag such as
`prerelease-123456789-1` for the new prerelease, then removes older
rolling prerelease releases and tags. Prerelease tags are not force-moved, so
normal developer `git pull` commands do not fail on tag clobber conflicts.
4. The prerelease is marked as a prerelease and is not marked as `Latest`.

Pull requests do not publish release binaries. The generic `CI` workflow runs
Expand All @@ -39,8 +42,9 @@ workflow to avoid duplicate full race-test runs on merge.
Registry image.

Stable release workflow policy does not move tags, use `--clobber`, or replace
existing releases. Keep repository-wide immutable releases disabled so the
rolling `prerelease` release can remain mutable.
existing releases. The rolling prerelease workflow also avoids moving tags, but
it still replaces the visible prerelease entry by creating a new generated tag
and deleting older rolling prerelease releases.

### Assets

Expand Down
10 changes: 2 additions & 8 deletions .github/scripts/release-notes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,8 @@ if [ "${RELEASE_NOTES_SKIP_GH:-}" = "true" ]; then
printf 'Generated release notes skipped for local dry run.\n' \
>"$generated_notes_file"
else
notes_tag="$release_tag"
if [ "$release_kind" = "prerelease" ]; then
# GitHub ignores target_commitish when tag_name already exists.
notes_tag="${release_tag}-notes-${commit_sha}"
fi

generate_notes_args=(
-f "tag_name=${notes_tag}"
-f "tag_name=${release_tag}"
-f "target_commitish=${commit_sha}"
)
if [ -n "$previous_tag" ] && [ "$previous_tag" != "$release_tag" ]; then
Expand All @@ -75,7 +69,7 @@ published_at="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"

if [ "$release_kind" = "prerelease" ]; then
overview="Rolling prerelease build from \`${ref_name:-master}\`."
summary="This mutable prerelease is replaced on each successful merge to \`master\`."
summary="The rolling prerelease entry is replaced on each successful merge to \`master\`, using a generated tag for this build."
else
overview="Stable release \`${release_tag}\`."
summary="This stable release is immutable. Tags and assets are not replaced by workflow policy."
Expand Down
133 changes: 120 additions & 13 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,92 @@ permissions:
security-events: write

jobs:
analyze:
name: Analyze (${{ matrix.language }})
changes:
name: Detect CodeQL Inputs
runs-on: ubuntu-24.04
timeout-minutes: 5
outputs:
go: ${{ steps.detect.outputs.go }}
javascript_typescript: ${{ steps.detect.outputs.javascript_typescript }}
steps:
# actions/checkout v6.0.3
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10
with:
fetch-depth: 0
persist-credentials: false

- name: Detect changed CodeQL inputs
id: detect
env:
BEFORE_SHA: ${{ github.event.before }}
EVENT_NAME: ${{ github.event_name }}
run: |
set -euo pipefail

go_changed=false
js_changed=false

if [ "$EVENT_NAME" = "schedule" ]; then
go_changed=true
js_changed=true
else
zero_sha=0000000000000000000000000000000000000000
if git rev-parse --verify --quiet HEAD^2 >/dev/null; then
diff_base=HEAD^1
diff_head=HEAD^2
elif [ -n "${BEFORE_SHA}" ] &&
[ "${BEFORE_SHA}" != "${zero_sha}" ]; then
diff_base="${BEFORE_SHA}"
diff_head=HEAD
else
diff_base=HEAD^
diff_head=HEAD
fi

mapfile -t changed_files < <(
git diff --name-only "$diff_base" "$diff_head"
)

for file in "${changed_files[@]}"; do
case "$file" in
.github/workflows/codeql.yml | .github/codeql/*)
go_changed=true
js_changed=true
;;
*.go | go.mod | go.sum | Makefile | \
.github/actions/setup-go/* | .github/actions/go-checks/*)
go_changed=true
;;
_datafiles/html/admin/static/js/monaco* | \
_datafiles/html/admin/static/js/highlight.js | \
_datafiles/html/admin/static/css/monaco-editor.css | \
_datafiles/html/public/static/js/xterm/*)
;;
*.html | *.htm | *.js | *.jsx | *.ts | *.tsx | *.mjs | *.cjs | \
package.json | package-lock.json | npm-shrinkwrap.json | \
yarn.lock | pnpm-lock.yaml)
js_changed=true
;;
esac
done
fi

{
echo "go=${go_changed}"
echo "javascript_typescript=${js_changed}"
} >> "$GITHUB_OUTPUT"

analyze-go:
name: Analyze (go)
needs: changes
if: >-
${{
github.event_name == 'schedule' ||
needs.changes.outputs.go == 'true'
}}
runs-on: ubuntu-24.04
# Keep analyzer regressions from tying up a runner indefinitely.
timeout-minutes: 30
strategy:
# Run both languages so one analyzer failure does not hide the other.
fail-fast: false
matrix:
language:
- go
- javascript-typescript

steps:
# actions/checkout v6.0.3
Expand All @@ -52,13 +126,11 @@ jobs:
# yamllint disable-line rule:line-length
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e
with:
languages: ${{ matrix.language }}
languages: go
# Path filters live in CodeQL config, not workflow event filters.
config-file: ./.github/codeql/codeql-config.yml

- name: Autobuild
# JavaScript/TypeScript is interpreted here; only Go needs autobuild.
if: matrix.language == 'go'
# github/codeql-action v4.36.2
# yamllint disable-line rule:line-length
uses: github/codeql-action/autobuild@8aad20d150bbac5944a9f9d289da16a4b0d87c1e
Expand All @@ -69,4 +141,39 @@ jobs:
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e
with:
# Keep separate code scanning result categories for each language.
category: "/language:${{ matrix.language }}"
category: "/language:go"

analyze-javascript-typescript:
name: Analyze (javascript-typescript)
needs: changes
if: >-
${{
github.event_name == 'schedule' ||
needs.changes.outputs.javascript_typescript == 'true'
}}
runs-on: ubuntu-24.04
# Keep analyzer regressions from tying up a runner indefinitely.
timeout-minutes: 30

steps:
# actions/checkout v6.0.3
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10
with:
persist-credentials: false

- name: Initialize CodeQL
# github/codeql-action v4.36.2
# yamllint disable-line rule:line-length
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e
with:
languages: javascript-typescript
# Path filters live in CodeQL config, not workflow event filters.
config-file: ./.github/codeql/codeql-config.yml

- name: Perform CodeQL Analysis
# github/codeql-action v4.36.2
# yamllint disable-line rule:line-length
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e
with:
# Keep separate code scanning result categories for each language.
category: "/language:javascript-typescript"
66 changes: 38 additions & 28 deletions .github/workflows/prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ name: Prerelease
branches:
- master

# Prerelease is intentionally mutable: each successful merge to master replaces
# the existing prerelease assets and moves the prerelease tag forward.
# The prerelease entry is intentionally rolling: each successful merge to master
# replaces the existing prerelease assets. The Git tags are unique per workflow
# attempt so normal developer fetches do not fail on a force-moved tag.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
Expand Down Expand Up @@ -110,7 +111,8 @@ jobs:
id-token: write
attestations: write
env:
RELEASE_TAG: prerelease
RELEASE_TAG: prerelease-${{ github.run_id }}-${{ github.run_attempt }}
RELEASE_TAG_PREFIX: prerelease
RELEASE_TITLE: prerelease
BINARY_VERSION: ${{ needs.metadata.outputs.binary_version }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down Expand Up @@ -162,32 +164,40 @@ jobs:
.github/scripts/release-assets.sh upload-paths
)

# Move the lightweight prerelease tag when it already exists. If it
# does not exist, gh release create will create it at this commit.
mapfile -t old_release_tags < <(
gh release list \
--limit 100 \
--json isPrerelease,tagName \
--jq '.[] | select(
.isPrerelease
and (
.tagName == "prerelease"
or (.tagName | startswith("prerelease-"))
)
) | .tagName'
)

gh release create "$RELEASE_TAG" \
"${assets[@]}" \
--title "$RELEASE_TITLE" \
--target "$GITHUB_SHA" \
--prerelease \
--latest=false \
--notes-file release-notes.md

for old_tag in "${old_release_tags[@]}"; do
if [ "$old_tag" = "$RELEASE_TAG" ]; then
continue
fi
gh release delete "$old_tag" --yes --cleanup-tag
done

# Remove a retired mutable prerelease tag even if it is not attached
# to a release anymore.
if gh api \
"repos/${GITHUB_REPOSITORY}/git/ref/tags/${RELEASE_TAG}" \
"repos/${GITHUB_REPOSITORY}/git/ref/tags/${RELEASE_TAG_PREFIX}" \
>/dev/null 2>&1; then
gh api \
-X PATCH \
"repos/${GITHUB_REPOSITORY}/git/refs/tags/${RELEASE_TAG}" \
-f "sha=${GITHUB_SHA}" \
-F force=true
fi

if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then
gh release upload "$RELEASE_TAG" "${assets[@]}" --clobber
gh release edit "$RELEASE_TAG" \
--title "$RELEASE_TITLE" \
--target "$GITHUB_SHA" \
--prerelease \
--latest=false \
--notes-file release-notes.md
else
gh release create "$RELEASE_TAG" \
"${assets[@]}" \
--title "$RELEASE_TITLE" \
--target "$GITHUB_SHA" \
--prerelease \
--latest=false \
--notes-file release-notes.md
-X DELETE \
"repos/${GITHUB_REPOSITORY}/git/refs/tags/${RELEASE_TAG_PREFIX}"
fi
6 changes: 3 additions & 3 deletions _datafiles/guides/running/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ or choose a numbered release for a permanent versioned build.

You can download a build from the [releases page](https://github.com/GoMudEngine/GoMud/releases),
unzip it and run the binary to get started, or if you prefer to build it
yourself, follow the instructions below. Use `prerelease` for the newest
`master` build, or a numbered release if you want a stable version you can
return to later.
yourself, follow the instructions below. Use the rolling `prerelease` entry for
the newest `master` build, or a numbered release if you want a stable version
you can return to later.

A youtube playlist to getting started has been set up here:

Expand Down