Menú de navegaciónMenú
Categorías

La mejor forma de Aprender Programación online y en español www.campusmvp.es

?id=01db8d5c-d0ab-4c22-9960-d8a3c9e2eaf8

3 trucos para automatizar tus tareas de desarrollo con git hooks

El sistema de control de versiones Git, como muchos otros, viene con unos cuantos trucos en la manga que lo hacen muy extensible de forma programática. En este artículo aprenderemos uno de ellos, los hooks, que permiten realizar acciones automáticas junto a muchos de los comandos típicos de Git.

Los hooks son programas que se ejecutan antes o después que algún evento importante de Git. Por ejemplo, antes de completar un git commit, tras cambiar de rama o antes de enviar los cambios durante un git push. Se almacenan en el directorio .git/hooks/ de cada proyecto clonado, y es necesario que sean programas o scripts ejecutables (en sistemas tipo Unix han de tener el permiso de ejecución).

Para añadir un hook a tu proyecto, simplemente copia o enlaza a dicho directorio el programa que quieras ejecutar automáticamente con el nombre del "evento" (por ejemplo, pre-commit, todos los posibles nombres están disponibles en la documentación de Git). Si el programa es un script y quieres que el resto de colaboradores puedan usarlo, es conveniente incluirlo en la raíz del proyecto y crear un acceso directo a él en .git/hooks/:

ln -s ../../pre-commit.sh .git/hooks/pre-commit

Vamos a ver algunas aplicaciones practicas de los hooks de Git.

1. Comprobar la calidad del código antes del commit

Los hooks que se ejecutan previos a la confirmación de un commit son útiles puesto que nos permiten realizar comprobaciones sobre el código añadido o eliminado justo antes de reflejar dichos cambios en el árbol de versiones del repositorio. Si el hook falla o devuelve código de error, el commit no se efectuará.

En el siguiente ejemplo (válido para sistemas Unix, como Linux o macOS), utilizamos el paquete jslint de Node.js para comprobar la calidad del código de una aplicación JavaScript antes de completar el commit:

#!/bin/bash
# pre-commit.sh

# Guardar los cambios no confirmados
STASH_NAME="pre-commit-$(date +%s)"
git stash save -q --keep-index $STASH_NAME

# Comprobaciones y tests
jslint my_application.js || exit 1

# Recuperar los cambios guardados
STASHES=$(git stash list)
if [[ $STASHES == "$STASH_NAME" ]]; then
  git stash pop -q
fi

Se podría proceder con la misma estrategia a lanzar una suite de tests sobre la aplicación u otras comprobaciones necesarias, por ejemplo, una búsqueda de claves o tokens secretos para evitar introducirlos al repositorio.

2. Generar la documentación conforme se suben cambios

Si en nuestro proyecto contamos con un generador de documentación a partir del código, podemos ejecutarlo regularmente conforme desarrollamos mediante un hook de tipo pre-push. Simplemente lanzamos el comando necesario para componer toda la documentación en algún directorio (por ejemplo, docs/) y la añadimos a un nuevo commit.

En el siguiente listado te muestro varios ejemplos de los posibles comandos que podrías usar para tal fin:

#!/bin/bash
# pre-push.sh

# Genera la documentación
doxygen Doxyfile

# Otro ejemplo, con Python:
pydoc3 -w docs/

# Otro ejemplo, con R:
Rscript -e 'pkgdown::build_site()'

# Añade y confirma los cambios relativos a la documentación
git add docs/
git commit -m "Update documentation ($(date +%[email protected]%R))"

La ventaja de esto es que, si utilizas GitHub Pages o un servicio similar para servir tu documentación online, siempre estará al día con los cambios de tu código y no se quedará obsoleta.

3. Comprueba dependencias al cambiar de rama

Por último, una aplicación de los hooks muy interesante es actualizar las dependencias instaladas al cambiar de rama en un proyecto. Si utilizas gestores de paquetes y dependencias para tu lenguaje de desarrollo (Pip en Python, npm en Node.js, Nuget en .NET, Bundler en Ruby, Cargo en Rust...), te puede ser muy útil el siguiente ejemplo.

El listado de código a continuación correspondería a un hook post-checkout, y lo que consigue es comprobar si entre la rama anterior y la nueva ha cambiado el archivo de dependencias (en este caso, Gemfile para Ruby), en cuyo caso ejecuta el instalador conveniente (en este caso, bundle).

#!/bin/bash
# post-checkout.sh

if [ $1 = 0000000000000000000000000000000000000000 ]; then
  # Si estamos en un proyecto recién clonado, comparar con el directorio vacío
  old=$(git hash-object -t tree /dev/null)
else
  # El primer argumento es el hash de la anterior HEAD
  old=$1
fi
if [ -f Gemfile ] &&
  git diff --name-only $old $2 | egrep -q '^Gemfile|\.gemspec$'
then
  # Vaciar $GIT_DIR evita problemas si bundle llama a git
  (unset GIT_DIR; exec bundle)
  # Se completa el checkout aunque falle bundler
  true
fi

Puedes adaptar este código para tu propio uso simplemente cambiando Gemfile por el archivo de dependencias que utilices (package.json o requirements.txt, por ejemplo) y bundle por el comando correspondiente (npm install o pip install -r requirements.txt, por ejemplo).

Fuentes y más información:

David Charte David Charte es un ingeniero informático y matemático apasionado por la divulgación del conocimiento. Cuando no está tratando de aprender un nuevo lenguaje, investiga en el campo de la ciencia de datos. Puedes seguirlo en Twitter en @fdavidcl. Ver todos los posts de David Charte
Archivado en: Herramientas

No te pierdas nada, recibe lo mejor en tu email

Si te ha gustado este art­ículo, únete a miles de desarrolladores que ya reciben cada mes nuestro boletí­n por email. No te pierdas los mejores trucos, noticias y frikadas.

Enviamos poco, pero bueno. Palabra de desarrollador.

Suscríbete aquí­

Sí­guenos también en:

Telegram LinkedIn YouTube
La mejor formación online para desarrolladores como tú

Agregar comentario

Los datos anteriores se utilizarán exclusivamente para permitirte hacer el comentario y, si lo seleccionas, notificarte de nuevos comentarios en este artículo, pero no se procesarán ni se utilizarán para ningún otro propósito. Lee nuestra política de privacidad.