CI/CD con GitHub Actions para Next.js: Pipeline Completo
Guia paso a paso para configurar CI/CD con GitHub Actions en tu proyecto Next.js. Linting, testing, build y deploy automatico a Vercel con cada push.
CI/CD con GitHub Actions para Next.js: Pipeline Completo
Configurar CI/CD con GitHub Actions para tu proyecto Next.js es una de esas cosas que parece compleja hasta que la haces una vez. Despues no entiendes como vivias sin ella. Cada push a tu repo dispara automaticamente linting, tests y build. Si algo falla, te enteras antes de que llegue a produccion. Si todo pasa, deploya solo.
Esta guia te lleva desde cero hasta un pipeline completo. No importa si nunca tocaste un archivo YAML de GitHub Actions. Vamos paso a paso.
Por que tu proyecto necesita CI/CD
Sin CI/CD, el flujo tipico es: escribes codigo, haces push, cruzas los dedos y deployeas manualmente. Si tienes suerte, funciona. Si no, descubres el bug en produccion cuando un usuario te reporta algo.
Con CI/CD, el flujo cambia completamente:
- Haces push o abres un pull request
- GitHub Actions automaticamente corre ESLint, los tests y el build
- Si algo falla, el PR se marca como fallido y no se puede mergear
- Si todo pasa, deploya automaticamente a produccion
Las ventajas concretas:
- Detectas errores antes: Un error de TypeScript que pasa en tu maquina no pasa en CI porque la configuracion es estricta
- Consistencia: No importa quien haga el push, las mismas validaciones corren siempre
- Confianza: Si el pipeline paso, sabes que el codigo compila, pasa los tests y el build funciona
- Historial: Cada run queda registrado. Si algo se rompe, puedes ver exactamente que commit lo causo
Requisitos previos
Antes de empezar, necesitas:
- Un proyecto Next.js funcionando en local (
npm run devsin errores) - Un repositorio en GitHub con tu proyecto pusheado
- ESLint configurado (Next.js lo incluye por defecto con
create-next-app)
No necesitas experiencia previa con YAML ni con GitHub Actions. Todo lo que necesitas saber de YAML lo vas a aprender aqui.
Si ya tienes deploy en Vercel
Si tu proyecto ya esta deployado en Vercel, la parte de CD (deploy automatico) ya la tienes resuelta. Esta guia te ayuda a agregar la parte de CI: linting, tests y build verification como checks obligatorios antes de mergear.
Tu primer workflow: lint automatico
Un workflow de GitHub Actions es un archivo YAML que vive en .github/workflows/ dentro de tu repositorio. Vamos a crear el mas basico posible: correr ESLint en cada push.
Crear el archivo
tu-proyecto/
├── .github/
│ └── workflows/
│ └── ci.yml
├── app/
├── components/
├── package.json
└── next.config.ts
Crea el archivo .github/workflows/ci.yml con este contenido:
# .github/workflows/ci.yml
name: CI
# Cuando se ejecuta este workflow
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lint:
# Maquina donde corre el job
runs-on: ubuntu-latest
steps:
# Paso 1: Clonar el repositorio
- name: Checkout codigo
uses: actions/checkout@v4
# Paso 2: Configurar Node.js
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: 20
# Paso 3: Instalar dependencias
- name: Instalar dependencias
run: npm ci
# Paso 4: Correr ESLint
- name: Lint
run: npm run lintQue hace cada parte
name: CI: El nombre que aparece en la interfaz de GitHubon: Define cuando se dispara el workflow. En este caso, en cada push amainy en cada pull request haciamainjobs: Los trabajos que se ejecutan. Un workflow puede tener multiples jobsruns-on: ubuntu-latest: La maquina virtual donde corre. Ubuntu es la opcion mas comun y rapidasteps: Los pasos dentro del job. Se ejecutan en ordennpm ci: Similar anpm installpero mas rapido y determinista. Usa elpackage-lock.jsonexacto sin modificarlo
npm ci vs npm install
Siempre usa npm ci en CI/CD. A diferencia de npm install, no modifica el package-lock.json y falla si hay inconsistencias. Esto garantiza que en CI se instalan exactamente las mismas versiones que en tu maquina local.
Verificar que funciona
Commitea el archivo y pushea:
$ Ve a tu repositorio en GitHub > pestaña Actions. Vas a ver tu workflow corriendo. Si ESLint pasa, el check se marca en verde. Si falla, en rojo con los errores en los logs.
Agregar tests al pipeline
Un linter detecta problemas de estilo y errores obvios, pero no verifica que tu logica funcione. Para eso necesitas tests. Vamos a configurar Vitest y agregarlo al workflow.
Configurar Vitest
$ Crea el archivo de configuracion:
// vitest.config.ts
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
import path from 'path'
export default defineConfig({
plugins: [react()],
test: {
environment: 'jsdom',
setupFiles: ['./vitest.setup.ts'],
globals: true,
},
resolve: {
alias: {
'@': path.resolve(__dirname, '.'),
},
},
})// vitest.setup.ts
import '@testing-library/jest-dom/vitest'Agrega el script en tu package.json:
{
"scripts": {
"dev": "next dev",
"build": "next build",
"lint": "next lint",
"test": "vitest run",
"test:watch": "vitest"
}
}Escribir un test basico
// __tests__/utils.test.ts
import { describe, it, expect } from 'vitest'
// Ejemplo: una funcion que formatea fechas
function formatearFecha(fecha: string): string {
return new Date(fecha).toLocaleDateString('es-MX', {
year: 'numeric',
month: 'long',
day: 'numeric',
})
}
describe('formatearFecha', () => {
it('formatea una fecha ISO correctamente', () => {
const resultado = formatearFecha('2026-03-03')
expect(resultado).toContain('marzo')
expect(resultado).toContain('2026')
})
it('maneja fechas invalidas', () => {
const resultado = formatearFecha('no-es-una-fecha')
expect(resultado).toBe('Invalid Date')
})
})Agregar el step de test al workflow
Actualiza el archivo ci.yml para incluir un job de test:
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout codigo
uses: actions/checkout@v4
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Instalar dependencias
run: npm ci
- name: Lint
run: npm run lint
test:
runs-on: ubuntu-latest
steps:
- name: Checkout codigo
uses: actions/checkout@v4
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Instalar dependencias
run: npm ci
- name: Tests
run: npm run testJobs en paralelo
Por defecto, los jobs de un workflow corren en paralelo. Lint y test se ejecutan al mismo tiempo en maquinas separadas, lo que reduce el tiempo total del pipeline.
Build verification
El linter pasa y los tests pasan, pero eso no garantiza que next build funcione. TypeScript puede tener errores que solo aparecen durante el build, o puedes tener imports rotos que no se detectan en dev mode.
Agrega un job de build al workflow:
build:
runs-on: ubuntu-latest
# Solo correr si lint y test pasaron
needs: [lint, test]
steps:
- name: Checkout codigo
uses: actions/checkout@v4
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Instalar dependencias
run: npm ci
- name: Build
run: npm run buildLa clave aqui es needs: [lint, test]. Esto le dice a GitHub Actions que el job de build solo corra si lint y test pasaron primero. No tiene sentido intentar el build si el linter encontro errores.
El flujo queda asi:
push / PR
├── lint ─────┐
└── test ─────┤
└── build (solo si ambos pasaron)Cachear dependencias para pipelines rapidos
Cada vez que corre el workflow, instala todas las dependencias desde cero. En un proyecto Next.js tipico, eso toma entre 30 segundos y 2 minutos. Multiplicado por tres jobs, es tiempo desperdiciado.
La solucion es cachear node_modules entre runs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout codigo
uses: actions/checkout@v4
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Instalar dependencias
run: npm ci
- name: Lint
run: npm run lintEl cambio es una sola linea: cache: 'npm' en el step de setup-node. GitHub Actions cachea automaticamente el directorio de cache de npm. Si el package-lock.json no cambio, las dependencias se restauran del cache en segundos.
Impacto del cache
En un proyecto Next.js tipico, el cache reduce el tiempo de instalacion de dependencias de 40-90 segundos a 3-5 segundos. En un pipeline con tres jobs, eso son entre 2 y 4 minutos ahorrados por cada run.
Cache avanzado: el store de Next.js
Next.js tiene su propio cache de build (.next/cache) que acelera builds subsecuentes. Puedes cachearlo tambien:
- name: Cache de Next.js
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.next/cache
# Regenerar cache cuando cambian dependencias o archivos de config
key: nextjs-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.ts', '**/*.tsx') }}
restore-keys: |
nextjs-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}-
nextjs-${{ runner.os }}-Esto puede reducir el tiempo de build de 60 segundos a 15-20 en builds incrementales.
Pull request checks: proteger tu rama principal
De nada sirve tener CI si alguien puede mergear un PR sin que pasen los checks. GitHub te permite configurar branch protection rules para hacer los checks obligatorios.
Configurar branch protection
- Ve a tu repositorio en GitHub > Settings > Branches
- Haz clic en Add branch protection rule
- En "Branch name pattern" escribe
main - Activa Require status checks to pass before merging
- Busca y selecciona tus checks:
lint,test,build - Activa Require branches to be up to date before merging
- Guarda los cambios
A partir de ahora, nadie puede mergear un PR a main si alguno de los checks falla. El boton de merge en GitHub se bloquea hasta que todo este en verde.
Primer run necesario
Los checks no aparecen en la lista hasta que el workflow haya corrido al menos una vez. Pushea el archivo ci.yml primero, espera a que complete, y despues configura las branch protection rules.
Que ve el equipo en un PR
Cuando alguien abre un PR, GitHub muestra el estado de cada check:
Checks:
✓ lint — Passed in 45s
✓ test — Passed in 1m 12s
✓ build — Passed in 2m 3s
✓ All checks have passedSi algo falla:
Checks:
✓ lint — Passed in 45s
✗ test — Failed in 38s
○ build — Skipped (needs test)
✗ Some checks were not successfulEl autor del PR ve los logs del error directamente en GitHub y puede corregir sin que nadie tenga que revisar codigo roto.
Deploy automatico con Vercel
Si ya tienes tu proyecto deployado en Vercel, el deploy automatico ya esta funcionando: cada push a main dispara un deploy a produccion, y cada PR genera un preview deployment.
Lo que puedes agregar con GitHub Actions es un paso adicional que corra tus validaciones antes de que Vercel haga el deploy. Asi te aseguras de que el deploy solo ocurra si CI pasa.
Opcion 1: Vercel + GitHub Actions en paralelo
La configuracion mas comun. Vercel sigue manejando los deploys, y GitHub Actions maneja las validaciones:
PR abierto
├── GitHub Actions: lint, test, build (CI)
└── Vercel: preview deployment (CD)
Merge a main
├── GitHub Actions: lint, test, build (CI)
└── Vercel: production deployment (CD)No necesitas configurar nada extra. Vercel y GitHub Actions corren en paralelo automaticamente.
Opcion 2: Deploy controlado por GitHub Actions
Si necesitas control total y quieres que el deploy solo ocurra si CI pasa, puedes usar la Vercel CLI desde GitHub Actions:
deploy:
runs-on: ubuntu-latest
needs: [lint, test, build]
# Solo deployar en push a main (no en PRs)
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Checkout codigo
uses: actions/checkout@v4
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Instalar Vercel CLI
run: npm install -g vercel
- name: Deploy a produccion
run: vercel --prod --token=${{ secrets.VERCEL_TOKEN }}
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}Para esta opcion necesitas agregar tres secrets en tu repositorio:
VERCEL_TOKEN: Lo generas en vercel.com/account/tokensVERCEL_ORG_ID: Lo encuentras en Vercel > Settings > GeneralVERCEL_PROJECT_ID: Lo encuentras en Vercel > tu proyecto > Settings > General
Alternativa: deploy a otras plataformas
GitHub Actions puede deployar a cualquier plataforma. Si usas Railway o DigitalOcean, el step de deploy cambia pero el pipeline de CI sigue igual:
# Ejemplo: deploy a Railway
deploy:
runs-on: ubuntu-latest
needs: [lint, test, build]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Checkout codigo
uses: actions/checkout@v4
- name: Deploy a Railway
uses: bervProject/railway-deploy@main
with:
railway_token: ${{ secrets.RAILWAY_TOKEN }}
service: tu-servicioLa parte de CI no cambia
El pipeline de CI (lint, test, build) es identico sin importar donde hagas deploy. Lo unico que cambia es el job final de deployment. Esto te da la libertad de migrar entre plataformas sin reescribir tu pipeline de validacion.
Avanzado: matrix strategy
Matrix strategy te permite correr el mismo job con diferentes configuraciones. El caso de uso mas comun es probar tu proyecto en multiples versiones de Node.js:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
steps:
- name: Checkout codigo
uses: actions/checkout@v4
- name: Configurar Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Instalar dependencias
run: npm ci
- name: Tests
run: npm run testEsto crea tres jobs que corren en paralelo, uno por cada version de Node.js. Si tu proyecto soporta Node 18, 20 y 22, verificas que funcione en las tres con un solo cambio.
Cuando usar matrix strategy
- Librerias o paquetes npm: Para garantizar compatibilidad con multiples versiones de Node.js
- Proyectos con multiples package managers: Probar con npm, yarn y pnpm
- Testing cross-OS: Probar en Ubuntu, macOS y Windows
Cuando NO usarla
Para la mayoria de aplicaciones Next.js, probar en una sola version de Node.js es suficiente. La matrix strategy aumenta el consumo de minutos. Si tu proyecto solo corre en produccion con Node 20, no necesitas probar en Node 18.
Avanzado: manejo de secrets y variables de entorno
Tu pipeline de CI probablemente necesita variables de entorno para funcionar. El build de Next.js puede necesitar NEXT_PUBLIC_SITE_URL, y tus tests pueden necesitar conexion a una base de datos de prueba.
Agregar secrets en GitHub
- Ve a tu repositorio > Settings > Secrets and variables > Actions
- Haz clic en New repository secret
- Escribe el nombre y el valor
Los secrets se encriptan y nunca se muestran en los logs, ni siquiera si haces echo $SECRET en un step.
Usar secrets en el workflow
build:
runs-on: ubuntu-latest
steps:
- name: Checkout codigo
uses: actions/checkout@v4
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Instalar dependencias
run: npm ci
- name: Build
run: npm run build
env:
NEXT_PUBLIC_SITE_URL: ${{ secrets.NEXT_PUBLIC_SITE_URL }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}Variables de entorno vs secrets
GitHub Actions distingue entre variables y secrets:
| Tipo | Encriptado | Visible en logs | Uso |
|---|---|---|---|
| Secrets | Si | Nunca | API keys, tokens, passwords |
| Variables | No | Si | URLs publicas, flags de configuracion |
Las variables se configuran en Settings > Secrets and variables > Actions > Variables y se acceden con vars.NOMBRE:
- name: Build
run: npm run build
env:
NEXT_PUBLIC_SITE_URL: ${{ vars.SITE_URL }}
API_SECRET: ${{ secrets.API_SECRET }}Secrets en forks
Si tu repositorio es publico y alguien abre un PR desde un fork, los secrets no estan disponibles en ese workflow por seguridad. Esto previene que alguien modifique el workflow para imprimir tus secrets. Los PRs de forks solo tienen acceso a variables publicas.
Seguridad del pipeline
Ademas de manejar secrets correctamente, considera agregar un step de seguridad a tu pipeline. Herramientas como datahogo pueden integrarse como step de CI para detectar secrets expuestos en tu codigo antes de que lleguen a produccion. Si tu repositorio ya esta conectado a datahogo, lo detecta automaticamente en cada PR.
Tambien puedes correr npm audit como parte del pipeline para detectar vulnerabilidades en dependencias:
- name: Auditoria de seguridad
run: npm audit --audit-level=highSi necesitas un enfoque mas completo de seguridad, revisa la guia de seguridad en aplicaciones Next.js.
Workflow completo
Este es el archivo ci.yml final con todas las piezas juntas: lint, test, build, cache, y deploy condicional:
# .github/workflows/ci.yml
name: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
# Cancelar runs anteriores del mismo PR para no desperdiciar minutos
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout codigo
uses: actions/checkout@v4
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Instalar dependencias
run: npm ci
- name: ESLint
run: npm run lint
test:
name: Tests
runs-on: ubuntu-latest
steps:
- name: Checkout codigo
uses: actions/checkout@v4
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Instalar dependencias
run: npm ci
- name: Vitest
run: npm run test
build:
name: Build
runs-on: ubuntu-latest
needs: [lint, test]
steps:
- name: Checkout codigo
uses: actions/checkout@v4
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Instalar dependencias
run: npm ci
- name: Cache de Next.js
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.next/cache
key: nextjs-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.ts', '**/*.tsx') }}
restore-keys: |
nextjs-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}-
nextjs-${{ runner.os }}-
- name: Build
run: npm run build
env:
NEXT_PUBLIC_SITE_URL: ${{ vars.SITE_URL }}
deploy:
name: Deploy
runs-on: ubuntu-latest
needs: [build]
# Solo deployar en push a main
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Checkout codigo
uses: actions/checkout@v4
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Instalar Vercel CLI
run: npm install -g vercel
- name: Deploy a produccion
run: vercel --prod --token=${{ secrets.VERCEL_TOKEN }}
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}Detalles importantes del workflow
concurrency: Cancela runs anteriores del mismo PR cuando haces un push nuevo. Si pusheas tres commits rapido, solo el ultimo run completa. Esto ahorra minutos de GitHub Actions.
needs: [lint, test]: El build solo corre si lint y test pasaron. No desperdicias minutos en un build que ya sabes que va a fallar.
if: github.event_name == 'push': El deploy solo corre en push directo a main, no en pull requests. Los PRs solo corren lint, test y build para validacion.
Estructura visual del pipeline
Pull Request:
├── lint (paralelo)
├── test (paralelo)
└── build (despues de lint + test)
Push a main:
├── lint (paralelo)
├── test (paralelo)
├── build (despues de lint + test)
└── deploy (despues de build)Debugging: cuando tu pipeline falla
Error: "npm ci" falla
npm ERR! `npm ci` can only install packages when your package-lock.json
npm ERR! is up-to-dateCausa: Tu package-lock.json no esta sincronizado con package.json.
Solucion: Corre npm install en local, commitea el package-lock.json actualizado y pushea.
$ Error: ESLint falla en CI pero no en local
Causa comun: Diferencia en versiones de Node.js o reglas mas estrictas en CI.
# Verifica que la version de Node.js sea la misma
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: 20 # Usa la misma version que en localError: build falla por variables de entorno
Error: NEXT_PUBLIC_SITE_URL is not definedCausa: El build necesita variables de entorno que no estan configuradas en el workflow.
Solucion: Agrega las variables como secrets o variables en GitHub y pasalas en el step de build. Si necesitas una guia detallada, revisa variables de entorno en Next.js y Vercel.
Error: timeout en tests
Error: Test timed out in 10000msCausa: Las maquinas de CI son mas lentas que tu maquina local. Un test que tarda 5 segundos local puede tardar 15 en CI.
Solucion: Aumenta el timeout en tu configuracion de Vitest:
// vitest.config.ts
export default defineConfig({
test: {
testTimeout: 30000, // 30 segundos
},
})Optimizaciones adicionales
Correr solo lo necesario
Si un push solo cambia archivos de documentacion, no tiene sentido correr el pipeline completo. Puedes filtrar por paths:
on:
push:
branches: [main]
paths-ignore:
- '*.md'
- 'docs/**'
- '.vscode/**'
pull_request:
branches: [main]
paths-ignore:
- '*.md'
- 'docs/**'
- '.vscode/**'Notificaciones de fallos
GitHub envia emails por defecto cuando un workflow falla, pero puedes configurar notificaciones a Slack o Discord:
notify:
runs-on: ubuntu-latest
needs: [build]
if: failure()
steps:
- name: Notificar fallo en Discord
uses: sarisia/actions-status-discord@v1
with:
webhook: ${{ secrets.DISCORD_WEBHOOK }}
status: ${{ job.status }}
title: "CI fallo"
description: "El pipeline fallo en ${{ github.repository }}"Badge de estado
Agrega un badge en tu README para mostrar el estado actual del pipeline:
Esto muestra un indicador verde (passing) o rojo (failing) en tiempo real.
Preguntas frecuentes
Cuantos minutos de GitHub Actions tengo disponibles?
| Plan | Minutos/mes | Almacenamiento |
|---|---|---|
| Free | 2,000 | 500 MB |
| Pro | 3,000 | 1 GB |
| Team | 3,000 | 2 GB |
| Enterprise | 50,000 | 50 GB |
Los repositorios publicos tienen minutos ilimitados y gratuitos.
Puedo correr GitHub Actions solo en PRs, no en push a main?
Si. Cambia el trigger:
on:
pull_request:
branches: [main]Esto es util si solo quieres validacion en PRs y confias en que el merge a main ya fue validado.
Como veo los logs de un run fallido?
Ve a tu repositorio > Actions > selecciona el run > haz clic en el job que fallo > expande el step con el error. GitHub muestra la salida completa de la terminal, incluyendo errores y stack traces.
El pipeline tarda mucho. Como lo optimizo?
Las tres optimizaciones con mayor impacto son:
- Cache de npm (
cache: 'npm'en setup-node): Reduce instalacion de 60s a 5s - Cache de Next.js (
actions/cachepara.next/cache): Reduce build de 60s a 20s - Concurrency (cancelar runs anteriores): Evita runs duplicados
Puedo tener multiples workflows?
Si. Puedes crear archivos separados para diferentes propositos:
.github/
└── workflows/
├── ci.yml (lint, test, build en PRs)
├── deploy.yml (deploy a produccion en push a main)
└── security.yml (auditoria semanal de dependencias)
Conclusion
El pipeline que construiste en esta guia cubre el 90% de lo que necesita un proyecto Next.js:
- Lint: Detecta errores de estilo y problemas obvios
- Test: Verifica que tu logica funcione correctamente
- Build: Confirma que TypeScript compila y el build de Next.js pasa
- Deploy: Lleva los cambios a produccion automaticamente
El archivo YAML completo tiene menos de 100 lineas. Lo configuras una vez y despues cada push y PR se valida automaticamente. Sin intervencion manual, sin olvidarte de correr los tests, sin deployear codigo roto.
Si ya tienes el deploy en Vercel configurado, solo necesitas la parte de CI. Si quieres control total del deploy, agrega el job final con la Vercel CLI. Y si tu plataforma de hosting es otra, el pipeline de CI sigue siendo exactamente el mismo.
Recursos adicionales
Preguntas frecuentes
Que es CI/CD y por que lo necesito para mi proyecto Next.js?
CI/CD (Continuous Integration / Continuous Deployment) automatiza el proceso de probar y deployar tu codigo. Cada vez que haces push, automaticamente corre linting, tests y build. Si todo pasa, deploya a produccion. Elimina errores humanos y te da confianza en cada release.
GitHub Actions es gratis?
Si para repos publicos (ilimitado). Para repos privados, GitHub ofrece 2,000 minutos gratuitos al mes en el plan Free, y 3,000 en Pro. Para la mayoria de proyectos Next.js, esto es mas que suficiente.
Puedo usar GitHub Actions si mi hosting no es Vercel?
Si. GitHub Actions puede deployar a cualquier plataforma: Vercel, Netlify, Railway, DigitalOcean, AWS, o tu propio servidor. Solo necesitas cambiar el step de deployment.
Como manejo secrets como API keys en GitHub Actions?
GitHub tiene un sistema de Encrypted Secrets. Vas a Settings > Secrets and variables > Actions y agregas tus secrets ahi. En el workflow los accedes con la sintaxis secrets.TU_SECRET. Nunca se exponen en logs.
Cual es la diferencia entre CI y CD?
CI (Continuous Integration) se encarga de validar tu codigo: correr linter, tests y build automaticamente. CD (Continuous Deployment) va un paso mas alla y deploya automaticamente a produccion cuando CI pasa. Puedes tener solo CI o ambos.
Articulos relacionados
Next.js 16: Guia de Migracion y Novedades
Migra tu proyecto de Next.js 15 a 16. Novedades principales, breaking changes, y pasos para actualizar sin romper tu app.
Testing en Next.js con Vitest y Playwright
Configura testing en tu proyecto Next.js. Unit tests con Vitest, E2E con Playwright, y como integrarlos en tu pipeline de CI/CD.
Tailwind CSS 4: Migracion desde v3
Migra tu proyecto de Tailwind CSS 3 a 4. Cambios principales, nuevo sistema de configuracion, CSS-first config y como actualizar sin romper tu app.