Ruff 0.16.0: el salto que rompió CI y por qué importa para equipos de Python
Astral lanzó Ruff 0.16.0 con un conjunto de reglas por defecto mucho más estricto. El cambio puede romper pipelines de CI si usan dependencias no fijadas; aquí explico el impacto, ejemplos y cómo reaccionar.
Qué es Ruff 0.16.0 y qué cambió
Ruff es una herramienta de linting para Python que ha ganado tracción por ser rápida y cubrir muchas reglas estáticas. El 23 de julio Astral publicó la versión 0.16.0, y el cambio más visible es que Ruff ahora habilita 413 reglas por defecto, frente a 59 en versiones anteriores. Desde la versión 0.1.0 la cantidad total de reglas ha crecido de 708 a 968, pero hasta ahora no todas estaban activadas por defecto.
La novedad principal es que muchas reglas que detectan problemas severos —errores de sintaxis y fallos que causan errores en tiempo de ejecución— ahora son activas sin necesidad de configuración adicional. El objetivo es que Ruff señale problemas importantes de forma inmediata en cualquier proyecto Python, incluso sin archivo de configuración.
Impacto inmediato en proyectos y pipelines de CI
Si mantienen dependencias de desarrollo sin fijar la versión (dev dependency sin pin), una actualización automática a Ruff 0.16.0 puede provocar que sus jobs de CI comiencen a fallar. Esto fue exactamente lo que me pasó: varios pipelines empezaron a marcar errores en proyectos con tests completos y compatibilidad con Python 3.10–3.14.
Para probar Ruff en un repositorio cualquiera se puede usar esta instrucción: uvx ruff@latest check . y para intentar arreglos automáticos: uvx ruff@latest check . --fix --unsafe-fixes.
En mi experiencia, ejecuté Ruff en tres proyectos principales —Datasette, sqlite-utils y LLM— y encontró cientos de incidencias relacionadas con las nuevas reglas por defecto. En uno de los proyectos, sqlite-utils, el comando de arreglo automático reportó: “Found 1618 errors (1538 fixed, 80 remaining).”
Es importante subrayar que estos proyectos tenían suites de prueba muy completas y se ejecutan en CI contra varias versiones de Python, lo que reduce el riesgo real de introducir bugs funcionales. Aun así, la aparición masiva de avisos puede requerir trabajo manual para dejar el código limpio frente a las nuevas reglas.
Ejemplos concretos que Ruff detectó
Ruff no solo lanza una lista de errores; suele explicar cada uno. Aquí hay tres ejemplos ilustrativos tal como los informó Ruff:
DTZ005 `datetime.datetime.now()` called without a `tz` argument --> tests/test_duplicate.py:17:10
15 | "datetime_col" TEXT)""")
16 | # Insert one row of mock data:
17 | dt = datetime.datetime.now() | ^^^^^^^^^^^^^^^^^^^^^^^
18 | data = {
19 | "text_col": "Cleo",
help: Pass a `datetime.timezone` object to the `tz` parameter
BLE001 Do not catch blind exception: `Exception` --> tests/test_plugins.py:16:12
14 | db.execute("select * from pragma_function_list()")
15 | return True
16 | except Exception: | ^^^^^^^^^
17 | return False
18 | finally:
B018 Found useless attribute access. Either assign it to a variable or remove it. --> tests/test_update.py:46:5
44 | def test_update_invalid_pk(fresh_db, pk, update_pk):
45 | table = fresh_db["table"]
46 | table.insert({"id1": 5, "id2": 3, "v": 1}, pk=pk).last_pk | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47 | with pytest.raises(NotFoundError):
48 | table.update(update_pk, {"v": 2})
Estos ejemplos muestran tres tipos de problemas comunes: manejo inseguro de zonas horarias, captura demasiado amplia de excepciones y accesos a atributos inútiles que probablemente indican código incompleto o confuso.
Automatización y ayuda de agentes de código
Un punto práctico: el reporte detallado de Ruff facilita que herramientas automatizadas o agentes de código propongan correcciones. Tras ejecutar Ruff, utilicé agentes basados en modelos de lenguaje para aplicar correcciones: Codex (GPT-5.6 Sol high) actualizó LLM y sqlite-utils, mientras que Claude Code (Opus 5) actualizó Datasette. Estos asistentes pueden acelerar el proceso, pero siempre hay que revisar los cambios en revisión de código y ejecutar las pruebas.
Consejos prácticos para equipos en América Latina
-
Fijen versiones de sus herramientas de desarrollo: para evitar sorpresas en CI, fijen la versión de Ruff (y otras herramientas) en sus ficheros de dependencia o en la configuración del pipeline.
-
Integren Ruff en CI con un plan de actualización: antes de actualizar a una versión mayor, prueben Ruff localmente con
uvx ruff@latest check .y evalúen la lista de errores. Consideren ejecutar--fixcon revisión humana posterior. -
Aprovechen los arreglos automáticos, pero revisen:
--fixy--unsafe-fixespueden corregir muchas cosas, pero también pueden introducir cambios que requieran validación en pruebas y revisión de código. -
Prioricen reglas críticas: si la avalancha de avisos impide avanzar, pueden deshabilitar temporalmente reglas específicas en el archivo de configuración de Ruff y planificar una limpieza gradual.
-
Usen agentes de código con cautela: los modelos pueden acelerar arreglos masivos, pero siempre revisen el diff y ejecuten la suite de tests. En equipos con procesos de revisión estrictos —comunes en empresas y proyectos serios de la región— los cambios automatizados deben pasar por el flujo normal de pull requests.
-
Comuníquenlo en su organización: cuando una herramienta central cambia su comportamiento, es clave informar a los equipos de desarrollo para coordinar la actualización y evitar bloqueos en el pipeline.
Conclusión
Ruff 0.16.0 representa un paso significativo hacia un linting más estricto y proactivo, detectando problemas que antes pasaban desapercibidos. Para equipos que gestionan proyectos Python en América Latina —especialmente en empresas y startups con pipelines automatizados— este tipo de actualización puede causar interrupciones si no se gestiona con cuidado.
La recomendación práctica es: prueben la nueva versión de Ruff en un entorno controlado, fijen versiones de dependencias en CI y usen las herramientas automáticas para acelerar correcciones, pero manteniendo revisiones humanas y la suite de pruebas como guardias finales. De ese modo pueden beneficiarse de una mayor calidad de código sin sufrir sorpresas en sus despliegues.
Fuente original: Simon Willison