85 lines
2.6 KiB
Bash
Executable file
85 lines
2.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# godot-docker.sh — run Godot Linux headless inside a freeze-proof Docker container.
|
|
#
|
|
# Why: `godot --headless --import` and similar commands kernel-panicked plum
|
|
# twice and freeze apricot when run cold. Containers on macOS run inside a
|
|
# Linux VM with its own kernel, fully isolated from macOS — no chance of
|
|
# tripping the GPU/video kexts that caused the panics. Cgroup limits below
|
|
# also keep the VM from starving itself.
|
|
#
|
|
# See: ~/.claude/plans/godot-container-runner.md
|
|
#
|
|
# Usage:
|
|
# scripts/godot-docker.sh [args...] # passed straight to godot
|
|
# scripts/godot-docker.sh --version # smoke test
|
|
# scripts/godot-docker.sh --headless --import # warm the import cache
|
|
# scripts/godot-docker.sh --headless --script res://addons/gut/gut_cmdln.gd -gexit -gtest=res://engine/tests/unit/test_city_buildable_helper.gd
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
DOCKERFILE="$REPO_ROOT/tools/docker/Dockerfile.godot"
|
|
|
|
IMAGE="mc-godot:4.6.2"
|
|
VOLUME="mc-godot-cache"
|
|
WORKDIR_IN_CONTAINER="/work/src/game"
|
|
|
|
# Cgroup hard caps so the container can't starve the host VM.
|
|
# Defaults sized for Docker Desktop with ≥7 GiB allocated.
|
|
CPUS="${MC_GODOT_CPUS:-4}"
|
|
MEMORY="${MC_GODOT_MEMORY:-6g}"
|
|
PIDS_LIMIT="${MC_GODOT_PIDS:-256}"
|
|
|
|
ensure_image() {
|
|
if docker image inspect "$IMAGE" >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
echo "[godot-docker] image $IMAGE not found — building..." >&2
|
|
docker build \
|
|
--tag "$IMAGE" \
|
|
--file "$DOCKERFILE" \
|
|
"$REPO_ROOT/tools/docker"
|
|
}
|
|
|
|
ensure_volume() {
|
|
if docker volume inspect "$VOLUME" >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
echo "[godot-docker] creating named volume $VOLUME for warm import cache" >&2
|
|
docker volume create "$VOLUME" >/dev/null
|
|
}
|
|
|
|
ensure_docker_running() {
|
|
if ! docker info >/dev/null 2>&1; then
|
|
echo "ERROR: Docker daemon not reachable. Start Docker Desktop first." >&2
|
|
exit 2
|
|
fi
|
|
}
|
|
|
|
main() {
|
|
ensure_docker_running
|
|
ensure_image
|
|
ensure_volume
|
|
|
|
# Force a TTY only when stdout is a terminal; CI invocations stay non-interactive.
|
|
local tty_flag=""
|
|
if [[ -t 1 ]]; then
|
|
tty_flag="-t"
|
|
fi
|
|
|
|
docker run \
|
|
--rm \
|
|
-i $tty_flag \
|
|
--cpus "$CPUS" \
|
|
--memory "$MEMORY" \
|
|
--memory-swap "$MEMORY" \
|
|
--pids-limit "$PIDS_LIMIT" \
|
|
--volume "$REPO_ROOT:/work" \
|
|
--volume "$VOLUME:/work/src/game/.godot" \
|
|
--workdir "$WORKDIR_IN_CONTAINER" \
|
|
"$IMAGE" \
|
|
"$@"
|
|
}
|
|
|
|
main "$@"
|