Saltar al contenido principal

📖 Documentación completa y siempre actualizada: gitlab.wiedii.co/wildcat/wiedii-configs Esta nota es un resumen de referencia rápida. El README.md del repo (y las páginas en docs/) son la fuente de verdad.

wiedii-configs — Hooks Compartidos

🎯 Para quién es esta guía. Es para quien mantiene o configura los git hooks compartidos de la empresa. Si tu repositorio ya los tiene configurados (lo normal), no necesitas nada de esto — los hooks corren solos en cada commit. El contenido denso de más abajo (remotes, overlay, glob, stage_fixed, reorder_arrays…) es jerga de mantenimiento; ignórala salvo que vayas a tocar la configuración.

Repositorio centralizado de configuraciones de git hooks para todos los proyectos Wiedii. En lugar de copiar y mantener el mismo YAML de hooks en cada repo, los proyectos consumen este repo vía lefthook remotes. No contiene código ejecutable — son archivos YAML puros.

  • Repo: wildcat/wiedii-configs
  • Rama activa: main (flujo GitHub Flow — rama única, sin develop)
  • Visibilidad: internal

Configs disponibles hoy:

  • lefthook/base.yaml — hooks universales (todos los stacks), incluida la validación/wizard de commits vía wietoo
  • lefthook/js.yaml — overlay de gestión de paquetes Node (sort-package-json, bun install) para repos JS/TS reales
  • lefthook/terraform.yaml — repos Terraform / Terragrunt (pipeline IaC ordenado)

base.yaml es nativo (sin Node): la validación de commits y el wizard son wietoo — ver wietoo-cli — para todos los stacks. La gestión de paquetes Node vive aparte, en el overlay js.yaml. Python y Go aún no tienen config de stack propio — base.yaml ya cubre lo que comparten. Se añadirá un lefthook/<stack>.yaml (y su página de docs) cuando exista el primer repo de ese stack que lo necesite.


taplo no soporta extends ni config remota. Las opciones de formato se pasan directamente via --option en el hook toml de base.yaml — se aplican en cada commit a todos los repos consumidores sin necesidad de ningún archivo local. El .taplo.toml por proyecto es opcional: solo si el proyecto corre taplo fuera del hook (CI directo, taplo fmt manual). Como en Wiedii taplo solo lo invoca lefthook, los repos consumidores no necesitan .taplo.toml. Ver linters para los detalles de la estrategia.


lefthook/base.yaml — todos los stacks

📄 Detalle completo por hook: docs/base.md (EN) · docs/base.es.md (ES).

pre-commit (parallel: true)

Corre mise trust como job inicial; el resto son commands glob-filtrados (con priority para los que no deben competir). Todo formateador usa stage_fixed: true, así que re-stagea automáticamente lo que reescribe.

ComandoGlobQué hace
mise-syncmise.{toml,lock}mise install --yes. Acotado a los archivos mise a propósito — así NO dispara lefthook install (vía el postinstall del consumidor) en cada commit.
toml*.tomltaplo fmt --option align_entries=true --option indent_entries=true --option reorder_arrays=true --option reorder_keys=true, auto-stagea
sort-package-json**/package.jsonOrdena las claves del package.json. Avisa y sigue si sort-package-json no está en devDependencies
hadolintDockerfileLint de Dockerfiles
shell*.shFormatea (shfmt --write) y luego lintea (ShellCheck, autofix + gate) — un solo comando; ver abajo
lefthook-validatelefthook*.yamllefthook validate — atrapa YAML de hooks malformado antes de que se publique
renovate-validaterenovate.json, .renovaterc*renovate-config-validator --strict. Corre desde /tmp para que bunx resuelva el validador y no el binario local del bot renovate cuando hay node_modules
checkov-secrets*checkov --framework secrets sobre los archivos staged — bloquea commits que introduzcan secretos/llaves hardcodeadas. Universal (todo repo, incluso solo-docs); de solo lectura y seguro en paralelo; no necesita .checkov.yaml por repo (el framework secrets está activo por defecto). Es un gate sobre archivos staged, no un escaneo full-tree (eso queda como backstop de CI)

⚠️ reorder_arrays=true reordena TODOS los arrays TOML — cuidado con los run ordenados. El hook toml formatea cada .toml staged en cada commit y, entre otras cosas, ordena alfabéticamente cualquier array (con stage_fixed, re-stagea el cambio). Esto rompe arrays donde el orden importa. El caso típico es [tasks.setup] run = [...] en mise.toml: el orden mise install --yes → mise lock → bun install se reordena alfabéticamente y en una máquina limpia bun install falla porque bun aún no está instalado. Solución: para tareas multi-paso ordenadas, escribir run como una sola cadena con && (run = "mise install --yes && mise lock && bun install") — una cadena no es un array, así que taplo no la reordena. El mise trust va antes (mise trust && mise run setup), nunca dentro del run. Ver mise.

shell es un solo comando a propósito (shfmt + ShellCheck): ambas herramientas autocorrigen y re-staggean los mismos archivos *.sh, y este pre-commit corre parallel: true. Como dos comandos separados competían — sus escrituras concurrentes a un script no conforme se entrelazaban y lo corrompían en disco (priority: solo ordena corridas secuenciales, así que bajo parallel nunca los serializó). Fusionados en un único bloque run corren en orden dentro de un mismo proceso — sin carrera por el archivo compartido — sin dejar de correr en paralelo a los demás comandos (no-.sh). Paso 1: shfmt --write normaliza el formato. Paso 2: ShellCheck aplica solo los arreglos que él mismo propone (mecánicos y seguros — comillas, llaves ${}) vía shellcheck -f diff | git apply; un diff vacío o un parche que no aplica nunca aborta el commit. Paso 3: ShellCheck re-corre como gate, así cualquier hallazgo restante (advisory o no auto-arreglable) sigue bloqueando el commit para revisión humana. Los checks opcionales se habilitan inline con flags -o (add-default-case, deprecate-which, quote-safe-variables, check-extra-masked-returns, check-set-e-suppressed, avoid-nullary-conditions, require-variable-braces) — la config vive en el hook sincronizado, no en un .shellcheckrc por repo. require-double-brackets se omite a propósito — marcaría scripts POSIX sh que usan [ ].

commit-msg

HookQué hace
commit-msgValida el mensaje con wietoo check-commit-msg — nativo, sin Node, superset estricto de Conventional Commits (tipo/scope, emoji obligatorio, header ≤100, sin punto final, líneas de cuerpo ≤100). El footer closed #<N> es advisory (WARN, nunca bloquea). No hay hook prepare-commit-msg: el asistente equivalente es wietoo commit, que se corre a mano (git commit -m … también lo valida este mismo hook). Ver wietoo-cli.

post-commit

ComandoQué hace
graphify-updateNo-op salvo que exista graphify-out/ (grafo inicializado). graphify . --update re-procesa solo los archivos cuyo SHA-256 cambió (típicamente < 5s). Nunca bloquea el commit (`

Detección de backend (en orden de prioridad): claude-cli (Claude Code en PATH) → GEMINI_API_KEYANTHROPIC_API_KEYOPENAI_API_KEY. Si ninguno está disponible imprime un aviso y sale con 0. Manual: graphify . --update --backend <claude-cli|gemini|claude|openai>.

post-merge, post-checkout, post-rewrite

Cada uno corre mise trust + mise install --yes, y luego:

ComandoGlobQué hace
bun-install**/{package.json,bun.lock,bunfig.toml}bun install --frozen-lockfile solo si falta node_modules o cambió un archivo de dependencias entre ORIG_HEAD y HEAD. Mantiene las dependencias sincronizadas tras pulls, cambios de rama y rebases sin reinstalar en cada operación

lefthook/terraform.yaml — Terraform / Terragrunt

📄 Detalle completo: docs/terraform.md (EN) · docs/terraform.es.md (ES).

Pipeline IaC ordenado para pre-commit en repos Terraform / Terragrunt. Se consume además de base.yaml.

Requisitos en el repo consumidor

  • terraform (o tofu — cambiar el binario en el hook), tflint, checkov, y terragrunt (solo si se usa) declarados en mise.toml.
  • .tflint.hcl y .checkov.yaml en la raíz del git — generados por proyecto con el skill del plugin wiedii-dev.
  • Plugins de tflint instalados una vez con tflint --init como paso de setup del consumidor. Nunca en el hook--init baja de GitHub y está rate-limited.

El pipeline — un único comando ordenado

Todo el pipeline es un solo comando pre-commit (glob *.{tf,tfvars,hcl}, stage_fixed: true), no un comando por herramienta. Como base.yaml corre pre-commit con parallel: true y todos los pasos leen/escriben los mismos archivos, como comandos paralelos competirían (checkov leyendo un archivo a mitad de reescritura por tflint --fix). Un solo comando garantiza este orden sin importar el flag parallel heredado:

PasoHerramientaAlcanceNotas
1terraform fmtcada .tf/.tfvars cambiadoPor-archivo: terraform fmt toma un target y evita reformatear archivos no relacionados/generados
2terragrunt hcl fmtrecursivoSe salta si el consumidor no usa Terragrunt (terragrunt ausente de mise.toml). Idempotente
3tflint --fixcada directorio de módulo cambiadoUn run por dir (derivado de las rutas staged vía dirname). Usa --config "$ROOT/.tflint.hcl" ($ROOT = git rev-parse --show-toplevel; ruta absoluta, necesaria porque corre con --chdir "$d" — y {root} no es template de lefthook)
4checkovcada directorio cambiadoÚltimo, para escanear el código ya formateado y --fixeado. Usa --config-file "$ROOT/.checkov.yaml" (misma ruta absoluta)

stage_fixed: true re-stagea lo que reescriban los pasos 1–3. Alcance: tflint y checkov corren por directorio cambiado (derivado de rutas staged vía dirname), así cualquier layout queda cubierto (raíz, deploy/**, modules/**, live/**, …). Los módulos sin cambios no se re-escanean; la validación full-tree es trabajo de CI.

checkov --skip-path — por qué está

El paso de checkov pasa --skip-path '\.terragrunt-cache' --skip-path '\.external_modules' --skip-path '\.terraform'. checkov -d <dir> recursa en todo bajo el directorio, incluyendo las copias efímeras que Terragrunt crea (.terragrunt-cache/, .external_modules/, .terraform/modules/). En un repo Terragrunt con caché tibia, esas copias multiplican cada hallazgo y error de parseo N veces. Diagnóstico real en ci-quality-hub-platform: un escaneo full-tree parseó 27.173 archivos — solo 138 Terraform propio del repo (86% dentro de .terragrunt-cache/), y un solo iam_pipes.tf malformado de un módulo de terceros apareció como 11 "parsing errors" duplicados. La exclusión se aplica centralmente en este hook compartido — no se deja al .checkov.yaml de cada consumidor — para que se sostenga aunque esa config falte o esté incompleta.

Gotchas

  • terragrunt hcl fmt corre solo si terragrunt se resuelve vía mise which terragrunt. Un repo solo-TF se salta el paso 2 limpiamente.
  • El hook requiere que .tflint.hcl y .checkov.yaml existan (se pasan vía --config/--config-file). Si faltan, las herramientas fallan — generarlos con el skill wiedii-dev antes del primer commit.
  • Para usar OpenTofu en vez de Terraform, cambiar el binario terraform en el paso 1 del hook.

Cómo consumir en un nuevo repo

Agregar el bloque remotes al lefthook.yaml del proyecto:

# lefthook.yaml
remotes:
- git_url: git@gitlab.wiedii.co:wildcat/wiedii-configs.git
ref: 0.2.0 # última release de wiedii-configs (ver nota abajo) — no `main`
configs:
- lefthook/base.yaml # obligatorio — todos los stacks
- lefthook/terraform.yaml # solo repos Terraform / Terragrunt

Luego instalar los hooks:

lefthook install # descarga y cachea los configs en .lefthook/

.lefthook/ debe estar en .gitignore del repo consumidor — es un artefacto local generado.

Pinnear ref: a la última release (tag SemVer). wiedii-configs ya publica releases (la primera es 0.1.0, 2026-07-06), así que el ref: debe apuntar al último tag de release, no a main. Ventajas: adopción controlada (un bump de tag es intencional — Renovate + aprobación, no un efecto silencioso de cualquier lefthook install), reproducibilidad (todo el equipo y CI usan la misma versión de hooks) y trazabilidad (lefthook.yaml es la fuente de verdad de la versión activa). Los tags de wiedii-configs no llevan prefijo v (regla SemVer estándar de Wiedii — no es un módulo Go). ref: main queda solo para que un maintainer valide un cambio de hooks en su feature branch antes de promoverlo (ver "Probar en un repo consumidor"); rastrear main de forma permanente quedó obsoleto. Renovate rastrea el tag vía gitlab-tags (ver el brief BRIEF-pin-wiedii-configs-tag.md).


Requisitos en el repo consumidor

Todas las herramientas de sistema deben instalarse vía mise — declaradas en el mise.toml del proyecto consumidor. Los hooks usan mise exec -- <herramienta> y fallarán si la herramienta no está en el entorno mise del proyecto.

Herramientas en mise.toml

HerramientaCuándo es necesaria
wietoo (backend go:)Siempre — validación (commit-msg) y wizard wietoo commit. Ver wietoo-cli para el pin exacto y la config de módulos Go privados
bunSiempre — bunx de renovate-validate; más sort-package-json / bun install en repos JS/TS (js.yaml)
lefthookSiempre — hook lefthook-validate
taploSiempre — hook toml (formato de archivos .toml)
checkovSiempre — hook checkov-secrets (escaneo de secretos en archivos staged)
hadolintSi el repo tiene Dockerfile
shfmtSi el repo tiene scripts .sh
shellcheckSi el repo tiene scripts .sh
terraform (o tofu), tflintSi el repo es Terraform/Terragrunt (lefthook/terraform.yaml). checkov ya es universal (ver arriba); en repos Terraform además corre el escaneo de misconfig en terraform.yaml
terragruntSolo si el repo Terraform usa Terragrunt

Ejemplo mínimo de mise.toml en el repo consumidor:

[tools]
"go:gitlab.wiedii.co/wiedii-registry/wietoo-cli/cmd/wietoo" = "vX.Y.Z"
bun = "1.x.x"
"aqua:evilmartians/lefthook" = "x.x.x"
"aqua:tamasfe/taplo" = "x.x.x"
"pipx:checkov" = "x.x.x"
# hadolint, shfmt, shellcheck — agregar si el repo los necesita
# terraform/tofu, tflint, terragrunt — para repos Terraform/Terragrunt (checkov ya está arriba)

Dependencias en package.json (solo repos JS/TS reales)

base.yaml no necesita ningún paquete npm — el commit tooling es nativo (wietoo). Solo los repos que además consumen el overlay lefthook/js.yaml necesitan una devDependency, gestionada por Renovate:

PaqueteDetalle
sort-package-jsonEl hook lo busca en node_modules/.bin/; avisa y sigue si no está

El hook bun-install de js.yaml solo se activa si los archivos correspondientes (package.json, bun.lock, bunfig.toml) existen y están staged. Ni ese ni sort-package-json son requisito para consumir base.yaml por sí solo.

⚠️ PKG_DIR — detección de package.json: los hooks de js.yaml detectan dinámicamente la ubicación del package.json con find . -maxdepth 2 (excluyendo node_modules/) y toman el resultado más superficial. Si un proyecto tiene dos package.json (por ejemplo en raíz y en src/), se usará siempre el de raíz.

ℹ️ Wizard de commits (wietoo commit): igual que el antiguo prepare-commit-msg de czg, es interactivo y necesita una TTY real, así que se corre a mano — no hay hook que lo dispare solo. git commit -m (agentes, CI) sigue validándose igual por el hook commit-msg. Ver wietoo-cli.


lefthook.yaml mínimo para un repo JS/TS

Los hooks centralizados cubren: validación/wizard de commits (wietoo), formateo TOML, Dockerfile lint, shell lint/format, lefthook validate, renovate validate y escaneo de secretos (checkov) — desde base.yaml — más sort-package-json y bun install desde el overlay js.yaml. El lefthook.yaml local solo necesita los linters específicos del proyecto:

remotes:
- git_url: git@gitlab.wiedii.co:wildcat/wiedii-configs.git
ref: 0.2.0 # última release de wiedii-configs — no `main`
configs:
- lefthook/base.yaml # obligatorio, todos los stacks
- lefthook/js.yaml # este repo es JS/TS real

pre-commit:
parallel: true
jobs:
- run: mise trust
commands:
prettier:
priority: 1
glob: '*.{js,cjs,mjs,ts,json,md,yaml}'
run: mise exec -- bun prettier --write --cache {staged_files}
stage_fixed: true
eslint:
priority: 2
glob: '*.{js,cjs,mjs,ts,json}'
run: mise exec -- bun eslint --config eslint.config.mjs --cache --fix {staged_files}
stage_fixed: true

Los hooks commit-msg (wietoo), post-merge/post-checkout/post-rewrite, sort-package-json/bun-install y los validadores universales ya vienen de base.yaml + js.yaml — no se duplican.


Cómo contribuir / actualizar

Este repo usa GitHub Flow (rama única main, sin develop). Las ramas de feature salen de main y vuelven a main vía Merge Request.

git switch -c hooks/nombre-del-cambio # rama desde main
# hacer cambios en lefthook/*.yaml (y actualizar docs/ si aplica)
mise exec -- lefthook validate # verificar sintaxis
mise exec -- lefthook run pre-commit # probar hooks localmente
wietoo commit # wizard nativo
git push -o merge_request.create -o merge_request.target=main \
-o "merge_request.title=feat(hooks): descripción"

Nunca hacer push directo a main. Abrir siempre un MR. Ver git-flow para el flujo de trabajo Git de Wiedii.

Documentar el cambio: cada config tiene una página en docs/ (una por idioma, EN *.md / ES *.es.md). Al cambiar un hook, actualizar su página docs/<config>.md en el mismo MR, y reflejar aquí los cambios esenciales.

Probar en un repo consumidor antes de mergear

# lefthook.yaml — apuntar temporalmente al feature branch
remotes:
- git_url: git@gitlab.wiedii.co:wildcat/wiedii-configs.git
ref: hooks/nombre-del-cambio
configs:
- lefthook/base.yaml

Revertir el ref: al tag de release pinneado (p. ej. 0.2.0) una vez mergeado — no dejarlo en main.


Actualización automática en repos consumidores

lefthook install descarga la versión del ref: configurado. Ocurre automáticamente en:

  • mise run setup (via [hooks].postinstall en mise.toml)
  • Al hacer post-merge / post-checkout si el repo lo incluye en hooks locales

Con el ref: pinneado a un tag de release, los consumidores adoptan una versión de hooks nueva solo cuando bumpean el tag (intencional, vía Renovate + aprobación) — no de forma silenciosa en cualquier lefthook install. Para mantenerse al día: cambiar ref: 0.2.0ref: <nuevo tag> (Renovate lo propone automáticamente vía gitlab-tags) y correr lefthook install.


Documentación detallada

El repo tiene un árbol docs/ con una página de referencia por config (bilingüe, *.md EN / *.es.md ES) que documenta cada hook: cuándo dispara, qué hace, si auto-arregla y re-stagea, qué debe proveer el repo consumidor y los gotchas conocidos:

La fuente autoritativa siempre es el comentario de cabecera dentro de cada lefthook/*.yaml; estas páginas lo expanden.


Referencias

  • wietoo-cli — guía completa de la validación/wizard de commits que activa base.yaml
  • lefthook — guía completa de lefthook: instalación, integración con mise, troubleshooting
  • commits — política de mensajes de commit que valida el hook commit-msg
  • repo-setup — checklist para configurar un nuevo repositorio (incluye bloque remotes)
  • cross-platform.gitattributes y .gitignore estándar para repos Wiedii
  • git-flow — flujo de trabajo Git de Wiedii (este repo usa la variante de rama única)