📖 Documentación completa y siempre actualizada: gitlab.wiedii.co/wildcat/wiedii-configs Esta nota es un resumen de referencia rápida. El
README.mddel repo (y las páginas endocs/) 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, sindevelop) - Visibilidad:
internal
Configs disponibles hoy:
lefthook/base.yaml— hooks universales (todos los stacks), incluida la validación/wizard de commits víawietoolefthook/js.yaml— overlay de gestión de paquetes Node (sort-package-json,bun install) para repos JS/TS realeslefthook/terraform.yaml— repos Terraform / Terragrunt (pipeline IaC ordenado)
base.yamles nativo (sin Node): la validación de commits y el wizard sonwietoo— ver wietoo-cli — para todos los stacks. La gestión de paquetes Node vive aparte, en el overlayjs.yaml. Python y Go aún no tienen config de stack propio —base.yamlya cubre lo que comparten. Se añadirá unlefthook/<stack>.yaml(y su página de docs) cuando exista el primer repo de ese stack que lo necesite.
taplo no soporta
extendsni config remota. Las opciones de formato se pasan directamente via--optionen el hooktomldebase.yaml— se aplican en cada commit a todos los repos consumidores sin necesidad de ningún archivo local. El.taplo.tomlpor proyecto es opcional: solo si el proyecto corre taplo fuera del hook (CI directo,taplo fmtmanual). 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.
| Comando | Glob | Qué hace |
|---|---|---|
mise-sync | mise.{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 | *.toml | taplo fmt --option align_entries=true --option indent_entries=true --option reorder_arrays=true --option reorder_keys=true, auto-stagea |
sort-package-json | **/package.json | Ordena las claves del package.json. Avisa y sigue si sort-package-json no está en devDependencies |
hadolint | Dockerfile | Lint de Dockerfiles |
shell | *.sh | Formatea (shfmt --write) y luego lintea (ShellCheck, autofix + gate) — un solo comando; ver abajo |
lefthook-validate | lefthook*.yaml | lefthook validate — atrapa YAML de hooks malformado antes de que se publique |
renovate-validate | renovate.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=truereordena TODOS los arrays TOML — cuidado con losrunordenados. El hooktomlformatea cada.tomlstaged en cada commit y, entre otras cosas, ordena alfabéticamente cualquier array (constage_fixed, re-stagea el cambio). Esto rompe arrays donde el orden importa. El caso típico es[tasks.setup] run = [...]enmise.toml: el ordenmise install --yes → mise lock → bun installse reordena alfabéticamente y en una máquina limpiabun installfalla porquebunaún no está instalado. Solución: para tareas multi-paso ordenadas, escribirruncomo una sola cadena con&&(run = "mise install --yes && mise lock && bun install") — una cadena no es un array, así que taplo no la reordena. Elmise trustva antes (mise trust && mise run setup), nunca dentro delrun. 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
| Hook | Qué hace |
|---|---|
commit-msg | Valida 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
| Comando | Qué hace |
|---|---|
graphify-update | No-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_KEY → ANTHROPIC_API_KEY → OPENAI_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:
| Comando | Glob | Qué 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(otofu— cambiar el binario en el hook),tflint,checkov, yterragrunt(solo si se usa) declarados enmise.toml..tflint.hcly.checkov.yamlen la raíz del git — generados por proyecto con el skill del pluginwiedii-dev.- Plugins de tflint instalados una vez con
tflint --initcomo paso de setup del consumidor. Nunca en el hook —--initbaja 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:
| Paso | Herramienta | Alcance | Notas |
|---|---|---|---|
| 1 | terraform fmt | cada .tf/.tfvars cambiado | Por-archivo: terraform fmt toma un target y evita reformatear archivos no relacionados/generados |
| 2 | terragrunt hcl fmt | recursivo | Se salta si el consumidor no usa Terragrunt (terragrunt ausente de mise.toml). Idempotente |
| 3 | tflint --fix | cada directorio de módulo cambiado | Un 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) |
| 4 | checkov | cada 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 fmtcorre solo siterragruntse resuelve víamise which terragrunt. Un repo solo-TF se salta el paso 2 limpiamente.- El hook requiere que
.tflint.hcly.checkov.yamlexistan (se pasan vía--config/--config-file). Si faltan, las herramientas fallan — generarlos con el skillwiedii-devantes del primer commit. - Para usar OpenTofu en vez de Terraform, cambiar el binario
terraformen 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.gitignoredel repo consumidor — es un artefacto local generado.
Pinnear
ref:a la última release (tag SemVer).wiedii-configsya publica releases (la primera es0.1.0, 2026-07-06), así que elref:debe apuntar al último tag de release, no amain. Ventajas: adopción controlada (un bump de tag es intencional — Renovate + aprobación, no un efecto silencioso de cualquierlefthook install), reproducibilidad (todo el equipo y CI usan la misma versión de hooks) y trazabilidad (lefthook.yamles la fuente de verdad de la versión activa). Los tags de wiedii-configs no llevan prefijov(regla SemVer estándar de Wiedii — no es un módulo Go).ref: mainqueda solo para que un maintainer valide un cambio de hooks en su feature branch antes de promoverlo (ver "Probar en un repo consumidor"); rastrearmainde forma permanente quedó obsoleto. Renovate rastrea el tag víagitlab-tags(ver el briefBRIEF-pin-wiedii-configs-tag.md).
Requisitos en el repo consumidor
Todas las herramientas de sistema deben instalarse vía mise — declaradas en el
mise.tomldel proyecto consumidor. Los hooks usanmise exec -- <herramienta>y fallarán si la herramienta no está en el entorno mise del proyecto.
Herramientas en mise.toml
| Herramienta | Cuá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 |
bun | Siempre — bunx de renovate-validate; más sort-package-json / bun install en repos JS/TS (js.yaml) |
lefthook | Siempre — hook lefthook-validate |
taplo | Siempre — hook toml (formato de archivos .toml) |
checkov | Siempre — hook checkov-secrets (escaneo de secretos en archivos staged) |
hadolint | Si el repo tiene Dockerfile |
shfmt | Si el repo tiene scripts .sh |
shellcheck | Si el repo tiene scripts .sh |
terraform (o tofu), tflint | Si 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 |
terragrunt | Solo 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:
| Paquete | Detalle |
|---|---|
sort-package-json | El 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 dejs.yamldetectan dinámicamente la ubicación delpackage.jsonconfind . -maxdepth 2(excluyendonode_modules/) y toman el resultado más superficial. Si un proyecto tiene dospackage.json(por ejemplo en raíz y ensrc/), se usará siempre el de raíz.
ℹ️ Wizard de commits (
wietoo commit): igual que el antiguoprepare-commit-msgde 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 hookcommit-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áginadocs/<config>.mden 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].postinstallenmise.toml)- Al hacer
post-merge/post-checkoutsi 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.0 → ref: <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:
docs/base.md— todos los hooks debase.yamldocs/terraform.md— el pipelinefmt → tflint → checkov
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 —
.gitattributesy.gitignoreestándar para repos Wiedii - git-flow — flujo de trabajo Git de Wiedii (este repo usa la variante de rama única)