la caja trae fuentes git por SSH: el arreglo, en un guion idempotente

Lo que hasta ahora era estado a mano en la caja queda reproducible. Hace las cinco piezas medidas:
reescritura de URLs con url.insteadOf, la clave del host reexpresada SIN puerto (cargo la busca así),
la huella de github.com PINEADA contra la publicada —si no coincide, sale con error en vez de
aceptarla—, la IdentityFile por host, y `net.git-fetch-with-cli = true` para que cargo delegue en el
git de verdad. Además mueve CARGO_HOME fuera de la raíz de 5,9 G, que es lo que tiró la caja.

No mueve ningún hash: la URL es un localizador y no entra en hash_inputs (ADR 0013). Termina con un
control que CLONA de los dos orígenes; si alguno no llega, sale distinto de cero.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sergio
2026-09-17 19:36:03 +00:00
co-authored by Claude Opus 5
parent 8d1e765bf7
commit 0bb40af496
+76
View File
@@ -0,0 +1,76 @@
#!/bin/sh
# Deja la caja de producción capaz de TRAER FUENTES GIT — que hoy no puede por HTTPS.
#
# ── POR QUÉ (2026-09-17) ────────────────────────────────────────────────────────────────────────
# El `git` sellado del corpus no trae `git-remote-http` (falta libcurl): en la caja, cualquier receta
# que clone muere con
#
# git: 'remote-https' is not a git command
#
# y eso son 36 recetas de tawasuyu y ~90 de GitHub — o sea, casi todo lo propio. La salida es traer
# por SSH. **No cuesta ningún hash**: la URL es un LOCALIZADOR y no entra en `hash_inputs`
# (ADR 0013), así que el mismo commit por otro transporte sella el MISMO artefacto. Por eso esto no
# toca ninguna receta: el worker sigue clonando por HTTPS, que es lo que él sí puede.
#
# Idempotente. Se corre EN LA CAJA, como root.
set -eu
CONF_SSH=/root/.ssh/config
CONF_GIT=/root/.gitconfig
CONF_CARGO=/root/.cargo/config.toml
KH=/root/.ssh/known_hosts
# ── 1. reescritura de URLs ───────────────────────────────────────────────────────────────────────
git config --global url."ssh://gitea@git.gioser.net:2345/".insteadOf "https://git.tawasuyu.net/"
git config --global url."ssh://git@github.com/".insteadOf "https://github.com/"
# ── 2. la clave del host, SIN el puerto ──────────────────────────────────────────────────────────
# cargo tiene su propio cliente SSH y busca `git.gioser.net` pelado; con la entrada sólo como
# `[git.gioser.net]:2345` se planta con «This host key was found, but is associated with a different
# host». Es la MISMA clave, reexpresada — no es aceptar nada nuevo.
if ! grep -q "^git.gioser.net ssh-" "$KH" 2>/dev/null; then
grep "^\[git.gioser.net\]:2345 " "$KH" | sed "s|^\[git.gioser.net\]:2345 |git.gioser.net |" >> "$KH"
fi
# ── 3. github.com: la huella se PINEA contra la publicada, no se acepta a ciegas ─────────────────
GH_FP="SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU"
if ! grep -q "^github.com ssh-ed25519" "$KH" 2>/dev/null; then
ssh-keyscan -t ed25519 github.com > /tmp/gh.keys 2>/dev/null
fp=$(ssh-keygen -lf /tmp/gh.keys | awk '{print $2}')
[ "$fp" = "$GH_FP" ] || { echo "github.com anuncia $fp y NO la publicada $GH_FP — no la acepto" >&2; exit 1; }
cat /tmp/gh.keys >> "$KH"; rm -f /tmp/gh.keys
fi
# ── 4. qué clave usa cada host ───────────────────────────────────────────────────────────────────
grep -q "^Host github.com" "$CONF_SSH" 2>/dev/null || cat >> "$CONF_SSH" <<'SSHEOF'
Host github.com
HostName github.com
User git
IdentityFile /root/.ssh/github5
IdentitiesOnly yes
SSHEOF
chmod 600 "$CONF_SSH"
# ── 5. cargo delega en el git de verdad ──────────────────────────────────────────────────────────
# Sin esto, `cargo vendor` usa libgit2 y ni lee `IdentityFile` de ~/.ssh/config:
# «no authentication methods succeeded». Es fetch, no build: no toca ningún hash.
mkdir -p "$(dirname "$CONF_CARGO")"
grep -q "git-fetch-with-cli" "$CONF_CARGO" 2>/dev/null || printf '[net]\ngit-fetch-with-cli = true\n' >> "$CONF_CARGO"
# ── 6. CARGO_HOME NO puede vivir en la raíz ──────────────────────────────────────────────────────
# Son 5,9 G. El vendor del monorepo bajó 2,7 G, la raíz llegó al 100 % y la caja se CAYÓ ENTERA
# —sin HTTP, sin SSH y sin responder al ping— con Hetzner informando `running` (SDD 28 §6.50 quinquies).
if [ ! -L /root/.cargo ]; then
mkdir -p /work/cargo-home
[ -d /root/.cargo ] && cp -a /root/.cargo/. /work/cargo-home/ && rm -rf /root/.cargo
ln -s /work/cargo-home /root/.cargo
fi
# ── control: que de verdad LLEGUE, no que el fichero exista ─────────────────────────────────────
fallos=0
for u in "https://git.tawasuyu.net/tawasuyu/tawasuyu.git" "https://github.com/uutils/coreutils.git"; do
if timeout 45 git ls-remote "$u" >/dev/null 2>&1; then echo "$u"; else echo "$u"; fallos=$((fallos+1)); fi
done
[ "$fallos" -eq 0 ] || { echo "NO llega a $fallos origen(es)" >&2; exit 1; }
echo "la caja trae fuentes git por SSH"