GitHub Actions falla en el build

Cuando el workflow queda en rojo, revisa el job correcto, el entorno de CI y los permisos antes de tocar producción.

Síntoma y contexto

GitHub Actions aparece en rojo cuando un workflow no completa uno de sus jobs. Puede ser un build de Node que falla en npm ci, un test que rompe tras un cambio pequeño, un deploy bloqueado por permisos, o un paso que depende de una variable de entorno que existe en tu máquina pero no en GitHub. El síntoma visible suele ser una cruz roja en el commit, una pull request bloqueada o una notificación de "workflow failed".

Esta guía complementa la de errores de build en Cloudflare Pages. Cloudflare Pages ejecuta su propio build para publicar el sitio. GitHub Actions, en cambio, ejecuta lo que define tu archivo YAML bajo .github/workflows/. Puede construir, probar, generar artefactos, llamar a Cloudflare, publicar en Pages, revisar enlaces o hacer cualquier paso que hayas configurado. Por eso el diagnóstico empieza localizando el job exacto y leyendo el log de ese job, no mirando solo el estado general del repositorio.

La regla práctica es no cambiar varias capas a la vez. Si el workflow falló después de actualizar dependencias, mira primero instalación y lockfile. Si falló después de añadir un deploy, mira permisos y variables. Si falla solo en pull requests desde forks, revisa restricciones de secretos. No compartas tokens, API keys ni contenido de .env. Para diagnosticar casi siempre basta con nombres de variables, fragmentos de YAML y logs censurados.

Causas probables

  1. Versión de Node distinta a la local. El proyecto puede requerir Node 20 y el workflow estar usando Node 18, o depender de una versión declarada en .nvmrc que actions/setup-node no está leyendo.
  2. Lockfile ausente o desincronizado. npm ci es más estricto que npm install. Si package-lock.json no coincide con package.json, el CI falla aunque en local parezca funcionar.
  3. Caché corrupta o clave de caché demasiado amplia. Reutilizar node_modules o una caché de gestor de paquetes con una clave que no cambia al modificar el lockfile puede dejar dependencias antiguas.
  4. Variables de entorno o secrets no definidos. El YAML puede leer secrets.API_TOKEN, vars.PUBLIC_API_URL o variables de entorno necesarias para build. Si el nombre no existe, el valor llega vacío.
  5. Permisos insuficientes del GITHUB_TOKEN. Jobs que escriben comentarios, suben releases, publican Pages o empujan artefactos necesitan permisos explícitos como contents: read, pages: write o id-token: write.
  6. Diferencias entre push y pull request. En forks, GitHub limita secretos por seguridad. Un job que despliega puede fallar o saltarse en PRs externos aunque funcione en la rama principal.
  7. Rutas relativas incorrectas en monorepo. Si el proyecto vive en una subcarpeta, el workflow debe fijar working-directory o ejecutar comandos desde la ruta correcta.
  8. Comando local no reproducible en Linux limpio. Archivos ignorados, dependencias globales, mayúsculas en rutas y scripts que asumen macOS o Windows suelen romper en runners Ubuntu.

Checklist copiable

DIAGNÓSTICO GITHUB ACTIONS - [repo / workflow]
Fecha: ___________  Rama: ___________

1. RUN FALLIDO
   URL del run: ___________
   Workflow: ___________
   Job fallido: ___________
   Evento: push / pull_request / workflow_dispatch / schedule

2. ERROR
   Primer paso en rojo: ___________
   Primera línea de error real: ___________
   ¿Falla siempre o solo en PR? ___________

3. STACK
   Node en workflow: ___________
   Node local: ___________
   Gestor: npm / yarn / pnpm
   Comando que falla: ___________

4. DEPENDENCIAS
   [ ] Lockfile commiteado
   [ ] package.json y lockfile sincronizados
   [ ] Caché revisada o desactivada para probar

5. VARIABLES Y SECRETS
   Nombres esperados (sin valores): ___________
   [ ] Existen en Settings
   [ ] No pegué tokens ni valores secretos

6. PERMISOS
   permissions en YAML: ___________
   ¿Publica o escribe en repo? Sí / No

7. CAMBIOS RECIENTES
   [ ] Dependencias   [ ] YAML   [ ] Node   [ ] Secrets
   [ ] Deploy   [ ] Ninguno claro

Qué capturar antes de escribir

Guarda el enlace al run fallido, el nombre del workflow, el job que falla y el evento que lo lanzó. Copia desde la primera línea de error real hasta el final del paso, no todo el log si incluye datos sensibles. Si el workflow tiene varios jobs, indica si falló instalación, tests, build, subida de artefactos o deploy. Añade el archivo YAML relevante y, si aplica, el fragmento de package.json con scripts y engines.

Para variables, envía solo los nombres: por ejemplo PUBLIC_SITE_URL, CLOUDFLARE_ACCOUNT_ID o API_BASE_URL. No envíes valores de secrets, tokens de GitHub, tokens de Cloudflare, credenciales de npm ni archivos .env. Si una captura muestra un valor, tápalo antes de adjuntarla. También ayuda saber si el mismo comando funciona en local tras borrar node_modules y reinstalar con el lockfile.

Comandos y paneles útiles

En GitHub, mira estas zonas antes de tocar el YAML:

  • Actions -> workflow -> run fallido: Abre el job en rojo y expande el paso concreto. Usa los timestamps si el fallo es intermitente.
  • Settings -> Secrets and variables -> Actions: Comprueba que existen los nombres usados por el YAML. Revisa Repository, Environment y Organization según el caso.
  • Settings -> Actions -> General: Permisos de workflow y del GITHUB_TOKEN, políticas de forks y aprobación de workflows.
  • Environments: Si usas entornos como production o preview, revisa protection rules y secrets propios de ese environment.
# Reproducir instalación limpia
rm -rf node_modules
npm ci
npm run build

# Ver versión local de Node
node -v

# Ver scripts disponibles
npm run

# Si usas pnpm
pnpm install --frozen-lockfile
pnpm build

Un YAML mínimo para Node suele fijar versión, instalar con lockfile y construir:

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm run build

Pasos de diagnóstico por escenario

El workflow falla en npm ci o instalación

Comprueba que el lockfile está commiteado y corresponde al gestor real. Si usas npm, no mezcles yarn.lock o pnpm-lock.yaml como fuente de verdad. Ejecuta npm ci en local después de borrar node_modules; si falla igual, el problema no es GitHub Actions sino el estado de dependencias. Si solo falla en CI, revisa versión de Node, plataforma Linux y caché. Para aislar una caché sospechosa, cambia temporalmente la clave o desactiva cache en setup-node.

El build funciona en local pero falla en Actions

Lista qué necesita el build para ejecutarse: archivos de contenido, variables públicas, conexión a APIs, generadores de imágenes, binarios nativos o rutas concretas. En CI no existen archivos ignorados por Git ni variables de tu shell. Si el log dice que falta una variable, crea el nombre correcto en GitHub como secret o variable según su sensibilidad. No conviertas un secreto en variable pública para "ver si funciona": si el valor es privado, debe seguir en secrets.

El deploy falla por permisos

Busca mensajes como "Resource not accessible by integration", "403", "permission denied" o "id-token: write". En repos nuevos, los permisos por defecto pueden ser solo lectura. Añade un bloque permissions ajustado al job, no permisos amplios para todo el workflow si no hacen falta. Si el job publica en Cloudflare, confirma que el token externo existe y tiene alcance mínimo suficiente en Cloudflare, pero no lo pegues en el issue ni en el formulario.

Falla solo en pull requests

Comprueba si la PR viene de una rama del mismo repositorio o de un fork. GitHub restringe secretos en forks porque el código de la PR podría imprimirlos en logs. Separa jobs seguros de build y test, que pueden ejecutarse sin secretos, de jobs de deploy, que deberían correr solo en ramas confiables o con aprobación manual. Usa condiciones if claras para no intentar desplegar previews cuando faltan credenciales.

GitHub Actions está verde pero Cloudflare Pages falla

Son sistemas distintos. Un workflow verde puede indicar que los tests pasan, mientras Cloudflare Pages falla al ejecutar su propio build. En ese caso compara comando, versión de Node, directorio raíz y variables entre ambos entornos. La guía de Cloudflare Pages cubre la parte de panel y despliegue. Si el problema visible es la web caída después de un deploy, revisa también la web no carga. Si el fallo afecta a un formulario que dependía del deploy, puede servir la guía de formulario que no envía.

Cuándo escalar

Escala o escribe por el formulario con categoría Web o despliegue cuando el log apunta a permisos, CI o publicación y no queda claro si debes tocar GitHub, Cloudflare o el código. También conviene pedir revisión si el workflow usa secrets en varios entornos, si hay monorepo con rutas cruzadas, si el build falla solo de forma intermitente o si un cambio de YAML puede afectar a producción.

Envía el enlace al run, el YAML relevante, el nombre de variables sin valores, versión de Node y qué comando probaste en local. No adjuntes tokens ni exports completos de configuración. Relacionado: error en Cloudflare Pages, web caída, formulario no envía.

¿Sigues atascado después de la checklist?

Escribir el problema Volver al triage