build(scripts): 📦️ Replace local build step with Docker-based simulator .so file generation in apricot-run.sh to ensure consistent artifacts with current SHA

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
autocommit 2026-05-26 13:02:45 -07:00
parent 05aa38dbcf
commit 97a5b9391f

View file

@ -185,43 +185,106 @@ git -C "\${CANONICAL}" worktree add --detach "\${SCRATCH}" "\${BUILD_REF}"
BUILT_SHA="\$(git -C "\${SCRATCH}" rev-parse --short HEAD)"
echo "built_sha=\${BUILT_SHA}"
# ── Step 2: build ────────────────────────────────────────────────────────────
( cd "\${SCRATCH}/src/simulator" && bash build-gdext.sh x86_64-unknown-linux-gnu )
rm -f "\${SCRATCH}/src/game/engine/addons/magic_civ_physics/libmagic_civ_physics.dylib"
# ── Step 2: docker build (bakes libmagic_civ_physics.x86_64.so per SHA) ──────
# The image bakes the simulator .so for this exact SHA. mc-ai-docker.sh then
# bind-mounts the worktree at /work, and the entrypoint installs the baked
# .so over whatever the worktree carries — guaranteeing Godot inside the
# container loads the SHA-matched artifact and never a stale one.
#
# Docker daemon must be running on this host. We fail loudly (exit 2) if
# it's not — no fallback to bare flatpak/cargo, per the brief's anti-stopgap
# rule. BuildKit's cache mounts keep this fast on rebuilds of the same SHA.
IMAGE_TAG="mc-ai:\${BUILT_SHA}"
DOCKER_BUILDKIT=1 docker build \\
--tag "\${IMAGE_TAG}" \\
--file "\${SCRATCH}/tools/docker/Dockerfile.mc-ai" \\
"\${SCRATCH}"
# ── Step 3: editor pre-pass to populate .godot/ class cache ─────────────────
flatpak run --user --filesystem=home --command=godot \\
org.godotengine.Godot --headless --editor --quit \\
--path "\${SCRATCH}/src/game" 2>&1 | tail -5 || true
# Trap → docker kill any container we started, so an OOM-killed or
# externally-stopped launcher doesn't leave the daemon-owned container
# running past the systemd unit's lifetime.
CONTAINER_NAME="mc-batch-\${STAMP}-run"
trap 'docker kill "\${CONTAINER_NAME}" 2>/dev/null || true' EXIT
# ── Step 4: run the batch ────────────────────────────────────────────────────
# Container cgroup ceilings. Scaled with PARALLEL so an N-seed batch gets
# N cores + headroom; explicit env overrides win. apricot has ~64 cores /
# ~96G RAM, so these defaults are safe and bounded.
MC_AI_CPUS_DEFAULT="\${PARALLEL}"
MC_AI_MEMORY_GB_DEFAULT="\$(( PARALLEL * 3 + 2 ))"
[[ "\${MC_AI_MEMORY_GB_DEFAULT}" -lt 4 ]] && MC_AI_MEMORY_GB_DEFAULT=4
export MC_AI_IMAGE_TAG="\${IMAGE_TAG}"
export MC_AI_WORKTREE="\${SCRATCH}"
export MC_AI_OUTPUT_DIR="\${RESULTS_SUB}"
export MC_AI_CPUS="\${MC_AI_CPUS:-\${MC_AI_CPUS_DEFAULT}}"
export MC_AI_MEMORY="\${MC_AI_MEMORY:-\${MC_AI_MEMORY_GB_DEFAULT}g}"
export MC_AI_PIDS="\${MC_AI_PIDS:-1024}"
export MC_AI_CONTAINER_NAME="\${CONTAINER_NAME}"
run_in_container() {
# Caller passes a sequence of KEY=VAL ... cmd args…; we route the KVs
# through MC_AI_EXTRA_ENV so they land as docker -e flags.
local _envs=()
while [[ \$# -gt 0 && "\$1" == *=* ]]; do
_envs+=("\$1"); shift
done
MC_AI_EXTRA_ENV="\${_envs[*]}" bash "\${SCRATCH}/scripts/mc-ai-docker.sh" "\$@"
}
# ── Step 3: editor pre-pass to populate .godot/ class cache (in container) ──
run_in_container godot --headless --editor --quit --path /work/src/game 2>&1 | tail -5 || true
# ── Step 4: run the batch (in container) ────────────────────────────────────
GPU_ENV_VAL="\${AI_GPU_ROLLOUT:-false}"
cd "\${SCRATCH}"
# Inside the container the batch writes to /work/.local/out (bind-mounted to
# RESULTS_SUB on the host). autoplay-batch.sh accepts results_dir as its last
# positional arg; huge-map-5clan.sh accepts it via HUGE_OUTPUT.
CONTAINER_OUT="/work/.local/out"
case "\${SUBMODE}" in
smoke)
AI_USE_MCTS=true AI_GPU_ROLLOUT="\${GPU_ENV_VAL}" PARALLEL="\${PARALLEL}" \\
bash tools/autoplay-batch.sh "\$@" "\${RESULTS_SUB}"
run_in_container \\
AUTOPLAY_GODOT_BIN=godot \\
AI_USE_MCTS=true \\
AI_GPU_ROLLOUT="\${GPU_ENV_VAL}" \\
PARALLEL="\${PARALLEL}" \\
RAYON_NUM_THREADS="\${RAYON_NUM_THREADS}" \\
bash tools/autoplay-batch.sh "\$@" "\${CONTAINER_OUT}"
;;
clan)
CLAN="\$1"; shift
AI_USE_MCTS=true AI_PIN_PERSONALITY="\${CLAN}" \\
AI_GPU_ROLLOUT="\${GPU_ENV_VAL}" PARALLEL="\${PARALLEL}" \\
bash tools/autoplay-batch.sh "\$@" "\${RESULTS_SUB}"
run_in_container \\
AUTOPLAY_GODOT_BIN=godot \\
AI_USE_MCTS=true \\
AI_PIN_PERSONALITY="\${CLAN}" \\
AI_GPU_ROLLOUT="\${GPU_ENV_VAL}" \\
PARALLEL="\${PARALLEL}" \\
RAYON_NUM_THREADS="\${RAYON_NUM_THREADS}" \\
bash tools/autoplay-batch.sh "\$@" "\${CONTAINER_OUT}"
;;
difficulty)
TIER="\$1"; shift
AI_USE_MCTS=true AI_DIFFICULTY="\${TIER}" \\
AI_DIFFICULTY_P0="\${TIER}" AI_DIFFICULTY_P1="\${TIER}" \\
AI_GPU_ROLLOUT="\${GPU_ENV_VAL}" PARALLEL="\${PARALLEL}" \\
bash tools/autoplay-batch.sh "\$@" "\${RESULTS_SUB}"
run_in_container \\
AUTOPLAY_GODOT_BIN=godot \\
AI_USE_MCTS=true \\
AI_DIFFICULTY="\${TIER}" \\
AI_DIFFICULTY_P0="\${TIER}" \\
AI_DIFFICULTY_P1="\${TIER}" \\
AI_GPU_ROLLOUT="\${GPU_ENV_VAL}" \\
PARALLEL="\${PARALLEL}" \\
RAYON_NUM_THREADS="\${RAYON_NUM_THREADS}" \\
bash tools/autoplay-batch.sh "\$@" "\${CONTAINER_OUT}"
;;
huge-map-5clan)
COUNT="\${1:-5}"; TURN_LIMIT="\${2:-300}"
mkdir -p "\${RESULTS_SUB}"
AI_USE_MCTS=true PARALLEL="\${PARALLEL}" RAYON_NUM_THREADS="\${RAYON_NUM_THREADS}" \\
COUNT="\${COUNT}" TURN_LIMIT="\${TURN_LIMIT}" \\
HUGE_OUTPUT="\${RESULTS_SUB}" \\
run_in_container \\
AUTOPLAY_GODOT_BIN=godot \\
AI_USE_MCTS=true \\
PARALLEL="\${PARALLEL}" \\
RAYON_NUM_THREADS="\${RAYON_NUM_THREADS}" \\
COUNT="\${COUNT}" \\
TURN_LIMIT="\${TURN_LIMIT}" \\
HUGE_OUTPUT="\${CONTAINER_OUT}" \\
bash tools/huge-map-5clan.sh
;;
*)