Docs

Sistema de Git Hooks

Sistema de calidad automatizada con Husky, lint-staged, commitlint y plugins ESLint para garantizar la calidad del código en el ecosistema Nvito.

PublicadoMarzo 2026Equipo de desarrollo, colaboradores

1. Introducción

El ecosistema Nvito implementa un sistema de calidad automatizada basado en Husky v9 que ejecuta scripts automáticamente en eventos clave de Git. Cada vez que un desarrollador hace commit, push o cambia de rama, una serie de verificaciones se ejecutan de forma transparente para garantizar que:

  • El código cumple con las reglas de linting y formato establecidas.
  • Los mensajes de commit siguen el estándar Conventional Commits.
  • No se filtran secrets ni archivos prohibidos al repositorio.
  • Los tipos de TypeScript compilan correctamente antes de publicar cambios.
  • Los tests pasan antes de enviar código al remoto.

Este sistema opera en los 7 repositorios del ecosistema (nvito-api, nvito-admin, nvito-invitations, nvito-client, nvito-pwa, nvito-docs y nvito-landing) con configuraciones adaptadas al tier de cada proyecto.

2. Hooks implementados

El sistema cuenta con 6 hooks de Git que cubren todo el ciclo de vida de un cambio:

HookMomentoVerificacionesTiempo
pre-commitAntes de crear el commitlint-staged (ESLint + Prettier) + secretlint + archivos prohibidos + tamañoMenos de 10s
commit-msgValida el mensaje de commitConventional Commits vía commitlintMenos de 1s
prepare-commit-msgAntes de abrir el editorDetecta branch gitflow y genera prefijo automáticoMenos de 1s
pre-pushAntes de enviar al remotoProtección de branches + tsc + tests completos30s–2min
post-checkoutAl cambiar de branchAviso si package-lock.json o Prisma cambiaronMenos de 1s
post-mergeTras merge o pullAviso si package-lock.json cambióMenos de 1s

Los hooks post-checkout y post-merge son informativos: muestran un aviso en la terminal recomendando ejecutar npm install o npx prisma generate, pero no bloquean la operación. Los demás hooks sí bloquean si detectan problemas.

pre-commit: la primera línea de defensa

El hook pre-commit ejecuta cuatro verificaciones en paralelo:

  1. lint-staged: ejecuta ESLint y Prettier únicamente sobre los archivos staged (modificados), no sobre todo el proyecto.
  2. secretlint: analiza los archivos staged buscando patrones de API keys, tokens, contraseñas y otros secrets.
  3. Archivos prohibidos: rechaza el commit si se incluyen archivos como .env, .env.local, claves privadas o archivos de credenciales.
  4. Tamaño de archivos: advierte si algún archivo staged supera un umbral razonable.

pre-push: verificación profunda

El hook pre-push es el más exhaustivo y ejecuta:

  1. Protección de branches: impide push directo a main y develop (solo se permite vía merge request).
  2. TypeScript check: ejecuta tsc --noEmit para verificar que no hay errores de tipos.
  3. Tests completos: ejecuta la suite completa de tests del proyecto con --bail para fallar rápido.

3. Conventional Commits

Todos los repositorios de Nvito utilizan el estándar Conventional Commits validado por commitlint. Esto garantiza un historial de Git limpio, legible y apto para generación automática de changelogs.

Formato

<tipo>(<scope>): <descripción>
  • tipo: categoría del cambio (obligatorio).
  • scope: repositorio o módulo afectado (obligatorio en Nvito).
  • descripción: resumen breve en minúsculas, sin punto final (obligatorio).

Tipos permitidos

TipoDescripciónEjemplo
featNueva funcionalidadfeat(admin): add guest capacity bar component
fixCorrección de bugfix(api): correct timezone offset in RSVP response
docsCambios en documentacióndocs(docs): add git hooks guide
styleFormato, espacios, puntos y comas (sin cambio funcional)style(admin): fix indentation in sidebar component
refactorReestructuración de código sin cambio funcionalrefactor(api): split notification service into sub-services
perfMejora de rendimientoperf(api): add database index for event queries
testAgregar o modificar teststest(client): add unit tests for auth reducer
buildCambios en sistema de build o dependenciasbuild(pwa): upgrade Next.js to 16.x
ciCambios en integración continuaci(api): add staging deploy workflow
choreTareas de mantenimientochore(deps): update eslint plugins

Scopes del ecosistema

ScopeRepositorio
apinvito-api
adminnvito-admin
clientnvito-client
pwanvito-pwa
invitationsnvito-invitations
docsnvito-docs
landingnvito-landing
depsDependencias transversales

Ejemplos de buenos mensajes de commit: - feat(api): add endpoint for cash fund contributions

  • fix(admin): resolve infinite loop in event wizard validation - refactor(client): extract auth logic into dedicated reducer - test(invitations): add security tests for XSS payloads - docs(docs): update deployment guide with Railway setup

Ejemplos de mensajes rechazados por commitlint: - updated stuff — falta tipo y scope - Fix bug — falta scope, la descripción empieza con mayúscula - feat: add new feature — falta scope (obligatorio en Nvito) - feat(api): Add endpoint. — la descripción no debe empezar con mayúscula ni terminar con punto

Auto-prefijo con prepare-commit-msg

El hook prepare-commit-msg detecta automáticamente la rama actual y genera un prefijo basado en el patrón gitflow:

  • Si estás en feature/admin-guest-capacity, al ejecutar git commit el editor se abre con feat(admin): prellenado.
  • Si estás en fix/api-timezone-offset, el editor muestra fix(api): prellenado.
  • Si estás en refactor/client-auth-split, el editor muestra refactor(client): prellenado.

Esto reduce errores y acelera el flujo de trabajo. El desarrollador solo necesita completar la descripción.

4. Plugins ESLint

Además de las reglas estándar de ESLint, los repositorios de tier 1 incluyen tres plugins especializados:

no-only-tests

Previene que se suban tests con .only() al repositorio. Cuando un desarrollador usa describe.only() o it.only() para depurar localmente y olvida quitarlo, solo ese test ejecutaría en CI y el resto se ignoraría silenciosamente.

Protección activa: este plugin convierte cualquier .only() en un error de ESLint que bloquea el commit automáticamente vía lint-staged. Esto protege las 254+ suites de nvito-api (y las de todos los repos) de ejecutarse parcialmente sin que nadie lo note.

unused-imports

Detecta y auto-elimina imports que no se usan en el archivo. Al ejecutar eslint --fix, los imports huérfanos se eliminan automáticamente, manteniendo el código limpio sin intervención manual.

simple-import-sort

Ordena automáticamente los imports de cada archivo de forma consistente al ejecutar --fix. El orden agrupa:

  1. Dependencias externas (react, next, @nestjs/*)
  2. Alias internos (@/components/*, @modules/*)
  3. Imports relativos (./utils, ../types)

Esto elimina discusiones de estilo y reduce conflictos de merge en los imports.

5. Configuración por repositorio

La configuración varía según el tier del repositorio:

RepositorioTierESLint pluginslint-stagedpre-push
nvito-api1no-only-tests, unused-imports, simple-import-sortESLint + Prettiertsc + tests (--bail)
nvito-admin1no-only-tests, unused-imports, simple-import-sortESLint + Prettiertsc + tests
nvito-invitations1no-only-tests, unused-imports, simple-import-sortESLint + Prettiertsc + tests
nvito-client1no-only-tests, unused-imports, simple-import-sortESLint + Prettiertsc + tests
nvito-pwa1no-only-tests, unused-imports, simple-import-sortESLint + Prettiertsc + tests
nvito-docs2Prettier onlybuild
nvito-landing2Prettier onlybuild

Los repositorios de tier 2 (docs y landing) no tienen tests unitarios significativos ni código TypeScript complejo, por lo que solo verifican formato con Prettier y que el build estático se genere correctamente.

6. Resolución de problemas

"Mi commit fue rechazado por commitlint"

El mensaje no cumple el formato tipo(scope): descripción. Verificar:

  • El tipo es uno de los permitidos: feat, fix, docs, style, refactor, perf, test, build, ci, chore.
  • El scope está entre paréntesis y es válido: api, admin, client, pwa, invitations, docs, landing, deps.
  • La descripción empieza en minúscula y no termina con punto.
  • Hay un espacio después de los dos puntos: feat(api): descripción (correcto) vs feat(api):descripción (incorrecto).

"ESLint encontró errores en pre-commit"

lint-staged ejecuta ESLint con --fix automáticamente, pero algunos errores no son auto-corregibles. Para resolverlos manualmente:

# Ver errores detallados
npx eslint archivo.ts

# Intentar fix automatico
npx eslint --fix archivo.ts

# Si el error persiste, corregirlo manualmente y re-stagear
git add archivo.ts

"secretlint reportó un falso positivo"

Si secretlint detecta un string como potencial secret pero es un falso positivo (por ejemplo, un hash de ejemplo en documentación):

# Opcion 1: agregar al archivo .secretlintignore
echo "ruta/al/archivo.ts" >> .secretlintignore

# Opcion 2: bypass puntual (NO recomendado)
git commit --no-verify -m "tipo(scope): descripcion"

"Pre-push tarda mucho"

Es normal. El hook pre-push ejecuta la suite completa de tests, lo que puede tomar entre 30 segundos y 2 minutos dependiendo del repositorio. Los tiempos aproximados son:

  • nvito-api: ~90s (254+ suites)
  • nvito-admin: ~60s (154+ suites)
  • nvito-client: ~30s (32+ suites)
  • nvito-pwa: ~20s (18+ suites)
  • nvito-invitations: ~15s (17+ suites)

Bypass de emergencia: los flags HUSKY=0 git push y git commit --no-verify deben usarse exclusivamente en emergencias. Omitir las verificaciones compromete la calidad del código y puede introducir regresiones. Todo bypass debe justificarse al equipo.

7. Referencia técnica

Archivos de configuración

ArchivoPropósito
.husky/pre-commitArchivos prohibidos + tamaño + secretlint + lint-staged
.husky/commit-msgValidación con commitlint
.husky/prepare-commit-msgAuto-prefijo desde nombre de branch
.husky/pre-pushBranch protection + tsc + tests
.husky/post-checkoutAviso de npm install si dependencias cambiaron
.husky/post-mergeAviso de npm install si dependencias cambiaron
commitlint.config.jsReglas de Conventional Commits
lint-staged.config.mjsQué linters ejecutar por tipo de archivo
.secretlintrc.jsonReglas de detección de secrets
.prettierrcConfiguración de formato de código
eslint.config.mjsReglas de ESLint + plugins
Esta pagina fue util?