hammer-{core,build,bootstrap,overlay,journal,mirror,upgrade,agent,recover,cli}
→ takana-*, con sus deps de workspace, sus identificadores en el fuente y las
referencias -p de los scripts.
VERIFICADO que no mueve nada del corpus: `takana hash recipes/zlib.toml`
devuelve b3:dc363f26… , idéntico a antes del renombre. Los nombres de crate no
entran en hash_inputs, pero eso se comprueba, no se supone. 600 tests en verde.
DOS BINARIOS SE CONGELAN, y no por prolijidad:
- `hammerd` — paquete Y binario. Es componente de Stage 1 de la distro (musl,
busybox, hammerd, arje-zero), lo supervisa arje-zero en el sistema arrancado,
`PRESEED=hammerd` lo nombra en selfhost-verify y sus bytes anclan el baseline
of_tree. El nombre del crate va en los símbolos ⇒ renombrarlo mueve los bytes.
- `hammer-recover` — el PAQUETE se renombra a takana-recover, el BINARIO no.
hammer-live-install.sh lo copia a /usr/sbin/hammer-recover en sistemas ya
instalados y hornea un hook de arranque que lo invoca por ese nombre:
renombrarlo rompe máquinas instaladas, no el repo.
Consecuencia que hay que anotar igual: al renombrar hammer-core, los bytes de
hammerd cambian de todos modos porque linkea contra un crate con otro nombre.
El baseline of_tree del selfhost hay que rehacerlo — es efecto de la etapa 4,
no de un cambio de hammerd.
Las referencias en comentarios de recetas y docs (rutas hammer-core/src/…)
quedan para la etapa 5: son texto, no mueven hash.
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
|
|
# (`takana-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 takana --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/takana" --store "$ROOT/store" hash "$TESTIGO" | tail -1)
|
|
h_w=$($SSH "root@$IP" "cd $REMOTE && ./target/release/takana --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
|