diff --git a/.github/RELEASING.md b/.github/RELEASING.md index 8700d7d84..d1c1c66da 100644 --- a/.github/RELEASING.md +++ b/.github/RELEASING.md @@ -2,63 +2,115 @@ [Semantic Versioning 2.0.0 reference](https://github.com/semver/semver/blob/master/semver.md) +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 prereleases use generated tags like `pre-YYYYMMDDHHMMSS-`. +- Reserve manual semver tags like `v0.10.x` for a future stable-release process if needed. + ### 1. New Feature or Breaking‑Change Release (Minor/Major) 1. **Merge & Verify** + - Merge all feature or breaking‑change PRs into `master`. - Ensure CI (tests, linter, codegen) all pass on `master`. -2. **Determine Version Bump** +1. **Determine Version Bump** + - **Major** (`X.0.0`) when you make incompatible changes - **Minor** (`0.Y.0`) when you add functionality in a backward compatible manner - **Patch** (`0.0.Z`) when you make backward compatible bug fixes -3. **Create Git Tag** - ```bash - git tag vX.Y.Z - git push origin vX.Y.Z - ``` - This triggers the `Release` workflow. +1. **Merge to `master`** + - Merging to `master` triggers the `Release` workflow automatically. -4. **Monitor Release** + Or, for a manual test without merging: + - Run the `Release` workflow with `workflow_dispatch`. + - Optionally provide a short `release_label` such as `test`. + +2. **Monitor Release** - GitHub Actions will: - Run `go generate ./...` - - Build artifacts with `main.version=vX.Y.Z` - - Zip as `go-mud-release-vX.Y.Z.zip` - - Publish the GitHub Release for `vX.Y.Z` - -5. **Announce** + - Build per-platform binaries with `main.version` set from `main.go` + - Create a generated prerelease tag like `pre-YYYYMMDDHHMMSS-` + - Archive `_datafiles` as `go-mud-datafiles-pre-YYYYMMDDHHMMSS-.zip` + - Generate `go-mud-pre-YYYYMMDDHHMMSS--SHA256SUMS.txt` + - Publish a GitHub prerelease for that generated tag + - Leave the release unmarked as `Latest` + +3. **Announce** + - After review, a repo owner can edit the release in GitHub and promote it to + `Latest`. - Share the release link with the team or via configured notifications. --- -### 2. Basic Patch Release (x.y.Z) +### 2. Merge-Driven Prerelease Policy + +1. **Pull requests do not publish release binaries** + - PRs should run normal CI only. + +2. **Merges to `master` do publish release binaries** + - A push to `master` runs the `Release` workflow and publishes a prerelease. -1. **Merge Bug‑Fix PR** - - Once the fix is in `master` and CI is green. +3. **Manual test runs can also publish prereleases** + - `workflow_dispatch` can be used to create a test prerelease without merging. + - An optional `release_label` is appended to the generated prerelease tag. -2. **Determine Patch Bump** - ```bash - # if current version is vX.Y.Z: - git tag vX.Y.(Z+1) - git push origin vX.Y.(Z+1) - ``` +4. **Generated release naming** + - The release tag is generated automatically from UTC time plus the merge commit SHA. + - Example: `pre-20260417021530-1a2b3c4` + - With a manual label: `pre-20260417021530-1a2b3c4-test` -3. **Tag & Push** - - Pushing the tag triggers the same release workflow. +--- + +### 3. Manual Test Release Flow + +1. **Run the release workflow manually** + - Use `workflow_dispatch` when you want a test release + without merging to `master`. + - Optionally set `release_label=test` or similar to make the generated tag clearer. + +2. **Verify the GitHub release** + - Confirm the workflow succeeds. + - Confirm the per-platform binaries are attached. + - Confirm the `_datafiles` zip asset is attached. + - Confirm the checksum manifest asset is attached. + - Confirm GitHub marks the release as a prerelease. + - Confirm GitHub does not mark it as `Latest`. -4. **Publish** - - The workflow publishes the release automatically after the build completes. +3. **Clean up if needed** + - Delete the test tag and release after validation if you do not want to keep them + in repository history. --- ### FAQ / Guidelines - **Does every merge to `master` trigger a release?** - No - only pushing a Git tag matching `v*.*.*` triggers a release. + Yes - every push to `master` runs the release workflow and publishes a prerelease. - **Is auto-tagging enabled?** - No - releases are manual. Create and push the version tag yourself when you want to publish. + Stable semver tags are not generated automatically. The merge-driven workflow creates + its own prerelease tag from UTC time plus commit SHA. + +- **Can I create a test release without merging to `master`?** + Yes - run the `Release` workflow manually with `workflow_dispatch`. That keeps PR + submissions clean while still allowing on-demand test releases. + +- **Are workflow-created releases stable releases?** + No - the workflow creates prereleases. A repo owner must manually promote a release + to `Latest` in GitHub when it is approved. + +- **What assets should a release include?** + Each release should include separate per-platform binaries, a `_datafiles` zip, + and a checksum manifest so testers can download only what they need and still + verify the assets. + +- **What tag format should we use going forward?** + Keep the source/binary version on the `0.10.x` line. Let the workflow generate + prerelease tags like `pre-YYYYMMDDHHMMSS-` on merges to `master`. - **When should I bump minor vs. patch?** - **Minor** for new, backward‑compatible features. diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml index b32f22818..2e06a465b 100644 --- a/.github/workflows/build-and-release.yml +++ b/.github/workflows/build-and-release.yml @@ -3,8 +3,14 @@ name: Release "on": push: - tags: - - 'v*.*.*' + branches: + - master + workflow_dispatch: + inputs: + release_label: + description: Optional prerelease label suffix, e.g. test or rc + required: false + type: string concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -13,13 +19,57 @@ concurrency: permissions: contents: write -env: - RELEASE_FILENAME: go-mud-release - RELEASE_VERSION: ${{ github.ref_name }} - jobs: + prep: + runs-on: ubuntu-24.04 + outputs: + binary_version: ${{ steps.meta.outputs.binary_version }} + release_tag: ${{ steps.meta.outputs.release_tag }} + datafiles_archive: ${{ steps.meta.outputs.datafiles_archive }} + checksums_file: ${{ steps.meta.outputs.checksums_file }} + steps: + - uses: actions/checkout@v6.0.2 + with: + persist-credentials: false + + - name: Compute release metadata + id: meta + env: + RELEASE_LABEL: ${{ inputs.release_label }} + run: | + binary_version="$( + sed -n 's/^const VERSION = \"\\([^\"]*\\)\"$/\\1/p' main.go + )" + if [ -z "$binary_version" ]; then + echo "Could not determine binary version from main.go" >&2 + exit 1 + fi + + release_stamp="$(date -u +%Y%m%d%H%M%S)" + release_tag="pre-${release_stamp}-${GITHUB_SHA::7}" + release_label="${RELEASE_LABEL:-}" + if [ -n "$release_label" ]; then + case "$release_label" in + *[!A-Za-z0-9._-]*) + echo "release_label must match [A-Za-z0-9._-]+" >&2 + exit 1 + ;; + esac + release_tag="${release_tag}-${release_label}" + fi + + { + echo "binary_version=${binary_version}" + echo "release_tag=${release_tag}" + echo "datafiles_archive=gomud-ALL-datafiles-${release_tag}.zip" + echo "checksums_file=gomud-${release_tag}-SHA256SUMS.txt" + } >> "$GITHUB_OUTPUT" + build: runs-on: ubuntu-24.04 + needs: prep + env: + BINARY_VERSION: ${{ needs.prep.outputs.binary_version }} steps: - uses: actions/checkout@v6.0.2 with: @@ -41,32 +91,32 @@ jobs: - name: Build windows amd64 run: >- env GOOS=windows GOARCH=amd64 go build -v - -ldflags "-X main.version=${{ env.RELEASE_VERSION }}" - -o bin/go-mud-windows_x64.exe . + -ldflags "-X main.version=${{ env.BINARY_VERSION }}" + -o bin/gomud-windows_x64.exe . - name: Build darwin/arm64 run: >- env GOOS=darwin GOARCH=arm64 go build -v - -ldflags "-X main.version=${{ env.RELEASE_VERSION }}" - -o bin/go-mud-darwin_arm64 . + -ldflags "-X main.version=${{ env.BINARY_VERSION }}" + -o bin/gomud-darwin_arm64 . - name: Build darwin/amd64 run: >- env GOOS=darwin GOARCH=amd64 go build -v - -ldflags "-X main.version=${{ env.RELEASE_VERSION }}" - -o bin/go-mud-darwin_x64 . + -ldflags "-X main.version=${{ env.BINARY_VERSION }}" + -o bin/gomud-darwin_x64 . - name: Build linux/amd64 run: >- env GOOS=linux GOARCH=amd64 go build -v - -ldflags "-X main.version=${{ env.RELEASE_VERSION }}" - -o bin/go-mud-linux_x64 . + -ldflags "-X main.version=${{ env.BINARY_VERSION }}" + -o bin/gomud-linux_x64 . - name: Build linux/arm5 run: >- env GOOS=linux GOARCH=arm GOARM=5 go build -v - -ldflags "-X main.version=${{ env.RELEASE_VERSION }}" - -o bin/go-mud-linux_arm5 . + -ldflags "-X main.version=${{ env.BINARY_VERSION }}" + -o bin/gomud-linux_arm5 . - name: Upload bin uses: actions/upload-artifact@v4 @@ -76,7 +126,13 @@ jobs: release: runs-on: ubuntu-24.04 - needs: build + needs: + - prep + - build + env: + RELEASE_TAG: ${{ needs.prep.outputs.release_tag }} + DATAFILES_ARCHIVE: ${{ needs.prep.outputs.datafiles_archive }} + CHECKSUMS_FILE: ${{ needs.prep.outputs.checksums_file }} steps: - name: Download builds uses: actions/download-artifact@v4 @@ -84,17 +140,38 @@ jobs: name: bin-artifact path: bin/ - - name: Archive release + - name: Archive datafiles run: >- zip -r - bin/${{ env.RELEASE_FILENAME }}-${{ env.RELEASE_VERSION }}.zip - bin/ + bin/${{ env.DATAFILES_ARCHIVE }} + bin/_datafiles + + - name: Generate release checksums + run: | + cd bin + sha256sum \ + gomud-windows_x64.exe \ + gomud-darwin_arm64 \ + gomud-darwin_x64 \ + gomud-linux_x64 \ + gomud-linux_arm5 \ + "${{ env.DATAFILES_ARCHIVE }}" \ + > "${{ env.CHECKSUMS_FILE }}" - name: Release with notes - uses: softprops/action-gh-release@v3.0.0 - with: - files: bin/${{ env.RELEASE_FILENAME }}-${{ env.RELEASE_VERSION }}.zip - tag_name: ${{ env.RELEASE_VERSION }} - fail_on_unmatched_files: true + run: | + gh release create "$RELEASE_TAG" \ + bin/gomud-windows_x64.exe \ + bin/gomud-darwin_arm64 \ + bin/gomud-darwin_x64 \ + bin/gomud-linux_x64 \ + bin/gomud-linux_arm5 \ + "bin/$DATAFILES_ARCHIVE" \ + "bin/$CHECKSUMS_FILE" \ + --title "$RELEASE_TAG" \ + --target "$GITHUB_SHA" \ + --prerelease \ + --latest=false \ + --generate-notes env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 12ffcec33..6a82dc3cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .vscode +bin/ private-notes.txt _datafiles/**/users/* _datafiles/**/plugin-data/*