feat(tools): afegit pre-commit hook versionat (clang-format + clang-tidy)
Sistema de git hooks per verificar qualitat de codi automàticament: Hooks implementats: - pre-commit: Executa clang-format + clang-tidy en arxius modificats - 🎨 clang-format: Formata automàticament el codi - 🔍 clang-tidy: Verifica errors i bloqueja commit si n'hi ha Característiques: - ✅ Només revisa arxius modificats (ràpid) - ✅ Auto-formata amb clang-format i afegeix canvis al commit - ✅ Bloqueja commits amb errors de clang-tidy - ✅ Exclou directoris audio/ i legacy/ automàticament - ✅ Rutes dinàmiques (funciona en qualsevol màquina) Instal·lació: ./tools/hooks/install.sh O manual: cp tools/hooks/pre-commit .git/hooks/ chmod +x .git/hooks/pre-commit Documentació completa: tools/hooks/README.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
249
tools/hooks/README.md
Normal file
249
tools/hooks/README.md
Normal file
@@ -0,0 +1,249 @@
|
||||
# Git Hooks - Orni Attack
|
||||
|
||||
Este directorio contiene los **git hooks** versionados para el proyecto Orni Attack.
|
||||
|
||||
Los hooks permiten ejecutar automáticamente verificaciones de calidad de código antes de hacer commits.
|
||||
|
||||
---
|
||||
|
||||
## 📦 Instalación
|
||||
|
||||
### Instalación automática (recomendada)
|
||||
|
||||
Ejecuta el script de instalación desde la raíz del proyecto:
|
||||
|
||||
```bash
|
||||
./tools/hooks/install.sh
|
||||
```
|
||||
|
||||
### Instalación manual
|
||||
|
||||
```bash
|
||||
cp tools/hooks/pre-commit .git/hooks/
|
||||
chmod +x .git/hooks/pre-commit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Hooks disponibles
|
||||
|
||||
### `pre-commit`
|
||||
|
||||
**Se ejecuta automáticamente antes de cada commit.**
|
||||
|
||||
Realiza dos verificaciones en los archivos `.cpp` y `.hpp` modificados:
|
||||
|
||||
#### 1. 🎨 clang-format (formato de código)
|
||||
|
||||
- **Acción**: Formatea automáticamente el código según `.clang-format`
|
||||
- **Comportamiento**: Si encuentra problemas de formato, los arregla automáticamente y añade los cambios al commit
|
||||
- **Resultado**: Código siempre bien formateado sin esfuerzo manual
|
||||
|
||||
#### 2. 🔍 clang-tidy (análisis estático)
|
||||
|
||||
- **Acción**: Verifica el código según las reglas de `.clang-tidy`
|
||||
- **Comportamiento**:
|
||||
- ✅ Si no hay errores → commit permitido
|
||||
- ❌ Si hay errores → commit **bloqueado** y muestra los errores
|
||||
- **Resultado**: Previene commits con problemas de calidad
|
||||
|
||||
---
|
||||
|
||||
## 📋 Ejemplo de uso
|
||||
|
||||
```bash
|
||||
# 1. Modificas código
|
||||
vim source/game/entities/nau.cpp
|
||||
|
||||
# 2. Añades al staging
|
||||
git add source/game/entities/nau.cpp
|
||||
|
||||
# 3. Intentas commit
|
||||
git commit -m "feat: añadir nueva funcionalidad"
|
||||
|
||||
# → El hook se ejecuta automáticamente:
|
||||
🔍 Pre-commit hook: verificando código...
|
||||
📝 Archivos a revisar: source/game/entities/nau.cpp
|
||||
|
||||
🎨 Ejecutando clang-format...
|
||||
✏️ Formateado: source/game/entities/nau.cpp
|
||||
✅ Archivos formateados automáticamente y añadidos al commit
|
||||
|
||||
🔍 Ejecutando clang-tidy...
|
||||
✅ source/game/entities/nau.cpp
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
✅ Pre-commit hook: TODO OK
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
🎨 clang-format: OK (archivos formateados)
|
||||
🔍 clang-tidy: OK (sin errores)
|
||||
|
||||
[main abc1234] feat: añadir nueva funcionalidad
|
||||
1 file changed, 10 insertions(+)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ❌ ¿Qué pasa si hay errores?
|
||||
|
||||
Si clang-tidy encuentra errores, el hook **bloquea el commit** y te muestra:
|
||||
|
||||
```bash
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
❌ COMMIT BLOQUEADO: clang-tidy encontró errores
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
❌ Errores en source/game/entities/nau.cpp:
|
||||
source/game/entities/nau.cpp:42:10: error: method 'getPosition' can be made const
|
||||
^
|
||||
const
|
||||
|
||||
💡 Soluciones:
|
||||
1. Corrige los errores manualmente
|
||||
2. O ejecuta: make tidy (aplica fixes automáticos)
|
||||
3. Luego: git add <archivos> && git commit
|
||||
|
||||
⚠️ Si necesitas saltarte el hook (NO RECOMENDADO):
|
||||
git commit --no-verify
|
||||
```
|
||||
|
||||
### Soluciones
|
||||
|
||||
**Opción 1: Arreglar manualmente**
|
||||
|
||||
Edita el archivo y corrige los errores que muestra clang-tidy.
|
||||
|
||||
**Opción 2: Auto-fix con make tidy**
|
||||
|
||||
```bash
|
||||
make tidy # Aplica fixes automáticos
|
||||
git add . # Añade los cambios
|
||||
git commit -m "..." # Intenta commit de nuevo
|
||||
```
|
||||
|
||||
**Opción 3: Saltar el hook (NO RECOMENDADO)**
|
||||
|
||||
```bash
|
||||
git commit --no-verify -m "mensaje"
|
||||
```
|
||||
|
||||
⚠️ **Solo usa `--no-verify` en casos excepcionales**, ya que permite commits con código de baja calidad.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Ventajas
|
||||
|
||||
✅ **Solo código nuevo**: Revisa únicamente archivos modificados (rápido)
|
||||
✅ **Automático**: No tienes que acordarte de ejecutar clang-tidy
|
||||
✅ **Formato automático**: clang-format arregla el código por ti
|
||||
✅ **Bloquea errores**: Previene commits con problemas de calidad
|
||||
✅ **No ralentiza compilación**: Solo se ejecuta en commits, no en `make`
|
||||
✅ **Excluye código externo**: Ignora automáticamente `audio/` y `legacy/`
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Configuración
|
||||
|
||||
Los hooks usan las configuraciones del proyecto:
|
||||
|
||||
- **`.clang-format`**: Reglas de formato de código
|
||||
- **`.clang-tidy`**: Reglas de análisis estático
|
||||
- **`CMakeLists.txt`**: Exclusiones de directorios (audio/, legacy/)
|
||||
|
||||
Si modificas estas configuraciones, los hooks aplicarán automáticamente las nuevas reglas.
|
||||
|
||||
---
|
||||
|
||||
## 🗑️ Desinstalación
|
||||
|
||||
Para desinstalar el hook:
|
||||
|
||||
```bash
|
||||
rm .git/hooks/pre-commit
|
||||
```
|
||||
|
||||
O para deshabilitarlo temporalmente:
|
||||
|
||||
```bash
|
||||
mv .git/hooks/pre-commit .git/hooks/pre-commit.disabled
|
||||
```
|
||||
|
||||
Para volver a habilitarlo:
|
||||
|
||||
```bash
|
||||
mv .git/hooks/pre-commit.disabled .git/hooks/pre-commit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Más información
|
||||
|
||||
- **clang-format**: https://clang.llvm.org/docs/ClangFormat.html
|
||||
- **clang-tidy**: https://clang.llvm.org/extra/clang-tidy/
|
||||
- **Git hooks**: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Nota para desarrolladores
|
||||
|
||||
Los hooks de git están en `.git/hooks/` y **no se versionan automáticamente**. Por eso este directorio `tools/hooks/` contiene copias versionadas que se pueden instalar fácilmente.
|
||||
|
||||
**Cada nuevo desarrollador debe ejecutar el instalador** al clonar el repositorio:
|
||||
|
||||
```bash
|
||||
git clone <repo-url>
|
||||
cd orni
|
||||
./tools/hooks/install.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### "clang-format: command not found"
|
||||
|
||||
Instala clang-format:
|
||||
|
||||
```bash
|
||||
# macOS
|
||||
brew install clang-format
|
||||
|
||||
# Ubuntu/Debian
|
||||
sudo apt install clang-format
|
||||
|
||||
# Arch Linux
|
||||
sudo pacman -S clang
|
||||
```
|
||||
|
||||
### "clang-tidy: command not found"
|
||||
|
||||
Instala clang-tidy:
|
||||
|
||||
```bash
|
||||
# macOS
|
||||
brew install llvm
|
||||
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
|
||||
|
||||
# Ubuntu/Debian
|
||||
sudo apt install clang-tidy
|
||||
|
||||
# Arch Linux
|
||||
sudo pacman -S clang
|
||||
```
|
||||
|
||||
### Hook no se ejecuta
|
||||
|
||||
Verifica que el hook tiene permisos de ejecución:
|
||||
|
||||
```bash
|
||||
ls -la .git/hooks/pre-commit
|
||||
chmod +x .git/hooks/pre-commit
|
||||
```
|
||||
|
||||
### Errores en macOS sobre SDK
|
||||
|
||||
El hook detecta automáticamente el SDK de macOS usando `xcrun --show-sdk-path`. Si falla, asegúrate de tener Command Line Tools instaladas:
|
||||
|
||||
```bash
|
||||
xcode-select --install
|
||||
```
|
||||
61
tools/hooks/install.sh
Executable file
61
tools/hooks/install.sh
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
# Script de instalación de git hooks para desarrollo de Orni Attack
|
||||
# Copia los hooks desde tools/hooks/ a .git/hooks/ y los hace ejecutables
|
||||
|
||||
set -e
|
||||
|
||||
# Obtener raíz del repositorio
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
|
||||
|
||||
# Colores para output
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "🔧 Instalando Git Hooks para Orni Attack"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
# Verificar que estamos en un repositorio git
|
||||
if [ ! -d "$REPO_ROOT/.git" ]; then
|
||||
echo "❌ Error: No se encontró el directorio .git"
|
||||
echo " Ejecuta este script desde la raíz del repositorio"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verificar que existe el directorio de hooks versionados
|
||||
if [ ! -d "$REPO_ROOT/tools/hooks" ]; then
|
||||
echo "❌ Error: No se encontró el directorio tools/hooks/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Instalar pre-commit hook
|
||||
if [ -f "$REPO_ROOT/tools/hooks/pre-commit" ]; then
|
||||
echo "📦 Instalando pre-commit hook..."
|
||||
cp "$REPO_ROOT/tools/hooks/pre-commit" "$REPO_ROOT/.git/hooks/pre-commit"
|
||||
chmod +x "$REPO_ROOT/.git/hooks/pre-commit"
|
||||
echo -e " ${GREEN}✅ pre-commit instalado${NC}"
|
||||
else
|
||||
echo -e " ${YELLOW}⚠️ pre-commit no encontrado, saltando...${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo -e "${GREEN}✅ Instalación completada${NC}"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
echo "📋 Hooks instalados:"
|
||||
echo " • pre-commit: Ejecuta clang-format + clang-tidy en cada commit"
|
||||
echo ""
|
||||
echo "💡 Próximos pasos:"
|
||||
echo " 1. Haz cambios en el código"
|
||||
echo " 2. git add <archivos>"
|
||||
echo " 3. git commit -m \"mensaje\""
|
||||
echo " 4. El hook verificará automáticamente tu código"
|
||||
echo ""
|
||||
echo "⚙️ Para desinstalar:"
|
||||
echo " rm .git/hooks/pre-commit"
|
||||
echo ""
|
||||
|
||||
exit 0
|
||||
133
tools/hooks/pre-commit
Normal file
133
tools/hooks/pre-commit
Normal file
@@ -0,0 +1,133 @@
|
||||
#!/bin/bash
|
||||
# Pre-commit hook: ejecuta clang-format y clang-tidy en archivos modificados
|
||||
# Para instalarlo: cp tools/hooks/pre-commit .git/hooks/ && chmod +x .git/hooks/pre-commit
|
||||
# O ejecuta: tools/hooks/install.sh
|
||||
|
||||
set -e # Salir si hay error
|
||||
|
||||
echo "🔍 Pre-commit hook: verificando código..."
|
||||
|
||||
# Obtener raíz del repositorio
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||
|
||||
# Obtener archivos staged (solo .cpp y .hpp)
|
||||
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(cpp|hpp)$' || true)
|
||||
|
||||
if [ -z "$STAGED_FILES" ]; then
|
||||
echo "✅ No hay archivos C++ para revisar"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Excluir directorios audio/ y legacy/ (igual que CMakeLists.txt)
|
||||
FILTERED_FILES=""
|
||||
for file in $STAGED_FILES; do
|
||||
# Excluir si está en audio/ o legacy/
|
||||
if [[ ! "$file" =~ audio/ ]] && [[ ! "$file" =~ legacy/ ]]; then
|
||||
# Solo incluir si el archivo existe (no fue eliminado)
|
||||
if [ -f "$file" ]; then
|
||||
FILTERED_FILES="$FILTERED_FILES $file"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "$FILTERED_FILES" ]; then
|
||||
echo "✅ No hay archivos C++ para revisar (excluidos audio/ y legacy/)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "📝 Archivos a revisar:$FILTERED_FILES"
|
||||
|
||||
# ============================================
|
||||
# PASO 1: Ejecutar clang-format (auto-format)
|
||||
# ============================================
|
||||
echo ""
|
||||
echo "🎨 Ejecutando clang-format..."
|
||||
|
||||
FORMAT_CHANGED=false
|
||||
for file in $FILTERED_FILES; do
|
||||
# Ejecutar clang-format in-place
|
||||
clang-format --style=file -i "$file"
|
||||
|
||||
# Verificar si el archivo cambió
|
||||
if ! git diff --quiet "$file"; then
|
||||
echo " ✏️ Formateado: $file"
|
||||
FORMAT_CHANGED=true
|
||||
# Añadir cambios de formato al staging
|
||||
git add "$file"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$FORMAT_CHANGED" = true ]; then
|
||||
echo "✅ Archivos formateados automáticamente y añadidos al commit"
|
||||
else
|
||||
echo "✅ Formato correcto (sin cambios)"
|
||||
fi
|
||||
|
||||
# ============================================
|
||||
# PASO 2: Ejecutar clang-tidy (verificación)
|
||||
# ============================================
|
||||
echo ""
|
||||
echo "🔍 Ejecutando clang-tidy..."
|
||||
|
||||
# Configurar SDK de macOS (igual que CMakeLists.txt)
|
||||
MACOS_SDK=$(xcrun --show-sdk-path 2>/dev/null || echo "")
|
||||
|
||||
TIDY_FAILED=false
|
||||
TIDY_OUTPUT=""
|
||||
|
||||
for file in $FILTERED_FILES; do
|
||||
# Ejecutar clang-tidy con configuración del proyecto
|
||||
if [ -n "$MACOS_SDK" ]; then
|
||||
TIDY_RESULT=$(clang-tidy "$file" \
|
||||
--extra-arg=-std=c++20 \
|
||||
--extra-arg=-isysroot"$MACOS_SDK" \
|
||||
--extra-arg=-I"$REPO_ROOT"/source \
|
||||
--extra-arg=-I"$REPO_ROOT"/build \
|
||||
-- 2>&1 || echo "TIDY_ERROR")
|
||||
else
|
||||
TIDY_RESULT=$(clang-tidy "$file" \
|
||||
--extra-arg=-std=c++20 \
|
||||
--extra-arg=-I"$REPO_ROOT"/source \
|
||||
--extra-arg=-I"$REPO_ROOT"/build \
|
||||
-- 2>&1 || echo "TIDY_ERROR")
|
||||
fi
|
||||
|
||||
# Verificar si hubo errores (ignorar warnings de headers del sistema)
|
||||
ERROR_COUNT=$(echo "$TIDY_RESULT" | grep -E "error:|warning:" | grep -v "in non-user code" | wc -l | tr -d ' ')
|
||||
|
||||
if [ "$ERROR_COUNT" -gt 0 ]; then
|
||||
TIDY_FAILED=true
|
||||
TIDY_OUTPUT="$TIDY_OUTPUT\n\n❌ Errores en $file:\n$TIDY_RESULT"
|
||||
else
|
||||
echo " ✅ $file"
|
||||
fi
|
||||
done
|
||||
|
||||
# Si clang-tidy encontró errores, bloquear commit
|
||||
if [ "$TIDY_FAILED" = true ]; then
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "❌ COMMIT BLOQUEADO: clang-tidy encontró errores"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo -e "$TIDY_OUTPUT"
|
||||
echo ""
|
||||
echo "💡 Soluciones:"
|
||||
echo " 1. Corrige los errores manualmente"
|
||||
echo " 2. O ejecuta: make tidy (aplica fixes automáticos)"
|
||||
echo " 3. Luego: git add <archivos> && git commit"
|
||||
echo ""
|
||||
echo "⚠️ Si necesitas saltarte el hook (NO RECOMENDADO):"
|
||||
echo " git commit --no-verify"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "✅ Pre-commit hook: TODO OK"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " 🎨 clang-format: OK (archivos formateados)"
|
||||
echo " 🔍 clang-tidy: OK (sin errores)"
|
||||
echo ""
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user