Sincronizar el codigo nuevo al worker y llamar a cargo NO basta: rsync -a preserva el mtime del hub, asi que el fuente recien llegado puede quedar mas VIEJO que el binario que el worker compilo hace un rato. cargo dice «Finished in 0.09s», el worker se queda con el hammer anterior, calcula la huella vieja y el paso 4 falla sin que se vea por que. Paso el 2026-08-12 al empujar el lab con los -dev: el worker tenia el lab.rs correcto Y el rootfs correcto, y aun asi divergia. Se arregla con un `touch` a los fuentes antes de compilar. El guardian del paso 4 hizo su trabajo: detecto la divergencia y NO dejo construir. Sin el, el worker habria molido horas sellando en direcciones que el hub nunca iria a buscar. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
74 lines
4.3 KiB
Bash
Executable File
74 lines
4.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# farm-lab-sync.sh <ip> — pone el LAB ANCLADO en un worker y PRUEBA que sella igual que el hub.
|
|
#
|
|
# ── POR QUÉ NO BASTA CON farm-sync ──────────────────────────────────────────────────────────────
|
|
# `farm-sync.sh` sube el código con `--exclude /.dev-fs`, a propósito: el lab es del entorno, no del
|
|
# repo. Eso estaba bien cuando el toolchain NO entraba en el hash. Desde el 2026-08-10 sí entra
|
|
# (`hammer-core/src/lab.rs`), así que un worker con su lab horneado en la golden —rustc 1.96— sella
|
|
# en direcciones DISTINTAS a las del hub —1.97— y su trabajo no le sirve a nadie: no es que compile
|
|
# distinto, es que lo guarda en otra dirección y el hub nunca lo encuentra.
|
|
#
|
|
# Tampoco basta con correr `bootstrap-devfs.sh` en el worker: su paso 0 sólo trae la imagen si NO
|
|
# hay rootfs, y la golden trae uno. Se reemplaza a la fuerza.
|
|
#
|
|
# ── EL WORKER SIGUE SIN SECRETOS ────────────────────────────────────────────────────────────────
|
|
# La imagen se EMPUJA desde el hub por scp, no se baja del Storage Box. Así el worker no necesita la
|
|
# llave del box y se mantiene el invariante del modelo hub-and-spoke: compute puro y descartable.
|
|
#
|
|
# ── EVIDENCIA, NO FE ────────────────────────────────────────────────────────────────────────────
|
|
# El paso final NO es "extraje la imagen": es comparar el `hammer hash` de una receta testigo entre
|
|
# worker y hub. Si no coinciden, este script FALLA y el worker no debe construir — un worker que
|
|
# sella en otra dirección quema dinero produciendo artefactos que nadie va a encontrar.
|
|
#
|
|
# Uso: scripts/farm/farm-lab-sync.sh <ip-del-worker>
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"; cd "$ROOT"
|
|
IP="${1:?falta la IP del worker}"
|
|
SSH_KEY="${SSH_KEY:-$HOME/.ssh/github5}"
|
|
REMOTE="${REMOTE:-/opt/hammer}"
|
|
SSH="ssh -i $SSH_KEY -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
|
|
IMG="$ROOT/.dev-fs/lab-image.tar.zst"
|
|
TESTIGO="${TESTIGO:-recipes/zlib.toml}"
|
|
|
|
log() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
|
|
ok() { printf '\033[1;32m✓\033[0m %s\n' "$*"; }
|
|
|
|
[ -f "$IMG" ] || { echo "no existe $IMG — corré scripts/lab-image.sh --crear" >&2; exit 1; }
|
|
|
|
log "1/4 empujando la imagen del lab ($(du -h "$IMG" | cut -f1)) a $IP"
|
|
rsync -a --partial-dir=.rsync-partial -e "$SSH" "$IMG" "root@$IP:$REMOTE/.dev-fs/lab-image.tar.zst"
|
|
|
|
log "2/4 reemplazando el rootfs del worker (rotación, no extracción encima)"
|
|
$SSH "root@$IP" "set -e
|
|
cd $REMOTE/.dev-fs
|
|
rm -rf alpine.nuevo && mkdir -p alpine.nuevo
|
|
zstd -d -q -c lab-image.tar.zst | tar -x -C alpine.nuevo
|
|
rm -rf alpine.viejo
|
|
[ -d alpine ] && mv alpine alpine.viejo
|
|
mv alpine.nuevo/alpine alpine
|
|
rmdir alpine.nuevo
|
|
rm -rf alpine.viejo"
|
|
|
|
log "3/4 recompilando hammer en el worker (el binario debe traer el lab en hash_inputs)"
|
|
# `touch` ANTES de compilar, y no es paranoia: `rsync -a` PRESERVA EL MTIME DEL HUB, así que un
|
|
# fuente recién sincronizado puede quedar más VIEJO que el binario que el worker compiló hace un
|
|
# rato ⇒ cargo dice «Finished in 0.09s» y no recompila nada. El worker se queda con el hammer
|
|
# anterior, calcula la huella vieja y el paso 4 falla sin que se vea por qué (2026-08-12).
|
|
$SSH "root@$IP" "cd $REMOTE && . \$HOME/.cargo/env 2>/dev/null
|
|
find crates -name '*.rs' -exec touch {} +
|
|
cargo build --release --bin hammer 2>&1 | tail -2"
|
|
|
|
log "4/4 EVIDENCIA: ¿el worker sella en la misma dirección que el hub?"
|
|
h_hub=$("$ROOT/target/release/hammer" --store "$ROOT/store" hash "$TESTIGO" | tail -1)
|
|
h_w=$($SSH "root@$IP" "cd $REMOTE && ./target/release/hammer --store ./store hash $TESTIGO 2>&1 | tail -1")
|
|
echo " hub : $h_hub"
|
|
echo " worker : $h_w"
|
|
if [ "$h_hub" = "$h_w" ]; then
|
|
ok "el worker sella igual que el hub — puede construir"
|
|
else
|
|
echo "⛔ DIVERGEN. Este worker NO debe construir: sus artefactos irían a direcciones que el hub"
|
|
echo " nunca va a buscar. Revisá que la imagen del lab llegó entera y que recompiló hammer." >&2
|
|
exit 1
|
|
fi
|