From b7b82a76ae0fa57e7fd92c069eeeca6385ec5fb7 Mon Sep 17 00:00:00 2001 From: Daniel McCoy Stephenson Date: Sun, 9 Aug 2026 19:15:47 -0600 Subject: [PATCH] ci: publish a rolling dev prerelease from main Adds dev-release.yml, which rebuilds the JAR on every non-documentation push to main and republishes it as the `dev` prerelease. This is what Dan's Plugin Manager's experimental release channel reads: /dpm get playerlore --experimental fetches releases/tags/dev, so without a workflow like this there is nothing for it to download. The build steps mirror release.yml deliberately. The publish step deletes and recreates the release because editing a published release does not move its tag to the new commit; a concurrency group keeps two runs from overlapping on that delete-and-recreate, and the JAR count is asserted because DPM installs the first .jar asset it finds. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/dev-release.yml | 90 +++++++++++++++++++++++++++++++ CHANGELOG.md | 6 +++ 2 files changed, 96 insertions(+) create mode 100644 .github/workflows/dev-release.yml diff --git a/.github/workflows/dev-release.yml b/.github/workflows/dev-release.yml new file mode 100644 index 0000000..f2af4ed --- /dev/null +++ b/.github/workflows/dev-release.yml @@ -0,0 +1,90 @@ +name: Dev Release + +# Publishes a rolling prerelease of the main branch so that server operators can opt into +# unreleased changes via Dan's Plugin Manager (`/dpm get playerlore --experimental`). +# +# The build steps deliberately mirror release.yml — if the release build changes, change it here too. + +on: + push: + branches: [ main ] + # A documentation-only merge produces an identical JAR, so it is not worth a new prerelease + # (and the release notification it sends to every watcher of this repository). + paths-ignore: + - '**.md' + - 'LICENSE' + workflow_dispatch: + +permissions: + contents: write + +# The publish step deletes and recreates the release, so two runs must never overlap. +# Queue instead of cancelling: a cancelled run could leave the repository with no dev release at all. +concurrency: + group: dev-release + cancel-in-progress: false + +jobs: + dev-release: + runs-on: ubuntu-latest + # Forks have neither the release to publish to nor a reason to publish one. + if: github.repository == 'Dans-Plugins/PlayerLore' + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Build with Maven + run: mvn clean package + + - name: Republish the dev prerelease + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + shopt -s nullglob + + # Dan's Plugin Manager installs the first .jar asset it finds on the release, so publishing + # more than one would leave the installed build depending on asset order. An empty or + # ambiguous match fails the run rather than publishing something unpredictable. + # release.yml publishes target/*.jar minus the shade plugin's original-*.jar; the same + # selection is made here, then asserted to be unambiguous. + jars=() + for jar in target/*.jar; do + case "$(basename "$jar")" in original-*) continue ;; esac + jars+=("$jar") + done + if [ ${#jars[@]} -ne 1 ]; then + echo "Expected exactly one JAR to publish, found ${#jars[@]}: ${jars[*]:-none}" >&2 + exit 1 + fi + + # The dev tag has to move to the new commit. Editing a published release does not move its + # tag, so the release and its tag are deleted and recreated. This leaves a window of a few + # seconds with no dev release; a client that fetches during it sees "no experimental build + # published" and succeeds on the next attempt. + gh release delete dev --yes --cleanup-tag || true + + gh release create dev \ + --prerelease \ + --target "$GITHUB_SHA" \ + --title "Development build" \ + --notes "Automated build of \`main\` at ${GITHUB_SHA}. + + **This is not a release.** It is unreleased, unreviewed code that has not been through any + release check, and a broken build can stop a server from starting. Do not run it on a server + you care about without a backup. + + Install it with Dan's Plugin Manager: + + \`\`\` + /dpm get playerlore --experimental + \`\`\` + + Return to published releases with \`/dpm get playerlore --stable\`." \ + "${jars[0]}" diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f468ea..1656435 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## [Unreleased] + +### Added + +- A `Dev Release` workflow, which republishes a rolling `dev` prerelease of `main` on every non-documentation push. This is what Dan's Plugin Manager's experimental channel installs from: `/dpm get playerlore --experimental` reads `releases/tags/dev`, so without it there is nothing for that command to download. The prerelease is unreleased, unreviewed code and is marked as such. + ## [2.0.0-SNAPSHOT-8-8-2026] – 2026-08-08 ### Changed