exp-ec: tres fallos del propio arnés — sellaba basura y el veredicto no miraba el estado de salida

Los encontró la corrida en el worker, y los tres estaban disfrazados de resultado.

1. El `exit 77` se insertaba antes de la ÚLTIMA `'''` del fichero, que no siempre cierra una fase:
   una receta puede traer bloques `'''` después (un `[[service]]`, una nota larga). En `dwarves`,
   `elfutils` y `elfutils-libdw` cayó fuera de toda fase, el build corrió entero y SELLÓ — con el
   hash movido por el `set -e`, o sea tres artefactos basura. Ahora se rastrea la anidación.

2. El veredicto se leía con `grep "exit 77"` sobre el log, y takana IMPRIME el script de la fase:
   esa cadena aparece siempre porque la inyectamos nosotros. Daba SOBREVIVE hasta a un build que
   selló. Ahora se ata a `build phase falló (exit 77)`, que es el estado de salida de verdad.
   (Comprobado a posteriori que los 14 SOBREVIVE de la corrida buena sí habían salido 77.)

3. Sin `--store`, takana usa su default `/store`, que en el worker es un store de SCRATCH casi
   vacío — reconstruía el mundo en vez de reusar el de la granja (`./store`, 908 artefactos). Ahora
   el store va por `STORE`.

Y un guardián para lo que no debería volver a pasar: si un build SELLA, se clasifica
`SELLO-INDEBIDO` y se grita el hash, en vez de contarse como un resultado más. Los tres artefactos
basura ya se borraron del `/store` de scratch del worker; el store de la granja nunca se tocó.
This commit is contained in:
Sergio
2026-09-18 19:19:28 +00:00
parent 7b09e26eca
commit 1a97da9839
+20 -4
View File
@@ -43,14 +43,30 @@ while read -r r; do
/^(compile|install|configure|check|prepare) = .{3}$/ { print; print "set -e"; inb=1; next }
{ print }
' "$r" > "$REC/exp-ec-$n.toml"
# `exit 77` como última línea de la última fase del fichero
last=$(grep -n "^'''$" "$REC/exp-ec-$n.toml" | tail -1 | cut -d: -f1)
# El `exit 77` va al cierre de la ÚLTIMA FASE, que NO es la última `'''` del fichero: una receta
# puede traer bloques `'''` después de las fases (un `[[service]]`, una nota larga). MEDIDO el
# 2026-09-18: en `dwarves`, `elfutils` y `elfutils-libdw` el `exit 77` cayó fuera de toda fase, el
# build corrió entero y SELLÓ — con el hash movido por el `set -e`, o sea basura en el store. Por
# eso acá se rastrea la anidación en vez de buscar la última comilla triple.
last=$(awk '
/^(compile|install|configure|check|prepare) = .{3}$/ { dentro=1; next }
dentro && /^.{3}$/ { fin=NR; dentro=0 }
END { print fin }' "$REC/exp-ec-$n.toml")
[ -n "$last" ] || { echo "[SIN-FASES] $n"; printf '%s\t%s\t%s\n' "$n" "SIN-FASES" "" >> "$OUT"; rm -f "$REC/exp-ec-$n.toml"; continue; }
[ -n "$last" ] && sed -i "${last}i exit 77" "$REC/exp-ec-$n.toml"
log="$TMP/$n.log"
timeout "$TLIMITE" flock -o "$LOCK" "$TAKANA" build "$REC/exp-ec-$n.toml" > "$log" 2>&1
timeout "$TLIMITE" flock -o "$LOCK" "$TAKANA" ${STORE:+--store "$STORE"} build "$REC/exp-ec-$n.toml" > "$log" 2>&1
rc=$?
if grep -q "exit 77" "$log"; then v="SOBREVIVE"
# ⚠ El veredicto se lee en el ESTADO DE SALIDA que reporta takana, NO buscando `exit 77` en el
# log: takana IMPRIME el script de la fase, así que esa cadena aparece SIEMPRE — la inyectamos
# nosotros. Buscarla a secas daría SOBREVIVE hasta a un build que selló.
if grep -q "build phase falló (exit 77)" "$log"; then v="SOBREVIVE"
elif grep -qE "sealed path=\S*-$n\$" "$log"; then
# No debería pasar nunca: si selló, el `exit 77` no llegó a correr y el artefacto lleva el hash
# MOVIDO por el `set -e` ⇒ es basura en el store. Se grita con el hash para poder borrarlo.
v="SELLO-INDEBIDO"
echo " ⚠⚠ $n SELLÓ — basura: $(grep -oE "sealed path=\S+" "$log" | tail -1 | sed 's|.*/||')"
elif [ $rc -eq 124 ]; then v="TIMEOUT"
elif grep -qE "build phase falló \(exit [0-9]+\)" "$log"; then v="SE-ROMPE"
else v="OTRO"; fi