Linting en CI/CD
Ejecuta ESLint, Prettier y verificación de tipos con TypeScript en GitHub Actions para garantizar la calidad del código en cada solicitud de extracción.
Busca en todas las páginas de la documentación
Ejecuta ESLint, Prettier y verificación de tipos con TypeScript en GitHub Actions para garantizar la calidad del código en cada solicitud de extracción.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
// scripts de package.json
{
"scripts": {
"lint": "next lint",
"format:check": "prettier --check .",
"type-check": "tsc --noEmit"
}
}# Ejecuta todos los controles localmente (igual que CI)
npm run lint && npm run format:check && npm run type-checkCuándo usarlo: En cada proyecto que usa solicitudes de extracción. CI es tu red de seguridad para detectar problemas que los hooks previos a commit no detectan.
# .github/workflows/code-quality.yml
name: Code Quality
on:
pull_request:
branches: [main]
push:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
quality:
name: Lint, Format & Type Check
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: "npm"
- name: Install dependencies
run: npm ci
- name: ESLint
run: npm run lint
- name: Prettier
run: npm run format:check
- name: TypeScript
run: npm run type-checkLo que esto demuestra:
npm ci instala versiones exactas del archivo de bloqueo (más rápido y determinista)cache: "npm" cachea node_modules entre ejecuciones para mayor velocidadconcurrency cancela las ejecuciones en progreso cuando se envían nuevos commitstimeout-minutes evita que los trabajos atascados se ejecuten indefinidamentemainnpm run lint ejecuta next lint, que sale con código 1 si hay erroresprettier --check sale con código 1 si algún archivo no está formateado correctamentetsc --noEmit sale con código 1 si hay errores de tipoTrabajos paralelos (más rápido para proyectos grandes):
jobs:
lint:
name: ESLint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: "npm"
- run: npm ci
- run: npm run lint
format:
name: Prettier
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: "npm"
- run: npm ci
- run: npm run format:check
type-check:
name: TypeScript
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: "npm"
- run: npm ci
- run: npm run type-checkCon Biome (un único control reemplaza lint + formato):
- name: Biome
run: npx biome check .Comentarios de revisión de PR con reviewdog:
- name: ESLint with reviewdog
uses: reviewdog/action-eslint@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review
eslint_flags: "src/"Esto publica errores de ESLint como comentarios de revisión en la PR en las líneas exactas que necesitan corrección.
Caché para pnpm:
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm"
- name: Install dependencies
run: pnpm install --frozen-lockfileConfiguración de protección de rama:
GitHub repo → Settings → Branches → Branch protection rules:
✓ Require status checks to pass before merging
✓ Require branches to be up to date before merging
Status checks: "Lint, Format & Type Check" (o nombres de trabajos individuales)
// tsc --noEmit verifica TODO el proyecto, no solo los archivos modificados.
// Esto es intencional - un cambio en un archivo puede romper tipos en otro lugar.
// Ejemplo: cambiar un tipo compartido
// types.ts
export type User = {
name: string;
email: string;
role: "admin" | "user"; // Agregar "moderator" aquí es seguro
};
// Pero eliminar "admin" rompe todo archivo que usa User.role === "admin"
// Solo tsc detecta esto - ESLint no puede.Cosas que te atraparán. Cada trampa incluye qué sale mal, por qué sucede y la corrección.
CI pasa pero falla localmente (o viceversa) - Diferentes versiones de Node.js, diferentes versiones de dependencias o comportamiento específico del SO. Corrección: Fija la versión de Node.js en CI para que coincida con la local. Usa npm ci (no npm install) para usar versiones exactas del archivo de bloqueo.
Errores de lint en archivos generados - CI lintea archivos que se generan durante la compilación (p. ej., cliente de Prisma, tipos de GraphQL). Corrección: Agrega directorios generados a .eslintignore o al array ignores en eslint.config.mjs y .prettierignore.
tsc es lento en CI - La verificación de tipos de TypeScript puede tomar 30 segundos o más en proyectos grandes. Corrección: Habilita "incremental": true en tsconfig.json y cachea el archivo .tsbuildinfo entre ejecuciones de CI. Alternativamente, usa @vercel/next-swc que realiza verificación de tipos más rápido.
La verificación de Prettier falla en finales de línea - Los desarrolladores de Windows envían archivos con CRLF, CI se ejecuta en Linux con LF. Corrección: Establece "endOfLine": "lf" en .prettierrc y configura Git: git config --global core.autocrlf input.
Protección de rama no aplicada - Los controles de estado solo bloquean la fusión si la protección de rama está configurada. Sin él, cualquiera puede fusionar PRs fallidas. Corrección: Habilita reglas de protección de rama en main y requiere que el trabajo de CI pase.
Otras formas de resolver el mismo problema - y cuándo cada una es la mejor opción.
| Alternativa | Úsalo Cuando | No lo Uses Cuando |
|---|---|---|
| Husky + lint-staged | Quieres detectar problemas antes de que lleguen a CI | Necesitas una red de seguridad de CI (usa ambos) |
| GitLab CI / CircleCI | No estás en GitHub | Estás en GitHub (Actions es nativo) |
trunk check | Quieres una herramienta de CI unificada que gestione linters por ti | Quieres control total sobre tu pipeline de CI |
| Vercel deployment checks | Solo te importan errores en tiempo de compilación | Quieres aplicación de lint y formato |
--no-verify.npm ci instala versiones exactas del archivo de bloqueo (determinista).node_modules primero para una instalación limpia.npm install en CI porque omite la resolución de dependencias.concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: truenpm ci.npm install localmente puede resolver versiones diferentes que npm ci en CI.npm ci.- name: Biome
run: npx biome check .Un único comando reemplaza tanto lint como verificación de formato.
reviewdog/action-eslint@v1."endOfLine": "lf" en .prettierrc.git config --global core.autocrlf input.tsc puede."incremental": true en tsconfig.json..tsbuildinfo entre ejecuciones de CI.ignores en eslint.config.mjs..prettierignore.tsc --noEmit aplicaRevisado por Chris St. John·Última actualización: 10 jul 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥