magicciv/scripts/ui-proof-capture.sh

106 lines
3.5 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# Reusable UI-proof capture — runs ON the RUN host (apricot).
#
# Drives flatpak Godot under a weston headless Wayland compositor pointed at a
# proof scene `.tscn`. The proof scene writes one or more PNGs to
# `user://screenshots/` (Godot flatpak userdata) and prints `SCREENSHOT_PATH:<abs>`
# per shot. This script wipes the matching prior PNGs, runs the scene, then lists
# the produced files so the caller can rsync them back.
#
# A real display is required because `--headless` returns a null viewport image
# (the proof scenes call get_viewport().get_texture().get_image()). weston
# --backend=headless provides a virtual Wayland host with no live session.
#
# Usage:
# SCRATCH_DIR=<repo-root-on-apricot> \
# PROOF_SCENE=res://engine/scenes/tests/<name>.tscn \
# SHOT_GLOB='<name>_*.png' \
# bash scripts/ui-proof-capture.sh
#
# Env:
# SCRATCH_DIR repo root on apricot containing src/game (required)
# PROOF_SCENE res:// path to the proof tscn (required)
# SHOT_GLOB glob (within the screenshots dir) of PNGs this run emits (required)
# LOG_FILE Godot log destination (default /tmp/ui-proof.log)
# TIMEOUT_SEC Godot timeout in seconds (default 120)
# WIDTH/HEIGHT weston virtual output size (default 1280/720)
set -uo pipefail
SCRATCH_DIR="${SCRATCH_DIR:?SCRATCH_DIR is required}"
PROOF_SCENE="${PROOF_SCENE:?PROOF_SCENE is required}"
SHOT_GLOB="${SHOT_GLOB:?SHOT_GLOB is required}"
LOG_FILE="${LOG_FILE:-/tmp/ui-proof.log}"
TIMEOUT_SEC="${TIMEOUT_SEC:-120}"
WIDTH="${WIDTH:-1280}"
HEIGHT="${HEIGHT:-720}"
GODOT_USERDATA="$HOME/.var/app/org.godotengine.Godot/data/godot/app_userdata/Magic Civilization"
SHOT_DIR="$GODOT_USERDATA/screenshots"
echo "=== UI proof capture ==="
echo "SCRATCH_DIR: $SCRATCH_DIR"
echo "PROOF_SCENE: $PROOF_SCENE"
echo "SHOT_GLOB: $SHOT_GLOB"
echo "Sandbox shots dir: $SHOT_DIR"
mkdir -p "$SHOT_DIR"
rm -f "$SHOT_DIR"/$SHOT_GLOB 2>/dev/null || true
if ! command -v weston >/dev/null 2>&1; then
echo "ERROR: weston not installed" >&2
exit 2
fi
WESTON_SOCKET="ui-proof-$$"
WESTON_LOG="/tmp/ui-proof-weston.log"
echo "Starting weston (headless, socket=$WESTON_SOCKET, ${WIDTH}x${HEIGHT})..."
weston --backend=headless --no-config --socket="$WESTON_SOCKET" \
--width="$WIDTH" --height="$HEIGHT" \
>"$WESTON_LOG" 2>&1 &
WESTON_PID=$!
sleep 1.5
if ! kill -0 "$WESTON_PID" 2>/dev/null; then
echo "ERROR: weston failed to launch — see $WESTON_LOG" >&2
tail -20 "$WESTON_LOG" >&2
exit 3
fi
trap 'kill $WESTON_PID 2>/dev/null; wait $WESTON_PID 2>/dev/null' EXIT
XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" \
timeout "$TIMEOUT_SEC" flatpak run --user \
--filesystem=home \
--socket=wayland \
--unset-env=DISPLAY \
--env=WAYLAND_DISPLAY="$WESTON_SOCKET" \
--filesystem=xdg-run/${WESTON_SOCKET} \
org.godotengine.Godot \
--path "$SCRATCH_DIR/src/game" \
--display-driver wayland \
--rendering-driver opengl3 \
--rendering-method gl_compatibility \
"$PROOF_SCENE" \
>"$LOG_FILE" 2>&1
RC=$?
echo "--- Godot exit rc=$RC ---"
echo "--- Tail of log ---"
tail -40 "$LOG_FILE"
echo "-------------------"
echo "--- SCREENSHOT_PATH lines ---"
grep "SCREENSHOT_PATH:" "$LOG_FILE" || echo "(none)"
echo "-----------------------------"
shopt -s nullglob
SHOTS=( "$SHOT_DIR"/$SHOT_GLOB )
shopt -u nullglob
if [ "${#SHOTS[@]}" -eq 0 ]; then
echo "ERROR: no $SHOT_GLOB produced under $SHOT_DIR" >&2
exit 1
fi
echo "Captured ${#SHOTS[@]} shots:"
ls -la "$SHOT_DIR"/$SHOT_GLOB
echo "=== Done ==="
exit 0