Improve MCC testing workflow resilience

This commit is contained in:
milutinke 2026-03-30 18:02:10 +02:00
parent 6b5435629f
commit 76e5cab248
16 changed files with 464 additions and 255 deletions

View file

@ -32,6 +32,7 @@ EOF
VERSION="1.21.11-Vanilla"
MODE="classic"
PORT="25565"
PORT_SET_BY_USER=false
DO_BUILD=true
DEBUG_ON=false
FILE_INPUT=false
@ -40,7 +41,7 @@ while [[ $# -gt 0 ]]; do
case "$1" in
-v|--version) VERSION="$2"; shift 2 ;;
-m|--mode) MODE="$2"; shift 2 ;;
-p|--port) PORT="$2"; shift 2 ;;
-p|--port) PORT="$2"; PORT_SET_BY_USER=true; shift 2 ;;
--no-build) DO_BUILD=false; shift ;;
--debug-on) DEBUG_ON=true; shift ;;
--file-input) FILE_INPUT=true; shift ;;
@ -54,6 +55,10 @@ CFG="$TEST_ROOT/MinecraftClient.debug.ini"
MCC_LOG="$TEST_ROOT/mcc-debug.log"
INPUT_FILE="$REPO_ROOT/mcc_input.txt"
SESSION_NAME="mc-${VERSION//\./_}"
PREPARE_CFG_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/prepare_offline_mcc_config.sh"
ENSURE_SERVER_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/ensure_offline_server.sh"
PREFLIGHT_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/preflight_test_env.sh"
GET_PORT_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/get_server_port.sh"
mkdir -p "$TEST_ROOT"
@ -64,6 +69,8 @@ echo " Config: $CFG"
echo " Log: $MCC_LOG"
echo ""
bash "$PREFLIGHT_SCRIPT" "$VERSION" >/dev/null
# --- Build ---
if $DO_BUILD; then
echo "[1/4] Building MCC..."
@ -75,21 +82,22 @@ fi
# --- Prepare config ---
echo "[2/4] Preparing config..."
cp "$REPO_ROOT/MinecraftClient.ini" "$CFG"
sed -i \
-e 's/Account = { Login = "[^"]*", Password = "[^"]*" }/Account = { Login = "CursorBot", Password = "-" }/' \
-e 's/TerrainAndMovements = false/TerrainAndMovements = true/' \
-e 's/InventoryHandling = false/InventoryHandling = true/' \
-e 's/EntityHandling = false/EntityHandling = true/' \
"$CFG"
bash "$PREPARE_CFG_SCRIPT" "$CFG" "${VERSION%-Vanilla}" CursorBot >/dev/null
if [[ "$MODE" == "tui" ]]; then
sed -i 's/ConsoleMode = "classic"/ConsoleMode = "tui"/' "$CFG"
if [[ "$(uname)" == "Darwin" ]]; then
sed -i '' 's/ConsoleMode = "classic"/ConsoleMode = "tui"/' "$CFG"
else
sed -i 's/ConsoleMode = "classic"/ConsoleMode = "tui"/' "$CFG"
fi
fi
if $DEBUG_ON; then
sed -i 's/DebugMessages = false/DebugMessages = true/' "$CFG"
if [[ "$(uname)" == "Darwin" ]]; then
sed -i '' 's/DebugMessages = false/DebugMessages = true/' "$CFG"
else
sed -i 's/DebugMessages = false/DebugMessages = true/' "$CFG"
fi
fi
echo " Config ready"
@ -99,14 +107,7 @@ echo "[3/4] Starting server $VERSION..."
if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
echo " Server already running"
else
# Ensure offline mode
SERVER_DIR="$MCC_SERVERS/$VERSION"
if [[ -f "$SERVER_DIR/server.properties" ]]; then
sed -i 's/^online-mode=.*/online-mode=false/' "$SERVER_DIR/server.properties"
grep -q "^enable-rcon=" "$SERVER_DIR/server.properties" || echo "enable-rcon=true" >> "$SERVER_DIR/server.properties"
grep -q "^rcon.password=" "$SERVER_DIR/server.properties" || echo "rcon.password=test123" >> "$SERVER_DIR/server.properties"
grep -q "^rcon.port=" "$SERVER_DIR/server.properties" || echo "rcon.port=25575" >> "$SERVER_DIR/server.properties"
fi
bash "$ENSURE_SERVER_SCRIPT" "$VERSION" >/dev/null
mc-start "$VERSION" >/dev/null
echo -n " Waiting for server..."
@ -125,6 +126,10 @@ else
done
fi
if ! $PORT_SET_BY_USER; then
PORT="$(bash "$GET_PORT_SCRIPT" "$VERSION")"
fi
# --- Launch MCC ---
echo "[4/4] Launching MCC in $MODE mode..."
: > "$INPUT_FILE"

View file

@ -26,6 +26,9 @@ mc-cmd() { local v="${2:-1.20.6}"; echo "$1" > "$MCC_SERVERS/$v/stdin.pipe"; }
mc-log() { local s; s=$(_mc-session "${1:-1.20.6}"); tmux capture-pane -t "$s" -p -S "-${2:-50}"; }
mc-kill() { local v="${1:-1.20.6}" s; s=$(_mc-session "$v"); tmux kill-session -t "$s" 2>/dev/null; rm -f "$MCC_SERVERS/$v/stdin.pipe"; echo "Killed $s"; }
mc-list() { tmux list-sessions 2>/dev/null | grep "^mc-" || echo "No running MC servers"; }
mc-wait-ready() { bash "$MCC_REPO/.skills/mcc-integration-testing/scripts/preflight_test_env.sh" "${1:-1.20.6}" >/dev/null && source "$MCC_REPO/.skills/mcc-integration-testing/scripts/common.sh" && wait_for_server_ready "${1:-1.20.6}" "${2:-60}"; }
mc-wait-stop() { source "$MCC_REPO/.skills/mcc-integration-testing/scripts/common.sh" && wait_for_server_stop "${1:-1.20.6}" "${2:-60}"; }
mc-reset-test-env() { bash "$MCC_REPO/.skills/mcc-integration-testing/scripts/reset_shared_test_state.sh" "$@"; }
# --- RCON ---
mc-rcon() { bash "$MCC_REPO/tools/mc-rcon.sh" "$@"; }
@ -59,3 +62,4 @@ mcc-tui() {
mcc-debug() { bash "$MCC_REPO/tools/mcc-debug.sh" "$@"; }
mcc-log-mcc() { tail -f "${TMPDIR:-/tmp}/mcc-debug/mcc-debug.log" 2>/dev/null || echo "No MCC log found"; }
mcc-state() { echo "debug state" >> "$MCC_REPO/mcc_input.txt"; sleep 1; tail -30 "${TMPDIR:-/tmp}/mcc-debug/mcc-debug.log" 2>/dev/null; }
mcc-preflight() { bash "$MCC_REPO/.skills/mcc-integration-testing/scripts/preflight_test_env.sh" "$@"; }

View file

@ -5,6 +5,8 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
# shellcheck source=tools/mcc-env.sh
source "$REPO_ROOT/tools/mcc-env.sh"
# shellcheck source=.skills/mcc-integration-testing/scripts/common.sh
source "$REPO_ROOT/.skills/mcc-integration-testing/scripts/common.sh"
usage() {
cat <<'EOF'
@ -37,6 +39,7 @@ MCC_LOG="$TEST_ROOT/mcc.log"
SERVER_LOG_FILE="$MCC_SERVERS/$SERVER_DIR/logs/latest.log"
INPUT_FILE="$REPO_ROOT/mcc_input.txt"
MCC_PID=""
SERVER_PORT="25565"
mkdir -p "$TEST_ROOT"
@ -59,33 +62,6 @@ wait_for_file_pattern() {
return 1
}
wait_for_server_ready() {
local timeout="${1:-60}"
local elapsed=0
while (( elapsed < timeout )); do
if mc-log "$SERVER_DIR" 250 2>/dev/null | grep -Fq "Done ("; then
return 0
fi
sleep 1
((elapsed += 1))
done
echo "Timed out waiting for server readiness" >&2
return 1
}
kill_other_servers() {
local sessions
sessions="$(tmux list-sessions 2>/dev/null | awk -F: '/^mc-/{print $1}' || true)"
if [[ -n "$sessions" ]]; then
while IFS= read -r session; do
[[ -z "$session" ]] && continue
tmux kill-session -t "$session" 2>/dev/null || true
done <<< "$sessions"
fi
}
cleanup() {
if [[ -n "${MCC_PID:-}" ]] && kill -0 "$MCC_PID" 2>/dev/null; then
echo "quit" >> "$INPUT_FILE" 2>/dev/null || true
@ -96,7 +72,7 @@ cleanup() {
if [[ -p "$MCC_SERVERS/$SERVER_DIR/stdin.pipe" ]]; then
echo "stop" > "$MCC_SERVERS/$SERVER_DIR/stdin.pipe" 2>/dev/null || true
sleep 2
wait_for_server_stop "$SERVER_DIR" 20 >/dev/null 2>&1 || true
fi
tmux kill-session -t "$SESSION_NAME" 2>/dev/null || true
@ -105,24 +81,7 @@ cleanup() {
trap cleanup EXIT
prepare_config() {
cp "$REPO_ROOT/MinecraftClient.ini" "$CFG"
sed -i \
-e 's/Account = { Login = "test", Password = "-" }/Account = { Login = "CursorBot", Password = "-" }/' \
-e "s/MinecraftVersion = \"auto\"/MinecraftVersion = \"$MC_VERSION\"/" \
-e 's/TerrainAndMovements = false/TerrainAndMovements = true/' \
-e 's/InventoryHandling = false/InventoryHandling = true/' \
-e 's/EntityHandling = false/EntityHandling = true/' \
-e 's/AutoRespawn = false/AutoRespawn = true/' \
"$CFG"
sed -i '/^\[ChatBot.ScriptScheduler\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$CFG"
sed -i '/^\[ChatBot.DiscordRpc\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$CFG"
sed -i '/^\[ChatBot.AntiAFK\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$CFG"
sed -i '/^\[ChatBot.AutoDig\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$CFG"
sed -i '/^\[ChatBot.AutoAttack\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$CFG"
sed -i '/^\[ChatBot.PlayerListLogger\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$CFG"
sed -i '/^\[ChatBot.ReplayCapture\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$CFG"
bash "$REPO_ROOT/.skills/mcc-integration-testing/scripts/prepare_offline_mcc_config.sh" "$CFG" "$MC_VERSION" CursorBot >/dev/null
}
send_mcc_command() {
@ -195,23 +154,30 @@ modern_mob_and_effects() {
run_server_command "effect give CursorBot minecraft:regeneration 10 1 true"
}
bash "$REPO_ROOT/.skills/mcc-integration-testing/scripts/preflight_test_env.sh" "$SERVER_DIR" >/dev/null
bash "$REPO_ROOT/.skills/mcc-integration-testing/scripts/reset_shared_test_state.sh" --all >/dev/null
prepare_config
kill_other_servers
rm -f "$MCC_LOG" "$INPUT_FILE"
bash "$REPO_ROOT/.skills/mcc-integration-testing/scripts/ensure_offline_server.sh" "$SERVER_DIR" >/dev/null
SERVER_PORT="$(bash "$REPO_ROOT/.skills/mcc-integration-testing/scripts/get_server_port.sh" "$SERVER_DIR")"
if [[ -f "$MCC_SERVERS/$SERVER_DIR/server.properties" ]]; then
sed -i 's/^use-native-transport=.*/use-native-transport=false/' "$MCC_SERVERS/$SERVER_DIR/server.properties"
sed_in_place 's/^use-native-transport=.*/use-native-transport=false/' "$MCC_SERVERS/$SERVER_DIR/server.properties"
fi
mc-start "$SERVER_DIR" >/dev/null
wait_for_server_ready || exit 1
wait_for_server_ready "$SERVER_DIR" || exit 1
: > "$INPUT_FILE"
(
cd "$REPO_ROOT"
MCC_FILE_INPUT=1 dotnet run --project MinecraftClient -c Release --no-build -- "$CFG" > "$MCC_LOG" 2>&1
MCC_FILE_INPUT=1 dotnet run --project MinecraftClient -c Release --no-build -- \
"$CFG" \
CursorBot \
- \
"localhost:$SERVER_PORT" \
> "$MCC_LOG" 2>&1
) &
MCC_PID=$!

View file

@ -1,12 +1,38 @@
#!/bin/bash
# Start a Minecraft server in a tmux session with named pipe for stdin
# Servers live under $MCC_SERVERS or default to MinecraftOfficial/downloads/<version>/.
resolve_java_bin() {
if command -v java >/dev/null 2>&1 && java -version >/dev/null 2>&1; then
command -v java
return 0
fi
local candidate
for candidate in \
"${JAVA_BIN:-}" \
"/opt/homebrew/opt/openjdk/bin/java" \
"/usr/local/opt/openjdk/bin/java" \
"/usr/lib/jvm/default-java/bin/java"
do
[[ -z "$candidate" ]] && continue
if [[ -x "$candidate" ]]; then
if "$candidate" -version >/dev/null 2>&1; then
printf '%s\n' "$candidate"
return 0
fi
fi
done
return 1
}
VERSION="${1}"
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
DOWNLOADS="${MCC_SERVERS:-$REPO_ROOT/MinecraftOfficial/downloads}"
DIR="$DOWNLOADS/$VERSION"
PIPE="$DIR/stdin.pipe"
SESSION="mc-${VERSION//\./_}"
JAVA_BIN="$(resolve_java_bin || true)"
if [ -z "$VERSION" ] || [ ! -d "$DIR" ]; then
echo "Error: Server directory not found${VERSION:+: $DIR}"
@ -20,6 +46,16 @@ if [ ! -f "$DIR/server.jar" ]; then
exit 1
fi
if ! command -v tmux >/dev/null 2>&1; then
echo "Error: tmux is required to start local test servers"
exit 1
fi
if [[ -z "$JAVA_BIN" ]]; then
echo "Error: Java was not found on PATH. Install Java or set JAVA_BIN." >&2
exit 1
fi
if tmux has-session -t "$SESSION" 2>/dev/null; then
echo "Server $VERSION already running in tmux session '$SESSION'"
echo "View output: tmux capture-pane -t '$SESSION' -p -S -50"
@ -29,10 +65,14 @@ fi
rm -f "$DIR/world/session.lock"
if [[ -e "$PIPE" && ! -p "$PIPE" ]]; then
rm -f "$PIPE"
fi
[ -p "$PIPE" ] || mkfifo "$PIPE"
tmux new-session -d -s "$SESSION" -c "$DIR" \
"tail -f $PIPE | java -Xmx2G -Xms2G -jar server.jar nogui 2>&1"
"tail -f $PIPE | '$JAVA_BIN' -Xmx2G -Xms2G -jar server.jar nogui 2>&1"
echo "Server $VERSION started in tmux session '$SESSION'"
echo "Send commands: echo 'say hello' > $PIPE"