Odio de verdad GitHub Actions
(xlii.space)- Un desarrollador comparte su frustración con el bucle de retroalimentación lento y el proceso de depuración complejo de GitHub Actions
- En el proyecto tmplr, generó documentación con CUE mediante
build.rs, pero el problema empezó cuando falló el build de CI - De 4 plataformas, solo fallaba el build de Linux ARM; la causa fue la forma en que GitHub Actions oculta binarios x86_64 en runners arm64 durante cross builds
- Se repetía un bucle de retroalimentación ineficiente donde probar un solo cambio tomaba 2 a 3 minutos
- Como solución, eliminó
build.rsy cambió a un GNU Makefile, resolviendo el problema al controlar directamente la lógica de CI
Contexto del problema
- tmplr es una herramienta de scaffolding de archivos/proyectos que usa archivos de plantilla legibles y editables por humanos
- En
build.rsse usaba CUE para generarREADME.md,CHANGELOG.mdy archivos de versión/ayuda, garantizando consistencia - El trabajo en sí se completó en unas 1.5 horas, e incluso el artículo relacionado ya estaba escrito
- En local funcionaba bien, pero en el entorno de CI de GitHub Actions el build falló porque el binario de CUE no estaba instalado
Causa del fallo del build
- De las 4 plataformas (Linux ARM, macOS ARM, Linux x86_64, macOS x86_64), solo Linux ARM mostraba el error “command not found”
- La causa: el matrix cross build está fuertemente aislado, así que CUE solo se instaló en el host Linux x86_64 y en el host macOS ARM
- En macOS no hay problema para ejecutar binarios x86_64
- En Linux x86_64 tampoco hay problema para ejecutar binarios x86_64
- Pero GitHub Actions oculta los binarios x86_64 en runners arm64, dejándolos imposibles de ejecutar
Bucle de retroalimentación ineficiente
- Proceso repetido para resolver el problema:
1. Buscar posibles formas de corregirlo
2. Cambiarci.yml
3. Hacer commit y push (jj squash --ignore-immutable && jj git push)
4. Abrir la pestaña “Actions”
5. Abrir la ejecución más reciente
6. Abrir la ejecución de Linux ARM
7. Esperar unos segundos
8. Frustrarse
9. Repetir - Cada cambio individual tardaba 2 a 3 minutos
- Idealmente, GitHub podría ofrecer un runner local completo o alguna forma de revisar rápidamente el progreso después de hacer push
- Algo como un “scratch commit”: una manera de probar varias ejecuciones sin contaminar el historial de Git ni el registro de ejecuciones de Actions
- Pero actualmente esa función no existe
Solución
- Tras repetir el bucle durante 30 minutos, decidió detenerse
- Aplicó un enfoque recomendado en internet: “No dejes que GitHub Actions gestione la lógica; controla tú mismo el script y haz que Actions solo invoque ese script”
- Eliminó
build.rs(aunque le pesó, era un sacrificio necesario) - Movió todas las tareas de generación a un GNU Makefile
- Hizo commit de los archivos generados en el repositorio y revirtió los cambios de CI
- Problema resuelto
Conclusión
- GitHub Actions es una de las razones por las que no se pueden tener algunas cosas buenas
- Se pierde mucho tiempo depurando runners u optimizando procesos de build
- Aun así, también ofrece ventajas difíciles de conseguir por otros medios, como los builds para macOS
- Claro, tampoco se conoce otro sistema que sea más fácil de configurar que GitHub Actions
We are all doomed to GitHub Actions. …but at least I dodged the bullet early.
3 comentarios
GitHub Actions solo debería encargarse de configurar el entorno (SO, toolchain de compilación, …) y ejecutar scripts (shell, Python, bat, ps1…). Incluso si GitHub se cae, mientras tengas el entorno listo deberías poder compilar en cualquier lado. Cuando veo los workflows de GitHub Actions de estos días, pienso si de verdad hace falta ponerse a buscar y usar cosas hasta ese punto. Hace mucho tiempo Ansible terminó fracasando por hacer eso.
Opiniones en Hacker News
El problema principal de GitHub Actions es que el ciclo de retroalimentación es demasiado lento
Tener que hacer push y esperar solo para confirmar un fallo simple es realmente frustrante
Creo que es mejor separar las tareas de CI en scripts que puedan ejecutarse localmente, y usar las funciones de Actions solo como mejora progresiva
La combinación de
workflow_dispatchygh workflow runtambién está bien, pero es incómodo que este último no entregue de inmediato la URL del workflow ejecutadoMe ha funcionado bastante bien para obtener retroalimentación rápida
Si surge un problema, puedo depurarlo en un estado casi idéntico al entorno de GitHub Actions
Debería ser un requisito básico de cualquier sistema de CI
Al final, lo importante son funciones como cola de tareas, análisis de salida y telemetría del historial de compilaciones
gh workflow run, para obtener la URL tenía que volver a consultar la lista de ejecuciones del workflow mediante la API de GitHubSi había varias ejecuciones al mismo tiempo podía enredarse, pero por ahora funciona más o menos bien
Hice un resumen de consejos para diseñar CI
Un shell simple debería bastar
Lo ideal es definir los objetivos de CI en un
Makefiley llamarlos de forma simple, comomake ci-testDesde entonces manejo todo el CI con wrappers simples como
make buildSería bueno poder separarlos con marcadores como
BeginStep("Nombre del paso")El problema no es tanto GitHub Actions en sí, sino la automatización mal montada encima
La lógica debería ponerse en scripts con lenguajes como Python para que también se puedan ejecutar localmente
Cada vez hay que modificar el workflow, hacer push y esperar
Yo manejo todo mi CI dentro de contenedores
La plataforma de CI solo ejecuta ese contenedor, así que también puedo correrlo igual en local
A las plataformas no les gusta este enfoque, porque rompe el vendor lock-in
Si falla, puedes conectarte por SSH de inmediato para depurar, y también volver a ejecutar tras modificar el manifiesto sin hacer push de una rama
Eso sí, requiere self-hosting
La estandarización se vuelve más fácil, pero aparece el costo de mantener la imagen
En la práctica casi no hay lock-in, pero la gente está atrapada en el cargo cult de CI/CD
A mí sí me gusta GitHub Actions
Es mejor que Travis, que usaba antes, y para proyectos OSS es muy útil como recurso gratuito
Desde que adopté Nix, la reproducibilidad del entorno mejoró mucho y la combinación con Actions funciona bastante mejor
Un contenedor hecho con flake puede ejecutarse tal cual en Actions
Proyecto de ejemplo
Creo que GitHub Actions debería limitarse a llamar scripts de bash o Python
Bash tiene muchas limitaciones, Python es más flexible y también es fácil de ejecutar localmente
Un método ideal es instalar uv automáticamente y manejar dependencias, como en este artículo
Es más complejo que bash, pero en el entorno de Actions el impacto en rendimiento no es tan grande
El mayor problema de Actions es la forma en que lo promocionan como algo para componer workflows
Depurarlo es casi imposible y configurar la caché es complicado, lo que vuelve lentos los builds
Por eso resulta atractivo ejecutar todo directamente en una VM persistente
Soy fundador de Depot
Opero un servicio que ofrece runners de GitHub Actions más rápidos y baratos
La frustración que siente mucha gente refleja de verdad la opinión mayoritaria
El sistema de Actions es estructuralmente ineficiente, y cada semana encontramos nuevos cuellos de botella
Estoy convencido de que hay una forma mejor y la estamos poniendo a prueba
Más detalles en depot.dev
El fin de semana pasado hice una herramienta llamada
gg watch actionSirve para encontrar la action más reciente o en ejecución de la rama actual
Enlace de GitHub
gh”Aunque había un bug donde no se veía el repositorio en el comando
gg tuiMe preguntaba si una herramienta como
actayudaríanektos/act
Puede haber diferencias entre la ejecución local y la online por temas de arquitectura, pero aun así parece útil
Tenía como 80% de compatibilidad
SourceHut sí soporta eso y resulta muy conveniente
Parece ser un problema inevitable por la estructura que te obliga a meter la lógica dentro del YAML.
El texto de arriba parece dar más o menos esa respuesta abajo, pero también da la impresión de que, si reemplazas la parte de los scripts con Dagger, esa sería la respuesta correcta.
"No dejes que GitHub Actions gestione la lógica; controla los scripts directamente y haz que Actions solo invoque esos scripts"