ci: add plugin build and release pipeline
Release / release (push) Successful in 4m23s
CI / build (push) Successful in 1m14s

This commit is contained in:
dmg
2026-08-08 14:32:17 -04:00
parent 45fa29e290
commit 1d580220c3
6 changed files with 291 additions and 9 deletions
+40
View File
@@ -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
+140
View File
@@ -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"
+100
View File
@@ -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 <player>` | Inspect a known online or offline player | `creeperfear.admin.inspect` |
| `/creeperaura set <player> <progress>` | Set current-tier progress | `creeperfear.admin.modify` |
| `/creeperaura add <player> <amount>` | Adjust current-tier progress | `creeperfear.admin.modify` |
| `/creeperaura rank <player> <rank>` | Set rank and reset tier progress | `creeperfear.admin.modify` |
| `/creeperaura threshold <rank> <points>` | 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.
+1
View File
@@ -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)
+1
View File
@@ -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.
@@ -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