From 1d580220c31f3ee65584426fd610c81f2ecdcbb9 Mon Sep 17 00:00:00 2001 From: Dylan Garvis Date: Sat, 8 Aug 2026 14:32:17 -0400 Subject: [PATCH] ci: add plugin build and release pipeline --- .gitea/workflows/ci.yml | 40 +++++ .gitea/workflows/release.yml | 140 ++++++++++++++++++ README.md | 100 +++++++++++++ design/index.md | 1 + design/log.md | 1 + .../us-007-build-and-release-plugin.md | 18 +-- 6 files changed, 291 insertions(+), 9 deletions(-) create mode 100644 .gitea/workflows/ci.yml create mode 100644 .gitea/workflows/release.yml create mode 100644 README.md diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..90a1762 --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,40 @@ +name: CI + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: gradle + + - name: Validate conventional commits + if: github.event_name == 'pull_request' + run: | + npx -y \ + -p @commitlint/cli \ + -p @commitlint/config-conventional \ + commitlint --from "${{ github.event.pull_request.base.sha }}" --to "${{ github.sha }}" \ + --extends @commitlint/config-conventional + + - name: Build and test + run: ./gradlew clean check jar + + - name: Upload development artifact + uses: actions/upload-artifact@v3 + with: + name: spigot-creeper-fear-${{ github.sha }} + path: build/libs/*.jar + if-no-files-found: error diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..101f676 --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,140 @@ +name: Release + +on: + push: + branches: + - main + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.RELEASE_TOKEN }} + + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: gradle + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Build and test before release + run: ./gradlew clean check + + - name: Capture previous tag + id: previous_tag + run: | + if git describe --tags --abbrev=0 >/dev/null 2>&1; then + echo "value=$(git describe --tags --abbrev=0)" >> "$GITHUB_OUTPUT" + else + echo "value=" >> "$GITHUB_OUTPUT" + fi + + - name: Run semantic-release + env: + GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} + run: | + npx -y \ + -p semantic-release@24.2.9 \ + -p @semantic-release/commit-analyzer@13.0.1 \ + -p @semantic-release/release-notes-generator@14.1.0 \ + semantic-release \ + --branches main \ + --plugins @semantic-release/commit-analyzer,@semantic-release/release-notes-generator + + - name: Capture current tag + id: current_tag + run: | + if git describe --tags --exact-match HEAD >/dev/null 2>&1; then + echo "value=$(git describe --tags --exact-match HEAD)" >> "$GITHUB_OUTPUT" + else + echo "value=" >> "$GITHUB_OUTPUT" + fi + + - name: Resolve release + id: release + env: + PREVIOUS_TAG: ${{ steps.previous_tag.outputs.value }} + CURRENT_TAG: ${{ steps.current_tag.outputs.value }} + run: | + if [ -n "$CURRENT_TAG" ] && [ "$CURRENT_TAG" != "$PREVIOUS_TAG" ]; then + echo "created=true" >> "$GITHUB_OUTPUT" + echo "tag=$CURRENT_TAG" >> "$GITHUB_OUTPUT" + echo "version=${CURRENT_TAG#v}" >> "$GITHUB_OUTPUT" + else + echo "created=false" >> "$GITHUB_OUTPUT" + fi + + - name: Build versioned plugin + if: steps.release.outputs.created == 'true' + env: + VERSION: ${{ steps.release.outputs.version }} + run: ./gradlew clean jar -PreleaseVersion="$VERSION" + + - name: Upload release workflow artifact + if: steps.release.outputs.created == 'true' + uses: actions/upload-artifact@v3 + with: + name: spigot-creeper-fear-${{ steps.release.outputs.version }} + path: build/libs/spigot-creeper-fear-${{ steps.release.outputs.version }}.jar + if-no-files-found: error + + - name: Create Gitea release and upload plugin + if: steps.release.outputs.created == 'true' + env: + GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }} + GITEA_SERVER_URL: ${{ github.server_url }} + REPOSITORY: ${{ github.repository }} + TAG: ${{ steps.release.outputs.tag }} + VERSION: ${{ steps.release.outputs.version }} + PREVIOUS_TAG: ${{ steps.previous_tag.outputs.value }} + run: | + api_url="${GITEA_SERVER_URL}/api/v1" + jar="build/libs/spigot-creeper-fear-${VERSION}.jar" + export RELEASE_BODY + if [ -n "$PREVIOUS_TAG" ]; then + RELEASE_BODY=$(git log --pretty='format:- %s (%h)' "${PREVIOUS_TAG}..HEAD") + else + RELEASE_BODY=$(git log --pretty='format:- %s (%h)' HEAD) + fi + payload=$(node -e ' + process.stdout.write(JSON.stringify({ + tag_name: process.env.TAG, + name: process.env.TAG, + body: process.env.RELEASE_BODY, + draft: false, + prerelease: false + })); + ') + response=$(curl --fail-with-body --silent --show-error \ + -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + "${api_url}/repos/${REPOSITORY}/releases" \ + --data "$payload") + release_id=$(printf '%s' "$response" | node -e ' + let input = ""; + process.stdin.on("data", chunk => input += chunk); + process.stdin.on("end", () => { + const response = JSON.parse(input); + if (!response.id) process.exit(1); + process.stdout.write(String(response.id)); + }); + ') + curl --fail-with-body --silent --show-error \ + -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/octet-stream" \ + --data-binary "@${jar}" \ + "${api_url}/repos/${REPOSITORY}/releases/${release_id}/assets?name=spigot-creeper-fear-${VERSION}.jar" diff --git a/README.md b/README.md new file mode 100644 index 0000000..ec251b9 --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +# Spigot Creeper Fear + +A Spigot 26.2 plugin that lets players earn six Creeper Aura ranks. Once unlocked, an aura prevents creeper explosions that hit the player from breaking blocks, trading that protection for rank-dependent player damage. + +## Requirements + +- Spigot 26.2 +- Java 17 or newer + +## Progression + +Players earn one current-tier point when they kill a creeper directly, through a projectile, or through an owned tameable. A self-destructing creeper also awards one point to every player its explosion hits. Each tier defaults to 100 points and resets progress to zero when unlocked. + +| Rank | Creeper damage | Block damage | +| --- | ---: | --- | +| Locked | 1× | Normal | +| I | 3× | Prevented | +| II | 2× | Prevented | +| III | 1.5× | Prevented | +| IV | 1× | Prevented | +| V | 0.5× | Prevented | +| VI | Cancelled | Prevented | + +Progress is stored by player UUID in `plugins/CreeperFear/player-progress.sqlite3`. Database work runs away from the server thread. + +After each point, a temporary boss bar shows current-tier progress. Unlocking a rank displays a full-screen title. Rank VI players no longer receive a progress bar. + +## Build and install + +```bash +./gradlew clean check jar +cp build/libs/spigot-creeper-fear-0.1.0-SNAPSHOT.jar /path/to/server/plugins/ +``` + +Restart the server after copying the JAR. The plugin creates its configuration and SQLite database under `plugins/CreeperFear/`. + +## Commands + +| Command | Description | Permission | +| --- | --- | --- | +| `/creeperaura progress` | Show personal progress | `creeperfear.progress` | +| `/creeperaura progress ` | Inspect a known online or offline player | `creeperfear.admin.inspect` | +| `/creeperaura set ` | Set current-tier progress | `creeperfear.admin.modify` | +| `/creeperaura add ` | Adjust current-tier progress | `creeperfear.admin.modify` | +| `/creeperaura rank ` | Set rank and reset tier progress | `creeperfear.admin.modify` | +| `/creeperaura threshold ` | Persist a rank requirement | `creeperfear.admin.configure` | +| `/creeperaura reload` | Reload validated configuration | `creeperfear.admin.configure` | + +The personal progress permission defaults to everyone. Administrative permissions default to server operators. Administrative changes are recorded in the server log. + +## Configuration + +```yaml +progression: + requirements: + I: 100 + II: 100 + III: 100 + IV: 100 + V: 100 + VI: 100 + +aura: + damage-multipliers: + I: 3.0 + II: 2.0 + III: 1.5 + IV: 1.0 + V: 0.5 + VI: 0.0 + +feedback: + progress-bar-seconds: 5 + rank-up-title: "Creeper Aura %rank%" + rank-up-subtitle: "Unlocked!" +``` + +Requirements must be positive integers. Multipliers must be finite and non-negative. Invalid reloads are rejected while the last valid runtime settings remain active. Requirement changes preserve current rank and tier progress; a subsequent qualifying point can unlock at most one rank. + +## Releases + +Gitea Actions builds and tests every push and pull request and uploads a development JAR. Pull requests also validate conventional commit messages. + +Pushes to `main` run semantic-release: + +- `fix:` creates a patch release; +- `feat:` creates a minor release; +- a breaking-change footer or `!` creates a major release. + +A successful release attaches a versioned JAR to the corresponding Gitea release. The repository must define a `RELEASE_TOKEN` secret with repository contents write permission. + +For a local versioned artifact: + +```bash +./gradlew clean check jar -PreleaseVersion=1.2.3 +``` + +## Design + +The [OKF design bundle](design/index.md) contains the architecture and completed user stories. diff --git a/design/index.md b/design/index.md index 286db08..51a1567 100644 --- a/design/index.md +++ b/design/index.md @@ -14,3 +14,4 @@ This bundle documents a Spigot plugin in which players earn Creeper Aura ranks b - [User stories](user-stories/index.md) - [Plugin architecture](architecture.md) - [Design log](log.md) +- [Project README](../README.md) diff --git a/design/log.md b/design/log.md index 3503ba0..4f12629 100644 --- a/design/log.md +++ b/design/log.md @@ -20,3 +20,4 @@ description: Chronological record of material changes to the Spigot Creeper Fear - Completed US-004 with an asynchronous self-service progress command, ordinary-player permission, completion output, and command metadata. - Completed US-005 with UUID-backed offline inspection, atomic progress and rank administration, separate permissions, online-state refresh, and audit logging. - Completed US-006 with validated per-rank requirements and multipliers, configurable feedback, persistent threshold administration, and safe reload behavior. +- Completed US-007 with Java 17/Spigot 26.2 Gradle builds, project documentation, Gitea CI, conventional-commit checks, semantic versioning, and release artifact publication. diff --git a/design/user-stories/us-007-build-and-release-plugin.md b/design/user-stories/us-007-build-and-release-plugin.md index 3e3eec2..14654dc 100644 --- a/design/user-stories/us-007-build-and-release-plugin.md +++ b/design/user-stories/us-007-build-and-release-plugin.md @@ -2,7 +2,7 @@ type: User Story title: "US-007: Build and release the plugin" description: Give maintainers repeatable Java builds, automated verification, and versioned Gitea releases. -status: backlog +status: done --- # US-007: Build and release the plugin @@ -11,14 +11,14 @@ As a **plugin maintainer**, I want automated builds and releases so that tested, ## Acceptance criteria -- [ ] The Gradle project compiles with Java 17 against Spigot API 26.2. -- [ ] Automated tests run as part of the Gradle `check` lifecycle. -- [ ] Pushes and pull requests build and test the plugin in Gitea Actions. -- [ ] Pull requests validate conventional commit messages. -- [ ] CI stores a development JAR as a workflow artifact. -- [ ] Main-branch conventional commits drive semantic versioning. -- [ ] A successful release builds a versioned JAR and attaches it to the corresponding Gitea release. -- [ ] Build, installation, command, permission, configuration, and release procedures are documented. +- [x] The Gradle project compiles with Java 17 against Spigot API 26.2. +- [x] Automated tests run as part of the Gradle `check` lifecycle. +- [x] Pushes and pull requests build and test the plugin in Gitea Actions. +- [x] Pull requests validate conventional commit messages. +- [x] CI stores a development JAR as a workflow artifact. +- [x] Main-branch conventional commits drive semantic versioning. +- [x] A successful release builds a versioned JAR and attaches it to the corresponding Gitea release. +- [x] Build, installation, command, permission, configuration, and release procedures are documented. ## Related