test(docker): add local Spigot test server
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
.gradle/
|
.gradle/
|
||||||
|
.docker/
|
||||||
build/
|
build/
|
||||||
out/
|
out/
|
||||||
.idea/
|
.idea/
|
||||||
|
|||||||
@@ -17,6 +17,40 @@ The approved behavior and implementation record are in the [OKF design bundle](d
|
|||||||
|
|
||||||
The plugin JAR is written to `build/libs/`.
|
The plugin JAR is written to `build/libs/`.
|
||||||
|
|
||||||
|
## Local Docker test server
|
||||||
|
|
||||||
|
Build the current plugin and start it on an isolated Spigot 26.2 server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/start-test-server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Connect to `localhost:25565` as `WindMagi`, which the harness configures as an operator. The server uses offline mode for local convenience and binds only to the loopback interface.
|
||||||
|
|
||||||
|
The first startup may take several minutes while the image downloads and Spigot is prepared. Override the 15-minute wait or local RCON password when needed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
TREE_FELLER_START_TIMEOUT=1200 \
|
||||||
|
TREE_FELLER_RCON_PASSWORD='local-secret' \
|
||||||
|
./scripts/start-test-server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Common lifecycle commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Follow server logs
|
||||||
|
docker compose -f compose.test.yml logs -f minecraft
|
||||||
|
|
||||||
|
# Stop while preserving the world and server configuration
|
||||||
|
docker compose -f compose.test.yml down
|
||||||
|
|
||||||
|
# Stop and permanently reset all generated local test state
|
||||||
|
docker compose -f compose.test.yml down
|
||||||
|
rm -rf .docker/minecraft
|
||||||
|
```
|
||||||
|
|
||||||
|
Re-run the start script after code changes to rebuild the JAR and recreate the test container. Generated server state remains under `.docker/minecraft/` and is ignored by Git.
|
||||||
|
|
||||||
## Player commands
|
## Player commands
|
||||||
|
|
||||||
```text
|
```text
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
name: tree-feller-test
|
||||||
|
|
||||||
|
services:
|
||||||
|
minecraft:
|
||||||
|
image: itzg/minecraft-server:java25
|
||||||
|
container_name: tree-feller-test
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:25565:25565"
|
||||||
|
environment:
|
||||||
|
EULA: "TRUE"
|
||||||
|
TYPE: SPIGOT
|
||||||
|
VERSION: "26.2"
|
||||||
|
MEMORY: 2G
|
||||||
|
OPS: WindMagi
|
||||||
|
ONLINE_MODE: "false"
|
||||||
|
ENABLE_RCON: "true"
|
||||||
|
RCON_PASSWORD: "${TREE_FELLER_RCON_PASSWORD:-tree-feller-local-test}"
|
||||||
|
VIEW_DISTANCE: "6"
|
||||||
|
SIMULATION_DISTANCE: "6"
|
||||||
|
SPAWN_PROTECTION: "0"
|
||||||
|
volumes:
|
||||||
|
- ./.docker/minecraft:/data
|
||||||
|
- ./build/libs/tree-feller-0.1.0-SNAPSHOT.jar:/plugins/TreeFeller.jar:ro
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mc-health"]
|
||||||
|
start_period: 15m
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 90
|
||||||
|
restart: "no"
|
||||||
|
stdin_open: true
|
||||||
|
tty: true
|
||||||
@@ -2,6 +2,14 @@
|
|||||||
|
|
||||||
## 2026-08-11
|
## 2026-08-11
|
||||||
|
|
||||||
|
### US-010 local Docker test server completed
|
||||||
|
|
||||||
|
- Added a repository-local Docker Compose harness using `itzg/minecraft-server:java25` with Spigot 26.2, persistent ignored state, offline local testing, and loopback-only port binding.
|
||||||
|
- Added one executable script that runs the strict Gradle build, recreates the isolated container with the latest JAR, waits for health, verifies Tree Feller through RCON, and confirms `WindMagi` as an operator.
|
||||||
|
- Documented start, log, stop, persistent-state reset, timeout, and RCON-password controls.
|
||||||
|
- Live verification completed in 23 seconds: the container was healthy, RCON reported `TreeFeller`, `ops.json` contained `WindMagi` at level 4, and port 25565 was bound only to `127.0.0.1`.
|
||||||
|
- The test server remains running at `localhost:25565` for gameplay testing.
|
||||||
|
|
||||||
### US-009 build and release completed
|
### US-009 build and release completed
|
||||||
|
|
||||||
- Added maintainer documentation for requirements, builds, commands, configuration, supported species, persistence, safety, compatibility, and releases.
|
- Added maintainer documentation for requirements, builds, commands, configuration, supported species, persistence, safety, compatibility, and releases.
|
||||||
|
|||||||
@@ -9,3 +9,4 @@
|
|||||||
7. [US-007: Administer Tree Feller](us-007-administer-tree-feller.md)
|
7. [US-007: Administer Tree Feller](us-007-administer-tree-feller.md)
|
||||||
8. [US-008: Configure and persist Tree Feller](us-008-configure-and-persist-tree-feller.md)
|
8. [US-008: Configure and persist Tree Feller](us-008-configure-and-persist-tree-feller.md)
|
||||||
9. [US-009: Build and release Tree Feller](us-009-build-and-release-tree-feller.md)
|
9. [US-009: Build and release Tree Feller](us-009-build-and-release-tree-feller.md)
|
||||||
|
10. [US-010: Run a local Docker test server](us-010-run-local-docker-test-server.md)
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
type: User Story
|
||||||
|
title: "US-010: Run a local Docker test server"
|
||||||
|
description: Provide a repeatable Docker Compose harness that builds and loads Tree Feller on an isolated Spigot 26.2 server.
|
||||||
|
status: done
|
||||||
|
---
|
||||||
|
|
||||||
|
# US-010: Run a local Docker test server
|
||||||
|
|
||||||
|
As a **plugin developer**, I want one command to run the current Tree Feller build on a local containerized server so that I can perform repeatable integration and gameplay testing.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [x] One repository script builds and verifies the plugin before starting an isolated Spigot 26.2 server through Docker Compose.
|
||||||
|
- [x] The current Tree Feller JAR is mounted into the server automatically whenever the container is recreated.
|
||||||
|
- [x] `WindMagi` is configured and verified as a server operator.
|
||||||
|
- [x] The Minecraft port binds only to `127.0.0.1:25565` by default.
|
||||||
|
- [x] Startup waits for server health and verifies Tree Feller through RCON.
|
||||||
|
- [x] Generated worlds, logs, configuration, and downloaded server artifacts are stored under `.docker/minecraft/` and excluded from Git.
|
||||||
|
- [x] Stopping Compose preserves generated test state unless the operator explicitly deletes it.
|
||||||
|
- [x] Existing unrelated containers are not modified.
|
||||||
|
- [x] Maintainer documentation explains start, logs, stop, reset, timeout, and RCON-password controls.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This harness is for local development only. It does not define production deployment, publish an image, expose Minecraft or RCON publicly, or persist its runtime state in Git.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [US-003: Fell unlocked trees](us-003-fell-unlocked-trees.md)
|
||||||
|
- [US-005: Undo the last felled tree](us-005-undo-the-last-felled-tree.md)
|
||||||
|
- [US-009: Build and release Tree Feller](us-009-build-and-release-tree-feller.md)
|
||||||
|
- [User-story catalog](index.md)
|
||||||
Executable
+74
@@ -0,0 +1,74 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
project_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
compose_file="$project_root/compose.test.yml"
|
||||||
|
wait_seconds="${TREE_FELLER_START_TIMEOUT:-900}"
|
||||||
|
|
||||||
|
if ! command -v docker >/dev/null 2>&1; then
|
||||||
|
echo "Required command not found: docker" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! docker info >/dev/null 2>&1; then
|
||||||
|
echo "Docker is not running or is not accessible." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! docker compose version >/dev/null 2>&1; then
|
||||||
|
echo "Docker Compose v2 is required." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$project_root"
|
||||||
|
./gradlew clean check jar
|
||||||
|
mkdir -p .docker/minecraft
|
||||||
|
|
||||||
|
# Recreate the container so the image installs the newly built read-only plugin JAR.
|
||||||
|
docker compose -f "$compose_file" up -d --force-recreate
|
||||||
|
container_id="$(docker compose -f "$compose_file" ps -q minecraft)"
|
||||||
|
if [[ -z "$container_id" ]]; then
|
||||||
|
echo "The Tree Feller test container was not created." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Waiting up to ${wait_seconds}s for Spigot 26.2..."
|
||||||
|
deadline=$((SECONDS + wait_seconds))
|
||||||
|
while (( SECONDS < deadline )); do
|
||||||
|
container_state="$(docker inspect --format '{{.State.Status}}' "$container_id")"
|
||||||
|
health_state="$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "$container_id")"
|
||||||
|
if [[ "$health_state" == "healthy" ]]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [[ "$container_state" == "exited" || "$container_state" == "dead" ]]; then
|
||||||
|
docker compose -f "$compose_file" logs --tail=150 minecraft >&2
|
||||||
|
echo "The Minecraft server exited during startup." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
|
||||||
|
health_state="$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "$container_id")"
|
||||||
|
if [[ "$health_state" != "healthy" ]]; then
|
||||||
|
docker compose -f "$compose_file" logs --tail=150 minecraft >&2
|
||||||
|
echo "Timed out waiting for Spigot 26.2 (status: $health_state)." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
plugins="$(docker compose -f "$compose_file" exec -T minecraft rcon-cli plugins)"
|
||||||
|
if [[ "$plugins" != *"TreeFeller"* ]]; then
|
||||||
|
echo "$plugins" >&2
|
||||||
|
echo "TreeFeller was not reported by the running server." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This is idempotent and confirms the requested local test account is an operator.
|
||||||
|
docker compose -f "$compose_file" exec -T minecraft rcon-cli 'op WindMagi' >/dev/null
|
||||||
|
|
||||||
|
cat <<'MESSAGE'
|
||||||
|
Tree Feller test server is ready at localhost:25565.
|
||||||
|
Operator: WindMagi
|
||||||
|
View logs: docker compose -f compose.test.yml logs -f minecraft
|
||||||
|
Stop: docker compose -f compose.test.yml down
|
||||||
|
Reset: docker compose -f compose.test.yml down && rm -rf .docker/minecraft
|
||||||
|
MESSAGE
|
||||||
Reference in New Issue
Block a user