Todos los artículos
Codigo mostrado en una pantalla oscura con resaltado de sintaxis
·devopsinfrastructuredevtoolsengineering-culture

Los patrones de GitHub Actions que vale la pena conservar

La mayoria de las configuraciones de GitHub Actions estan a un secreto mal configurado de un mal dia. Estos patrones separan los pipelines que aguantan de los que fallan silenciosamente.

Hay un tipo particular de confianza que viene de un badge de CI en verde — y un tipo particular de pavor cuando te das cuenta de que te ha estado mintiendo durante seis semanas.

GitHub Actions se ha convertido en la capa de CI/CD por defecto para una enorme porcion de la industria del software. Es accesible, esta profundamente integrado con donde la mayoria del codigo ya vive, y tiene un marketplace lleno de community actions que prometen resolver cualquier problema en tres lineas de YAML. Esa accesibilidad tambien es la fuente de la mayoria de los footguns.

Una publicacion reciente en dev.to de Prabhu Ponnambalam profundiza en los patrones que separan los pipelines que realmente se sostienen de los que acumulan deuda invisible — permisos mal configurados, drift de dependencias, y workflows que tienen exito sin realmente probar lo que te importa.

Es una buena pregunta forzada: ¿cuando fue la ultima vez que auditaste tu configuracion de Actions, en lugar de solo agregarle cosas?

El problema de permisos que nadie corrige

Los permisos por defecto del GITHUB_TOKEN en Actions son mas amplios de lo que la mayoria de los desarrolladores creen. Si scaffoldeaste tus workflows desde una plantilla o copiaste de un blog post (sin juzgar — todos lo hacemos), hay una buena probabilidad de que tus jobs se esten ejecutando con permisos de write en contents, pull requests y packages cuando solo necesitan read.

La solucion es casi insultantemente simple: agrega un bloque explicito de permissions al principio de cada archivo de workflow.

permissions:
  contents: read
  pull-requests: write

Restringe a lo que el job realmente necesita. Si una action maliciosa o comprometida se inyecta en tu cadena de dependencias — lo cual ya ha pasado — permisos demasiado amplios convierten una molestia en un incidente genuino.

Relacionado: fija tus third-party actions a un SHA de commit completo, no a un tag. Los tags son mutables. actions/checkout@v4 puede apuntar a codigo diferente manana que hoy. actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 no. Si, es feo. Si, importa.

Secretos que realmente no son secretos

El segundo modo de fallo es mas sutil. GitHub hace un trabajo razonable enmascarando secretos en los logs — pero solo los secretos que conoce. Si estas construyendo valores sensibles dinamicamente dentro de un step (concatenando una API key con un prefijo, o haciendo echo de una variable de entorno a traves de un comando de shell), puedes filtrar credenciales en texto plano sin ninguna advertencia obvia.

La disciplina aqui es sobre nunca hacer echo o interpolar secretos directamente en run steps. Pasalos como variables de entorno al step, y deja que la herramienta los consuma de esa manera. Y audita tus logs de workflow ocasionalmente — realmente leelos, no solo revises el badge de estado.

Tambien vale la pena senalar: los secretos a nivel de repositorio son visibles para cualquiera que pueda crear un pull request apuntando a tu repo, si has habilitado workflows en PRs desde forks. Esta es una configuracion comun para proyectos open-source que crea una exposicion real. Los workflows pull_request_target, en particular, se ejecutan en el contexto del repositorio base y pueden exponer secretos a PRs de forks. Ha afectado a proyectos reales a escala.

La bomba de tiempo del drift de dependencias

Los pipelines de CI acumulan dependencias rapido. Las actions en si, paquetes npm instalados mid-workflow, imagenes base de Docker, runtimes de lenguaje — cada uno de estos es una variable no controlada si no eres explicito con las versiones.

El patron que realmente funciona: bloquea todo, luego automatiza el desbloqueo. Usa Dependabot o Renovate para bumps de versiones de Actions, fija imagenes de Docker a digests, y usa lockfiles consistentemente. El objetivo no es congelar tu stack permanentemente — es asegurar que los cambios de version sean intencionales, revisados y visibles en tu historial de git.

Esto suena tedioso porque lo es, ligeramente. Pero la alternativa es un pipeline que misteriosamente empieza a fallar un martes porque una action upstream envio un breaking change, y tu estas buceando en las notas de entorno de ubuntu-latest tratando de averiguar que cambio.

Gates condicionales que realmente funcionan como gates

Un anti-patron comun: workflows que tienen condiciones de branch, pero esas condiciones se evaluan despues de que steps costosos ya se ejecutaron. O peor — steps de deployment que solo verifican if: github.ref == 'refs/heads/main' pero no verifican tambien que los steps anteriores realmente tuvieron exito.

GitHub Actions tiene una sintaxis robusta de needs para encadenar jobs con requisitos de dependencia explicitos. Usala. No confies en la propagacion implicita de exito a traves de una larga cadena de steps — haz que tu gate de deployment sea un job separado que requiera explicitamente que tu job de test pase.

deploy:
  needs: [test, security-scan]
  if: github.ref == 'refs/heads/main' && success()

Ese success() esta haciendo mas trabajo del que parece. Previene el deployment si cualquier job de needs fallo o fue cancelado — lo cual el comportamiento por defecto no siempre garantiza en matrix builds complejos.

Reusable workflows: la feature infrautilizada

La mayoria de los equipos no aprovechan los reusable workflows lo suficiente. En su lugar, ves el mismo bloque de setup de 40 lineas copiado y pegado en una docena de repos — setup de Node, instalacion de dependencias, configuracion de credenciales — divergiendo lentamente mientras cada uno se ajusta por razones locales.

Los reusable workflows te permiten definir un workflow una vez en una ubicacion compartida y llamarlo como una funcion. Las ganancias de consistencia son reales, pero la mejora en la postura de seguridad es la parte subestimada: cuando un fix de seguridad necesita aplicarse a un step de setup, lo actualizas en un solo lugar.

El trade-off es que los reusable workflows anaden una capa de indireccion que puede hacer el debugging mas dificil. Documentalos como documentarias una libreria compartida. Trata los breaking changes como breaking changes.

La verdadera disciplina

Ninguno de estos patrones es exotico. La razon por la que los pipelines acumulan deuda de seguridad y problemas de fiabilidad no es ignorancia — es que la configuracion de CI vive en un espacio raro. Es infraestructura, pero parece un archivo de configuracion. Es critica para la seguridad, pero se siente como pegamento de automatizacion. Nadie programa un sprint para limpiar su configuracion de Actions.

Los equipos con pipelines ajustados tratan GitHub Actions como codigo de produccion: revisado en cada cambio, auditado periodicamente y sujeto al mismo rigor que cualquier otra cosa que toque secretos y envie software.

El badge esta en verde. Eso es necesario, pero ni de lejos suficiente.