diff --git a/.gitea/workflows/ai-review.yml b/.gitea/workflows/ai-review.yml index 4a57463..60d4bee 100644 --- a/.gitea/workflows/ai-review.yml +++ b/.gitea/workflows/ai-review.yml @@ -179,15 +179,56 @@ jobs: # comentarios: imprime el traceback y saluda con # "AI review completed successfully!". Sin esto el job quedaria en # verde sin haber revisado nada, que es peor que fallar. + # + # Cuidado con QUE se busca: el log tambien trae el texto de los + # comentarios que escribe el modelo, y ese texto puede decir + # cualquier cosa. El patron 'Error: ' que habia antes se disparo con + # el comentario de la propia revision (inventario#3) y marco como + # fallida una revision que habia salido bien. Por eso ahora se miran + # las marcas de nivel que imprime la herramienta, que el modelo no + # escribe, y el traceback al principio de linea. + ERRORES='\| (ERROR|CRITICAL) \||^Traceback \(most recent call last\)' + + # El plan gratuito de OpenRouter devuelve 502 cuando los proveedores + # del modelo estan saturados; pasó el 03/08/2026 y el pull request se + # mergeo sin revisar. Eso se reintenta, pero un 401 o un modelo que ya + # no existe no se arreglan esperando: por eso solo reintentamos con + # las marcas que deja una falla al pedirle la respuesta al modelo. + # Todas ocurren antes de publicar nada, asi que el reintento no puede + # dejar comentarios repetidos. + PASAJEROS='OpenRouterChatResponseSchema|LLM returned empty|Upstream|Too Many Requests|timed out' + INTENTOS=3 + PRIMERA_ESPERA=30 + revisar() { - echo "== ai-review $1" - if ! ai-review "$1" 2>&1 | tee "/tmp/ai-review-$1.log"; then - return 1 - fi - if grep -qiE 'Traceback \(most recent call last\)|HTTPClientError|Error: ' "/tmp/ai-review-$1.log"; then - echo "La revisión reportó errores en '$1' pese a terminar sin código de error." >&2 - return 1 - fi + modo="$1" + registro="/tmp/ai-review-${modo}.log" + intento=1 + espera="${PRIMERA_ESPERA}" + + while : ; do + echo "== ai-review ${modo} (intento ${intento} de ${INTENTOS})" + + # Sin tuberia a proposito: con "| tee" el codigo que se evalua es + # el de tee, que siempre da 0, y la falla pasaba desapercibida. + salida=0 + ai-review "${modo}" > "${registro}" 2>&1 || salida=$? + cat "${registro}" + + if [ "${salida}" -eq 0 ] && ! grep -qE "${ERRORES}" "${registro}"; then + return 0 + fi + + if [ "${intento}" -ge "${INTENTOS}" ] || ! grep -qE "${PASAJEROS}" "${registro}"; then + echo "La revisión reportó errores en '${modo}' pese a terminar sin código de error." >&2 + return 1 + fi + + echo "Falla pasajera del proveedor; reintento en ${espera}s." >&2 + sleep "${espera}" + intento=$((intento + 1)) + espera=$((espera * 2)) + done } # Para depurar la configuración existe "ai-review show-config", pero