From 97a5b9391fb0ea177625bf26b6cf534239909071 Mon Sep 17 00:00:00 2001 From: autocommit Date: Tue, 26 May 2026 13:02:45 -0700 Subject: [PATCH] =?UTF-8?q?build(scripts):=20=F0=9F=93=A6=EF=B8=8F=20Repla?= =?UTF-8?q?ce=20local=20build=20step=20with=20Docker-based=20simulator=20.?= =?UTF-8?q?so=20file=20generation=20in=20apricot-run.sh=20to=20ensure=20co?= =?UTF-8?q?nsistent=20artifacts=20with=20current=20SHA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- scripts/apricot-run.sh | 107 ++++++++++++++++++++++++++++++++--------- 1 file changed, 85 insertions(+), 22 deletions(-) diff --git a/scripts/apricot-run.sh b/scripts/apricot-run.sh index b331befc..3c887c9c 100755 --- a/scripts/apricot-run.sh +++ b/scripts/apricot-run.sh @@ -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 ;; *)