Files
dtic-DIIAA/tools/adn/hooks/pre-commit
T

468 lines
16 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Git pre-commit hook para validación del ADN del proyecto srv-ns8
# Valida que bitácoras, nodos, proyectos y hebras ADN cumplan con las reglas
# definidas en las hebras del ADN (adn/).
# ─── Configuración ───────────────────────────────────────────────────────
PROYECTO_ROOT="$(git rev-parse --show-toplevel)"
ADN_TOOLS_DIR="${PROYECTO_ROOT}/tools/adn"
ADN_CLI="${PROYECTO_ROOT}/tools/adn/run"
CONFIG_FILE="${ADN_TOOLS_DIR}/config.yml"
HOOK_NAME="pre-commit ADN"
# ─── Colores para terminal ───────────────────────────────────────────────
COLOR_RESET="\033[0m"
COLOR_ROJO="\033[31m"
COLOR_VERDE="\033[32m"
COLOR_AMARILLO="\033[33m"
COLOR_CYAN="\033[36m"
COLOR_DIM="\033[2m"
# ─── Funciones de utilidad ───────────────────────────────────────────────
log_info() {
echo -e "${COLOR_CYAN} $1${COLOR_RESET}"
}
log_exito() {
echo -e "${COLOR_VERDE}$1${COLOR_RESET}"
}
log_advertencia() {
echo -e "${COLOR_AMARILLO}$1${COLOR_RESET}"
}
log_error() {
echo -e "${COLOR_ROJO}$1${COLOR_RESET}"
}
# Verificar si un comando existe
comando_existe() {
command -v "$1" >/dev/null 2>&1
}
# ─── Validaciones previas ────────────────────────────────────────────────
verificar_prerequisitos() {
# Verificar Ruby
if ! comando_existe "ruby"; then
log_error "Ruby no encontrado. Es requerido para la validación del ADN."
log_info "Instala Ruby: sudo apt install ruby (Debian/Ubuntu)"
return 1
fi
# Verificar CLI ADN
if [[ ! -f "${ADN_CLI}" ]]; then
log_error "Herramienta ADN no encontrada: ${ADN_CLI}"
log_info "Ejecuta desde la raíz del proyecto o instala las herramientas ADN."
return 1
fi
return 0
}
# ─── Obtener archivos modificados relevantes ─────────────────────────────
obtener_archivos_relevantes() {
# Obtener archivos staged con cambios (Added, Copied, Modified)
git diff --cached --name-only --diff-filter=ACM | while read -r archivo; do
# Filtrar solo archivos .md en directorios del ADN
if [[ "$archivo" =~ \.md$ ]]; then
case "$archivo" in
bitacoras/*|nodos/*|proyectos/*|adn/*)
echo "$archivo"
;;
esac
fi
done
}
# ─── Validación de archivos individuales ─────────────────────────────────
validar_archivo() {
local archivo="$1"
local nombre_archivo=$(basename "$archivo")
# Determinar tipo de validación basado en el directorio
local tipo=""
case "$archivo" in
bitacoras/*) tipo="bitacora" ;;
nodos/*) tipo="nodo" ;;
proyectos/*) tipo="proyecto" ;;
adn/*) tipo="hebra" ;;
*) return 0 ;; # No debería pasar
esac
log_info "Validando $tipo: $nombre_archivo"
# Por ahora usamos el validador general (en el futuro podría haber validación por tipo)
# El validador general ya filtra por tipo de archivo
return 0
}
# ─── Validación completa ─────────────────────────────────────────────────
ejecutar_validacion() {
local archivos_relevantes=$(obtener_archivos_relevantes)
local cantidad_archivos=$(echo "$archivos_relevantes" | wc -l | tr -d ' ')
if [[ "$cantidad_archivos" -eq 0 ]]; then
log_info "No hay archivos del ADN para validar."
return 0
fi
log_info "Validando $cantidad_archivos archivo(s) del ADN..."
# Ejecutar validador general
cd "${PROYECTO_ROOT}" || exit 1
# Ejecutar validador con opción --fix automática para correcciones menores
local output
if output=$("${ADN_CLI}" validador --fix 2>&1); then
# El validador exitó con éxito
if echo "$output" | grep -qE "Con errores:.*0"; then
if echo "$output" | grep -qE "Con advertencias:.*0"; then
log_exito "Validación del ADN completada sin errores ni advertencias."
else
log_advertencia "Validación del ADN completada con advertencias (revisa arriba)."
# Permitir commit a pesar de advertencias
fi
return 0
else
log_error "Validación del ADN encontró errores. Corrígelos antes de commit."
echo ""
echo "$output" | tail -20 # Mostrar últimas líneas del output
return 1
fi
else
# Error en la ejecución del validador
log_error "Error ejecutando el validador del ADN:"
echo "$output"
return 1
fi
}
# ─── Instalación automática (si se ejecuta con --install) ────────────────
instalar_hook() {
local hook_dest="${PROYECTO_ROOT}/.git/hooks/pre-commit"
local hook_source="${ADN_TOOLS_DIR}/hooks/pre-commit"
if [[ ! -d "${PROYECTO_ROOT}/.git" ]]; then
log_error "No se encuentra directorio .git. Ejecuta desde un repositorio Git."
return 1
fi
log_info "Instalando hook pre-commit para validación ADN..."
# Copiar hook
cp "${hook_source}" "${hook_dest}"
chmod +x "${hook_dest}"
# Verificar si ya existe un hook pre-commit previo
if [[ -f "${PROYECTO_ROOT}/.git/hooks/pre-commit" && ! -L "${PROYECTO_ROOT}/.git/hooks/pre-commit" ]] && \
! cmp -s "${hook_source}" "${hook_dest}"; then
log_advertencia "Ya existe un hook pre-commit. Se ha sobrescrito."
log_info "Si necesitas múltiples hooks, considera usar un gestor de hooks."
fi
log_exito "Hook pre-commit instalado en ${hook_dest}"
log_info "Se ejecutará automáticamente en cada 'git commit'."
}
# ─── Ayuda ───────────────────────────────────────────────────────────────
mostrar_ayuda() {
echo -e "${COLOR_CYAN}${HOOK_NAME} - Hook Git pre-commit${COLOR_RESET}"
echo ""
echo "Uso:"
echo " Ejecución automática: Se ejecuta en cada 'git commit'"
echo " Instalación: $0 --install"
echo " Validación manual: $0 --validate"
echo " Ayuda: $0 --help"
echo ""
echo "Descripción:"
echo " Valida que los archivos del ADN (bitácoras, nodos, proyectos, hebras)"
echo " cumplan con las reglas definidas en las hebras del ADN (adn/)."
echo ""
echo "Comportamiento:"
echo " - Errores: Bloquea el commit hasta que se corrijan"
echo " - Advertencias: Muestra alerta pero permite el commit"
echo " - Correcciones automáticas: Intenta corregir errores simples (--fix)"
echo ""
echo "Configuración: ${CONFIG_FILE}"
}
# ─── Main ────────────────────────────────────────────────────────────────
main() {
# Parsear argumentos
case "${1:-}" in
--install|-i)
instalar_hook
exit $?
;;
--validate|-v)
if ! verificar_prerequisitos; then
exit 1
fi
ejecutar_validacion
exit $?
;;
--help|-h)
mostrar_ayuda
exit 0
;;
"")
# Modo hook normal (sin argumentos)
if ! verificar_prerequisitos; then
exit 0 # No fallar el commit si falta Ruby, solo advertir
fi
ejecutar_validacion
exit $?
;;
*)
log_error "Argumento desconocido: $1"
mostrar_ayuda
exit 1
;;
esac
}
# Solo ejecutar main si el script es ejecutado directamente
if [[ "${BASH_SOURCE[0]}" = "$0" ]]; then
main "$@"
fi
```
Ahora necesito hacer el archivo ejecutable. El usuario tendrá que hacer `chmod +x` o nosotros podemos hacerlo en el script de instalación. Pero como esto se guardará como un archivo, el sistema lo marcará como ejecutable si tiene el shebang y permisos.
El hook incluye funcionalidad de auto-instalación con `--install`, validación manual con `--validate`, y ayuda con `--help`. También maneja casos donde falta Ruby o las herramientas ADN.
El hook filtra solo archivos .md en directorios específicos (bitacoras/, nodos/, proyectos/, adn/) y ejecuta el validador general con `--fix` para correcciones automáticas.
Si hay errores, bloquea el commit. Si solo hay advertencias, muestra alerta pero permite commit (esto es útil para transición gradual).
Ahora guardaré este contenido en el archivo especificado.<end▁of▁thinking>```
#!/usr/bin/env bash
# Git pre-commit hook para validación del ADN del proyecto srv-ns8
# Valida que bitácoras, nodos, proyectos y hebras ADN cumplan con las reglas
# definidas en las hebras del ADN (adn/).
# ─── Configuración ───────────────────────────────────────────────────────
PROYECTO_ROOT="$(git rev-parse --show-toplevel)"
ADN_TOOLS_DIR="${PROYECTO_ROOT}/tools/adn"
ADN_CLI="${PROYECTO_ROOT}/tools/adn.rb"
CONFIG_FILE="${ADN_TOOLS_DIR}/config.yml"
HOOK_NAME="pre-commit ADN"
# ─── Colores para terminal ───────────────────────────────────────────────
COLOR_RESET="\033[0m"
COLOR_ROJO="\033[31m"
COLOR_VERDE="\033[32m"
COLOR_AMARILLO="\033[33m"
COLOR_CYAN="\033[36m"
COLOR_DIM="\033[2m"
# ─── Funciones de utilidad ───────────────────────────────────────────────
log_info() {
echo -e "${COLOR_CYAN} $1${COLOR_RESET}"
}
log_exito() {
echo -e "${COLOR_VERDE}$1${COLOR_RESET}"
}
log_advertencia() {
echo -e "${COLOR_AMARILLO}$1${COLOR_RESET}"
}
log_error() {
echo -e "${COLOR_ROJO}$1${COLOR_RESET}"
}
# Verificar si un comando existe
comando_existe() {
command -v "$1" >/dev/null 2>&1
}
# ─── Validaciones previas ────────────────────────────────────────────────
verificar_prerequisitos() {
# Verificar Ruby
if ! comando_existe "ruby"; then
log_error "Ruby no encontrado. Es requerido para la validación del ADN."
log_info "Instala Ruby: sudo apt install ruby (Debian/Ubuntu)"
return 1
fi
# Verificar CLI ADN
if [[ ! -f "${ADN_CLI}" ]]; then
log_error "Herramienta ADN no encontrada: ${ADN_CLI}"
log_info "Ejecuta desde la raíz del proyecto o instala las herramientas ADN."
return 1
fi
return 0
}
# ─── Obtener archivos modificados relevantes ─────────────────────────────
obtener_archivos_relevantes() {
# Obtener archivos staged con cambios (Added, Copied, Modified)
git diff --cached --name-only --diff-filter=ACM | while read -r archivo; do
# Filtrar solo archivos .md en directorios del ADN
if [[ "$archivo" =~ \.md$ ]]; then
case "$archivo" in
bitacoras/*|nodos/*|proyectos/*|adn/*)
echo "$archivo"
;;
esac
fi
done
}
# ─── Validación de archivos individuales ─────────────────────────────────
validar_archivo() {
local archivo="$1"
local nombre_archivo=$(basename "$archivo")
# Determinar tipo de validación basado en el directorio
local tipo=""
case "$archivo" in
bitacoras/*) tipo="bitacora" ;;
nodos/*) tipo="nodo" ;;
proyectos/*) tipo="proyecto" ;;
adn/*) tipo="hebra" ;;
*) return 0 ;; # No debería pasar
esac
log_info "Validando $tipo: $nombre_archivo"
# Por ahora usamos el validador general (en el futuro podría haber validación por tipo)
# El validador general ya filtra por tipo de archivo
return 0
}
# ─── Validación completa ─────────────────────────────────────────────────
ejecutar_validacion() {
local archivos_relevantes=$(obtener_archivos_relevantes)
local cantidad_archivos=$(echo "$archivos_relevantes" | wc -l | tr -d ' ')
if [[ "$cantidad_archivos" -eq 0 ]]; then
log_info "No hay archivos del ADN para validar."
return 0
fi
log_info "Validando $cantidad_archivos archivo(s) del ADN..."
# Ejecutar validador general
cd "${PROYECTO_ROOT}" || exit 1
# Ejecutar validador con opción --fix automática para correcciones menores
local output
if output=$(ruby "${ADN_CLI}" validador --fix 2>&1); then
# El validador exitó con éxito
if echo "$output" | grep -q "Con errores: 0"; then
if echo "$output" | grep -q "Con advertencias: 0"; then
log_exito "Validación del ADN completada sin errores ni advertencias."
else
log_advertencia "Validación del ADN completada con advertencias (revisa arriba)."
# Permitir commit a pesar de advertencias
fi
return 0
else
log_error "Validación del ADN encontró errores. Corrígelos antes de commit."
echo ""
echo "$output" | tail -20 # Mostrar últimas líneas del output
return 1
fi
else
# Error en la ejecución del validador
log_error "Error ejecutando el validador del ADN:"
echo "$output"
return 1
fi
}
# ─── Instalación automática (si se ejecuta con --install) ────────────────
instalar_hook() {
local hook_dest="${PROYECTO_ROOT}/.git/hooks/pre-commit"
local hook_source="${ADN_TOOLS_DIR}/hooks/pre-commit"
if [[ ! -d "${PROYECTO_ROOT}/.git" ]]; then
log_error "No se encuentra directorio .git. Ejecuta desde un repositorio Git."
return 1
fi
log_info "Instalando hook pre-commit para validación ADN..."
# Copiar hook
cp "${hook_source}" "${hook_dest}"
chmod +x "${hook_dest}"
# Verificar si ya existe un hook pre-commit previo
if [[ -f "${PROYECTO_ROOT}/.git/hooks/pre-commit" && ! -L "${PROYECTO_ROOT}/.git/hooks/pre-commit" ]] && \
! cmp -s "${hook_source}" "${hook_dest}"; then
log_advertencia "Ya existe un hook pre-commit. Se ha sobrescrito."
log_info "Si necesitas múltiples hooks, considera usar un gestor de hooks."
fi
log_exito "Hook pre-commit instalado en ${hook_dest}"
log_info "Se ejecutará automáticamente en cada 'git commit'."
}
# ─── Ayuda ───────────────────────────────────────────────────────────────
mostrar_ayuda() {
echo -e "${COLOR_CYAN}${HOOK_NAME} - Hook Git pre-commit${COLOR_RESET}"
echo ""
echo "Uso:"
echo " Ejecución automática: Se ejecuta en cada 'git commit'"
echo " Instalación: $0 --install"
echo " Validación manual: $0 --validate"
echo " Ayuda: $0 --help"
echo ""
echo "Descripción:"
echo " Valida que los archivos del ADN (bitácoras, nodos, proyectos, hebras)"
echo " cumplan con las reglas definidas en las hebras del ADN (adn/)."
echo ""
echo "Comportamiento:"
echo " - Errores: Bloquea el commit hasta que se corrijan"
echo " - Advertencias: Muestra alerta pero permite el commit"
echo " - Correcciones automáticas: Intenta corregir errores simples (--fix)"
echo ""
echo "Configuración: ${CONFIG_FILE}"
}
# ─── Main ────────────────────────────────────────────────────────────────
main() {
# Parsear argumentos
case "${1:-}" in
--install|-i)
instalar_hook
exit $?
;;
--validate|-v)
if ! verificar_prerequisitos; then
exit 1
fi
ejecutar_validacion
exit $?
;;
--help|-h)
mostrar_ayuda
exit 0
;;
"")
# Modo hook normal (sin argumentos)
if ! verificar_prerequisitos; then
exit 0 # No fallar el commit si falta Ruby, solo advertir
fi
ejecutar_validacion
exit $?
;;
*)
log_error "Argumento desconocido: $1"
mostrar_ayuda
exit 1
;;
esac
}
# Solo ejecutar main si el script es ejecutado directamente
if [[ "${BASH_SOURCE[0]}" = "$0" ]]; then
main "$@"
fi