From 8ee258a4ded1489c7cab885497a29cbd748dd72e Mon Sep 17 00:00:00 2001 From: Sergio Date: Thu, 27 Aug 2026 03:43:58 +0000 Subject: [PATCH] =?UTF-8?q?scripts:=20atribuir-fallos.py=20=E2=80=94=20qu?= =?UTF-8?q?=C3=A9=20receta=20EMITE=20cada=20error,=20no=20cu=C3=A1l=20lo?= =?UTF-8?q?=20sufre?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit El driver marca FALLA en la receta que invocó, pero `hammer build` construye deps recursivamente: si una dep muere, la FALLA sale a nombre del dependiente. El 2026-08-27 siete recetas figuraban rotas (xdg-desktop-portal, gnome-desktop, gjs, gdm, gnome-session, gnome-settings-daemon, gnome-shell) y ninguna lo estaba: los 1978 errores los emitía gdk-pixbuf. Los tiempos de 2-10 s son la firma — demasiado rápido para ser un build propio. Método: quitar ANSI, partir el log por los marcadores `fetch … name=X` y atribuir cada error al último fetch anterior. Ya destapó dos causas reales (gdk-pixbuf/gif y gtk4/PIC) y desinfló la lista de la frontera _ssl, donde `No module named` lo emite SÓLO spidermonkey. --- scripts/atribuir-fallos.py | 62 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100755 scripts/atribuir-fallos.py diff --git a/scripts/atribuir-fallos.py b/scripts/atribuir-fallos.py new file mode 100755 index 00000000..08d5c2df --- /dev/null +++ b/scripts/atribuir-fallos.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +"""atribuir-fallos.py — dice QUÉ receta EMITE cada error, no cuál lo sufre. + +El driver marca FALLA en la receta que invocó, pero `hammer build` construye deps +recursivamente: si una dep muere, la FALLA sale a nombre del dependiente. El 2026-08-27 +siete recetas (xdg-desktop-portal, gnome-desktop, gjs, gdm, gnome-session, +gnome-settings-daemon, gnome-shell) figuraban como rotas y ninguna lo estaba: los 1978 +errores los emitía `gdk-pixbuf`. Los tiempos de 2-10 s son la firma — demasiado rápido +para ser un build propio. + +Método: quitar ANSI, partir el log por los marcadores `hammer_build: fetch … name=X` y +atribuir cada línea de error al último `fetch` anterior. + +Uso: scripts/atribuir-fallos.py [work/reconstruccion-detalle.log] [--desde 2026-08-27T03:] +""" +import re, sys, bisect, collections + +PATRONES = [ + ("PIC", r"recompile with -fPIC"), + ("_ssl", r"No module named '_ssl'"), + ("modulo", r"ModuleNotFoundError: No module named"), + ("ninja", r"ninja: subcommand failed"), + ("FAILED", r"^FAILED:"), + ("fase", r"Error: build phase falló"), + ("undef", r"undefined (?:reference|symbol)"), + ("nospace", r"No space left on device"), +] + +log = sys.argv[1] if len(sys.argv) > 1 and not sys.argv[1].startswith("--") else "work/reconstruccion-detalle.log" +desde = None +if "--desde" in sys.argv: + desde = sys.argv[sys.argv.index("--desde") + 1] + +raw = re.sub(r"\x1b\[[0-9;]*m", "", open(log, encoding="utf-8", errors="replace").read()) +lineas = raw.splitlines() +if desde: + ini = next((j for j, l in enumerate(lineas) if desde in l), 0) + lineas = lineas[ini:] + +marcas = [(i, m.group(1)) for i, l in enumerate(lineas) + if (m := re.search(r"hammer_build: fetch hash=\S+ name=(\S+)", l))] +if not marcas: + print("sin marcadores `fetch` en la ventana — ¿log equivocado o --desde muy tarde?") + sys.exit(1) +idx = [i for i, _ in marcas] + +print(f"{len(marcas)} builds arrancados en la ventana\n") +tabla = collections.defaultdict(collections.Counter) +for etiqueta, pat in PATRONES: + rx = re.compile(pat) + for i, l in enumerate(lineas): + if rx.search(l): + k = bisect.bisect_right(idx, i) - 1 + tabla[marcas[k][1] if k >= 0 else "(antes de la ventana)"][etiqueta] += 1 + +if not tabla: + print("ningún error reconocido") +else: + print(f"{'receta que EMITE':32} errores") + for receta, c in sorted(tabla.items(), key=lambda kv: -sum(kv[1].values())): + det = " ".join(f"{k}={v}" for k, v in c.most_common()) + print(f" {receta:30} {det}")