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
186 changes: 186 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
name: Stable Release

# Fires when a vX.Y.Z tag is pushed, or can be triggered manually with a tag.
on:
push:
tags:
- 'v[0-9]*.[0-9]*.[0-9]*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to release (e.g. v2.0.1)'
required: true

jobs:
release:
name: Stable Release
runs-on: ubuntu-latest
permissions:
contents: write # Required for creating the GitHub Release

steps:
# ──────────────────────────────────────────────────────────────────────
# 1. CHECKOUT
# ──────────────────────────────────────────────────────────────────────
- name: Checkout
uses: actions/checkout@v6
with:
# For push:tags: github.ref is the tag ref (e.g. refs/tags/v2.0.1).
# For workflow_dispatch: github.ref is the branch (e.g. refs/heads/main).
# We never use the tag input here because the tag may not exist yet —
# it is created in a later step.
ref: ${{ github.ref }}
fetch-depth: 0

# ──────────────────────────────────────────────────────────────────────
# 2. RESOLVE VERSION
# ──────────────────────────────────────────────────────────────────────
- name: Resolve version from tag
id: meta
run: |
REF="${{ github.event.inputs.tag || github.ref_name }}"
VERSION="${REF#v}"
echo "ref=${REF}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Releasing version: ${VERSION}"

# ──────────────────────────────────────────────────────────────────────
# 3. CREATE TAG (if it doesn't exist yet)
#
# When triggered via workflow_dispatch the tag may not exist yet.
# This step creates and pushes it so the GitHub Release can reference it.
# ──────────────────────────────────────────────────────────────────────
- name: Create and push tag if missing
run: |
REF="${{ steps.meta.outputs.ref }}"
if git rev-parse --verify --quiet "refs/tags/${REF}" > /dev/null; then
echo "Tag ${REF} already exists; skipping creation."
else
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag "${REF}"
git push origin "${REF}"
echo "Created and pushed tag ${REF}."
fi

# ──────────────────────────────────────────────────────────────────────
# 4. BUILD & VERSION
# ──────────────────────────────────────────────────────────────────────
- name: Set up JDK 25
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '25'
cache: maven

- name: Set release version in POM
run: |
mvn -B -ntp versions:set \
-DnewVersion="${{ steps.meta.outputs.version }}" \
-DgenerateBackupPoms=false

- name: Build
run: mvn -B -ntp -DskipTests package

# ──────────────────────────────────────────────────────────────────────
# 5. EXTRACT CHANGELOG
#
# Reads the section for this version from CHANGELOG.md.
# Falls back to a generic message when the section is missing.
# ──────────────────────────────────────────────────────────────────────
- name: Extract changelog for this version
id: changelog
run: |
VERSION="${{ steps.meta.outputs.version }}"
HEADER="## [${VERSION}]"

# Fixed-string match via index() avoids regex issues with dots in versions.
NOTES=$(awk \
-v hdr="$HEADER" \
'/^## \[/ && p { exit }
index($0, hdr) == 1 { p=1; next }
p { print }' \
CHANGELOG.md 2>/dev/null || true)

if [[ -z "$NOTES" ]]; then
NOTES="No changelog entry found for ${VERSION}."
fi

printf '%s\n' "$NOTES" > release-notes.md
echo "=== Release notes preview ===" && cat release-notes.md

# ──────────────────────────────────────────────────────────────────────
# 6. GITHUB RELEASE
# ──────────────────────────────────────────────────────────────────────
- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "${{ steps.meta.outputs.ref }}" \
--title "EzBoost ${{ steps.meta.outputs.version }}" \
--notes-file release-notes.md \
"target/EzBoost-${{ steps.meta.outputs.version }}.jar"

# ──────────────────────────────────────────────────────────────────────
# 7. MODRINTH RELEASE
# ──────────────────────────────────────────────────────────────────────
- name: Release to Modrinth (stable)
uses: Kir-Antipov/mc-publish@v3.3
with:
modrinth-id: hxlosrDv
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
modrinth-featured: true
name: "EzBoost ${{ steps.meta.outputs.version }}"
version: "${{ steps.meta.outputs.version }}"
version-type: release
files: |
target/EzBoost-${{ steps.meta.outputs.version }}.jar
game-versions: ">=1.13"
game-versions-filter: release
loaders: |
bukkit
spigot
paper
folia
changelog-file: release-notes.md
dependencies: |
placeholderapi(optional)
worldguard(optional)

# ──────────────────────────────────────────────────────────────────────
# 8. DISCORD NOTIFICATION
# ──────────────────────────────────────────────────────────────────────
- name: Post Discord notification
env:
DISCORD_WEBHOOK: ${{ secrets.EZBOOST_RELEASE_DISCORD_WEBHOOK }}
run: |
REPO="${{ github.repository }}"
VERSION="${{ steps.meta.outputs.version }}"
GH_URL="https://github.com/${REPO}/releases/tag/${{ steps.meta.outputs.ref }}"
MODRINTH_URL="https://modrinth.com/plugin/ezplugins-ezboost/version/${VERSION}"

# Truncate changelog to fit Discord's 4096-char embed description limit.
CHANGELOG=$(head -c 3800 release-notes.md || true)

PAYLOAD=$(jq -n \
--arg version "$VERSION" \
--arg gh_url "$GH_URL" \
--arg modrinth_url "$MODRINTH_URL" \
--arg changelog "$CHANGELOG" \
'{
embeds: [{
title: ("🚀 EzBoost " + $version + " — Stable Release"),
url: $gh_url,
color: 3447003,
description: $changelog,
fields: [
{ name: "GitHub Release", value: ("[View on GitHub](" + $gh_url + ")"), inline: true },
{ name: "Modrinth", value: ("[Download on Modrinth](" + $modrinth_url + ")"), inline: true }
],
footer: { text: "Stable release" }
}]
}')

curl --fail -s -X POST "$DISCORD_WEBHOOK" \
-H "Content-Type: application/json" \
-d "$PAYLOAD"
26 changes: 20 additions & 6 deletions .github/workflows/smoke-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ on:
env:
PAPER_261_VERSION: "26.1.2" # New MC versioning scheme; uses fill.papermc.io API
FOLIA_VERSION: "26.1.2" # Folia tracks the same MC version as Paper
PAPER_121_VERSION: "1.21.11" # Legacy MC versioning; uses api.papermc.io API
SPIGOT_VERSION: "1.21.11"
BUKKIT_VERSION: "1.21.11"

Expand Down Expand Up @@ -52,7 +53,7 @@ jobs:
strategy:
fail-fast: false
matrix:
server: [paper, folia, spigot, bukkit]
server: [paper, folia, paper-1.21, spigot, bukkit]

steps:
- name: Set up Java 25
Expand Down Expand Up @@ -84,6 +85,17 @@ jobs:
curl -sfLo server.jar "$URL"
echo "Paper 26.1.2 URL: $URL"

# ── Paper 1.21.11 (legacy MC versioning; uses api.papermc.io) ────────
- name: Download Paper ${{ env.PAPER_121_VERSION }}
if: matrix.server == 'paper-1.21'
run: |
LATEST=$(curl -sf \
"https://api.papermc.io/v2/projects/paper/versions/${PAPER_121_VERSION}" \
| jq -r '.builds[-1]')
curl -sfLo server.jar \
"https://api.papermc.io/v2/projects/paper/versions/${PAPER_121_VERSION}/builds/${LATEST}/downloads/paper-${PAPER_121_VERSION}-${LATEST}.jar"
echo "Paper ${PAPER_121_VERSION} build ${LATEST} downloaded"

# ── Folia 26.1.2 (same fill.papermc.io API, project=folia) ───────────
- name: Download Folia ${{ env.FOLIA_VERSION }}
if: matrix.server == 'folia'
Expand Down Expand Up @@ -202,13 +214,15 @@ jobs:
RESULT=fail
break
fi
# Server fully started → all plugins have been enabled without errors.
# "Done (" is more reliable than checking "Enabling EzBoost" because
# some server variants (e.g. Paper 26.1) load worlds before enabling
# plugins, so "Enabling" can appear late.
if grep -qE "Done \([0-9.]" server.log 2>/dev/null; then
# Server fully started — verify EzBoost was actually enabled.
# "Done (" is more reliable than checking "Enabling EzBoost" because
# some server variants (e.g. Paper 26.1) load worlds before enabling
# plugins, so "Enabling" can appear late.
if grep -qE "Done \([0-9.]" server.log 2>/dev/null; then
if grep -qE "$FAIL_PAT" server.log 2>/dev/null; then
RESULT=fail
elif ! grep -q "Enabling EzBoost" server.log 2>/dev/null; then
RESULT=fail # Server started but plugin was never enabled (e.g. incompatible api-version)
else
RESULT=pass
fi
Expand Down
156 changes: 156 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Changelog

All notable changes to EzBoost are documented here.

Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
Versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
Release tags use the `v` prefix (e.g. `v2.0.1`).

---

## [Unreleased]

---

## [2.1.0] - 2026-05-18

### Added

- **Folia compatibility**: EzBoost now supports Folia servers via a `FoliaScheduler` abstraction that routes task scheduling through Folia's `GlobalRegionScheduler` / entity schedulers when the Folia runtime is detected.
- **Boost top leaderboard** (`/boosttop`): tracks and displays the top boost buyers using a Jaloquent-backed persistent storage layer.
- **Jaloquent storage backend**: replaced the previous `BoostStorage` abstraction with a fully Jaloquent-backed `EzBoostRepository` for consistent flat-file persistence across all storage operations.
- **`storage.debug-logging` option** (`storage.yml`, default `false`): suppresses verbose Jaloquent console output (`Queried X rows`, `Saved model…`). Set to `true` to re-enable for debugging.
- **Paper 1.21 smoke-test**: CI matrix now includes Paper 1.21.11 alongside Paper 26.1.2, Folia, Spigot, and Bukkit.

### Changed

- `api-version` lowered from `26.1.2` to `1.13` so the plugin loads on any Spigot/Paper 1.13+ server without an api-version warning or rejection.
- Java compiler target lowered from 25 to 17 for wider JDK compatibility.
- `AsyncChatEvent` (Paper-only) replaced with `AsyncPlayerChatEvent` for Spigot compatibility.
- Plugin version lookup changed from `getPluginMeta().getVersion()` to `getDescription().getVersion()` for broader server compatibility.
- CI smoke-test pass condition now also verifies `Enabling EzBoost` appears in the server log, preventing a false pass when the server starts but rejects the plugin due to an incompatible api-version.

### Fixed

- `YamlDataStore.query()` corrected to handle Jaloquent's flat key format.
- `storage.yml` added to `pom.xml` resource includes so it is correctly packaged.
- Vault is now fully optional: economy class access and listener registration are guarded so the plugin loads cleanly without Vault present.

---

## [2.0.0] - 2026-04-15

### Added

- **Minecraft 26.1.2 support**: updated `api-version` and build toolchain to target Paper MC 26.1.2 / Java 25.
- **9 new PlaceholderAPI placeholders** via an internal PAPI expansion (`EzBoostPlaceholder`): expose active boost info, remaining duration, cooldowns, and more.
- **MiniMessage tag resolvers** (`BoostTagResolvers`): native MiniMessage tags for boost context (name, duration, etc.) wired into all `BoostManager` messages for rich formatting without external placeholders.

### Changed

- CI updated to Java 25.

---

## [1.6.0] - 2026-04-14

### Added

- **11 preset boosts**: waterbreathing, saturation, luck, absorption, slow-falling, miner, warrior, farmer, explorer, xpboost, diver — all available out of the box with sensible defaults in `boosts.yml`.
- **XP boost custom effect** (`XpBoostEffect`): configurable experience multiplier applied for the duration of the boost.
- GUI slots pre-configured for the new preset boosts.

---

## [1.5.6] - 2026-04-01

### Fixed

- PlaceholderAPI registration timing corrected so placeholders are reliably available after server startup.
- `/ezboost about` subcommand output and tab-completion fixed.

---

## [1.5.5] - 2026-03-28

### Added

- **PlaceholderAPI integration**: `EzBoostPlaceholder` expansion exposes boost data to any PAPI-compatible plugin.
- **`/ezboost about` subcommand**: displays plugin version, authors, and resource links.
- **Formatted price placeholder** (`%ezboost_price_formatted%`): presents boost costs in a human-readable currency format.

---

## [1.5.4] - 2026-03-13

### Added

- **`show-effects` GUI option**: configurable toggle to show or hide active potion effects in the boost GUI.
- **Vault economy boost effects**: boosts can now charge players via Vault when activated (`XpBoostEffect` and economy hooks).
- **Cooldown improvements**: per-boost cooldown configuration expanded with additional options.
- CI pipeline to validate configuration and run tests.

---

## [1.5.3] - 2026-01-22

### Fixed

- Removed debug console messages that were printed when no effects were applied to a custom boost.

---

## [1.5.2] - 2026-01-21

### Fixed

- Custom boost definitions now load correctly from `boosts.yml`; a regression in 1.5.1 prevented custom boosts from being registered.

---

## [1.5.1] - 2026-01-21

### Changed

- Tab-completion for `/boost` and `/ezboost` improved: suggestions are now context-aware and include boost names.
- `BoostEffect` records now include a `name` field used in completions and display.

---

## [1.5.0] - 2026-01-20

### Added

- **Admin GUI** (`/ezboost create`): in-game inventory interface for creating and configuring boosts without editing config files directly.

---

## [1.4.0] - 2026-01-13

### Added

- **EzBoost API** (`EzBoostAPI`): public API surface for third-party plugins to query and trigger boosts programmatically.
- **Custom boost events**: `BoostStartEvent` and `BoostEndEvent` fired on the Bukkit event bus so other plugins can react to boost lifecycle changes.

---

## [1.3.0] - 2026-01-12

### Added

- **WorldGuard regional overrides**: define per-region boost behaviour (allow, deny, or override settings) using the built-in override system. WorldGuard is detected automatically as a soft dependency.

### Fixed

- Build version warning in `pom.xml` resolved.

---

## [1.2.0] - 2026-01-02

### Added

- Initial public release of EzBoost.
- Configurable potion boosts with durations, cooldowns, world restrictions, and GUI activation.
- Multi-file configuration (`settings.yml`, `boosts.yml`, `gui.yml`, `messages.yml`, `limits.yml`).
- Vault economy integration for charging players on boost activation.
Loading
Loading