En este primer artículo aprenderemos la parte teórica del uso Git Hooks y con ello todos los beneficios que nos pueden aportar a nuestros proyectos.
Este es el índice que se va a utilizar para estructurar este artículo
- Hooking de Eventos
- Git Hooks
- Usos Generales de los Git Hooks
- Construir un Git Hook desde 0
- Conclusiones
Hooking de Eventos
¿Qué es un Hook de Evento?
Según la Wikipedia:
"El término hooking engloba una serie de técnicas utilizadas para alterar o aumentar el comportamiento de un sistema operativo, de aplicaciones o de otros componentes de software interceptando llamadas a funciones o mensajes o eventos pasados entre componentes de software. El código que maneja estas llamadas a funciones, eventos o mensajes interceptados se denomina hook."
Diremos entonces que un "hook de evento" es un script que facilita el poder aplicar ciertas políticas cuando se producen ciertos eventos.
Por lo tanto, permite cambiar el comportamiento del programa en algunos aspectos sin tener que cambiar su código. O lo que es lo mismo que decir, que se trata de una pieza de código que interacciona o modifica otra pieza de código.
Idea: Añade funcionalidad a la aplicación o al ciclo de desarrollo cuando se produce un evento
Nota:
Existen diferentes tipos de técnicas de hooking en función en la parte en la que se ejecute. Por ejemplo: hooking de APIs, etc.
Contexto del uso Hooks con repositorios
Normalmente utilizamos los sistemas de control de versiones para subir código y llevar su registro de commits.
La calidad de la subida de código depende de las posibles guías de estilo de desarrollo que puedan existir y sobre todo a la actitud/predisposición de cada desarrollador para implementarla o utilizarla.
Algunos ejemplos de aspectos de calidad que se pueden considerar pueden ser:
- El cumplimiento de reglas de linting
- Pasar la batería de test unitarios definida
- Cumplir un valor de cobertura específico
- Etc.
Estos aspectos de calidad se suelen encontrar definidos en los flujos de programación, algunas veces son manuales y otras veces están automatizados dentro del ciclo de desarrollo de una aplicación.
Consejo
Algunos desarrolladores tratamos de mejorar los flujos de desarrollo constantemente para tratar evitar problemas que ya hemos vivido en programación una y otra vez -> Buscar soluciones y evitar lágrimas
Una posible solución de mejora para los flujos de programación y la aplicación de guías de estilo podría ser el uso de elementos tipo hooks de evento que se ejecuten antes o después de cosas como: un commit, push, etc.
Lo que nos va a permitir hacer cosas en estos "momentos" como:
- Validar nombre de la rama sobre la que se va a subir el código
- Validar el código
- Linting de código: estilo/formato, etc.
- Formatear el código
- Revisión ortográfica (por ejemplo: Markdown con hunspell)
- Cumplimiento de nomenclatura
- Linting de mensajes de confirmación
- Comprimir imágenes
- Ejecutar tests
- Evitar un mensaje de commit vacío o muy corto
- Comprobar la complejidad del código
- Análisis de código estático
- Análisis de vulnerabilidades de seguridad
- Generar documentación
- Actualizar dependencias instaladas cuando se va a cambiar de una rama
- …
Con la implementación de algunas o todas estas fases, se podría mejorar la calidad de las subidas de código y que el valor de la calidad no dependiera de la buena actitud/predisposición del desarrollador.
Además, esto podría aplicar por defecto a todo el equipo y formaría parte de la metodología de trabajo con lo que se conseguiría mayor coherencia y estandarización en los desarrollos.
Nota:
Con esto se cumpliría el patrón de desarrollo de "fallar rápido", ya que se podrían detectar errores antes de que lo pudieran hacer incluso las herramientas de CI. Esto se notaría mucho en la productividad de CI.
Pero cuidado, NO es un reemplazo para los pipelines de CI/CD (como Gihub Actions, CircleCI, etc-)
En el caso de que alguna de las fases NO se cumpla según la hayamos definido se puede evitar que se realice la subida de código a un repositorio. Pero si el código pasa todas las fases definidas entonces sí que se realizará la operativa de commit sobre el repositorio.
¡Esto es super interesante! Se puede impedir la subida de código si algo no está "correcto"
Cada repositorio tiene su propia forma de utilizar hooks, por lo que es muy necesario ver la documentación para ver cómo proceder en cada caso.
Además, este tipo de hooks se pueden implementar de diferentes formas y está muy valorada su automatización 🙂
Git Hooks
¿Qué es un Git Hook?
Un Git Hook (o gancho de Git) es un script personalizado que puede implementar un desarrollador para inferir en algún evento que ocurre en el ciclo de vida de Git.
Por lo tanto, serían los hooks de tipo evento que ocurren dentro de un repositorio.
Características:
- Es una función integrada de Git -> Requiere una instalación local de Git
- Hay que utilizarlos dentro de un repositorio Git para que funcione
- Facilita
- Añadir un comportamiento adicional a las acciones comunes de Git
- Cada una de ellas tiene un objetivo concreto
- Automatizar tareas
- Aplicar políticas corporativas, área o de equipo
- Agilizar los flujos de trabajo
- Añadir un comportamiento adicional a las acciones comunes de Git
- Se almacenan en el directorio .git/hook del repositorio Git local utilizado
- En este directorio se proporcionan varios ejemplos por defecto
- Se puede ejecutar antes o después de que se produzcan cualquiera de las operaciones de Git
- Tipologías: pre hooks y post hooks
- Deberían de ser rápidos -> No deberían de añadir retardo en los flujos de trabajo de Git
- Requiere
- Documentación -> Recordar que como cualquier código esto va a tener que ser mantenido en algún momento
- Avisar de su uso
- Se debería de explicar al resto de desarrolladores sobre la forma de utilizarse
- Explicar en la documentación del proyecto / README
- No ser intrusivos -> NO deben realizar ningún tipo de modificación sobre el código sin obtener el consentimiento del usuario
- Se pueden implementar con diferentes lenguajes: Shell, Python, etc.
Importante
Los Git Hooks se encuentran localizados en el directorio ".git/hook/" del repositorio local, por lo que hay que tener en cuenta que estos se encuentran fuera control de versiones (no tracking). Esto significa que cualquier modificación sobre alguno de los Git Hooks NO se subirá con el código.
Por otro lado, se aconseja tratar de guardar los Git Hooks implementados en un directorio fuera del repositorio local, ya que si se borrar el repositorio local entonces se borraran todos los Git Hooks ya que se encontraban en el directorio .git/hook/
Algunas soluciones a lo anterior:
- Crear un directorio dentro del proyecto que pueda venir dado por ejemplo desde el arquetipo
- Disponer de un repositorio externo de Git Hooks
Git dispone de diferentes hooks para disparar comandos antes o después de un evento específico. Los más típicos son, por ejemplo:
- "pre-commit" permite ejecutar un script antes de finalizar un commit y se suele utilizar para validar el formato del código o bien ejecutar pruebas antes de hacer un commit
- Este es uno de lo más utilizado
- "pre-push"* permite ejecutar un script antes de realizar un push y se suele utilizar para confirmar la rama sobre la que se sube o bien realizar pruebas extras
Usos Generales de los Git Hooks
En este aparto de explicará el uso de algunos usos para los Git Hooks
- Mostrar Git Hooks disponibles
- Evitar el uso Git Hooks
- Ver configuración de Git Hooks
Mostrar Git Hooks disponibles
Pasos a seguir:
- Arrancar un terminal
- Ubicarse dentro de un repositorio Git local
- Ejecutar el siguiente comando
ls -1 .git/hooks/
- Verificar la lista de Git Hooks
Si el fichero contiene la extensión ".sample" entonces se trata de un ejemplo y no se encontraría habilidado para su uso
Para estar habilitado el fichero debería de NO contener la extensión y debería de tener los permisos de ejecución o bien ser una enlace símbolico.
ls -la .git/hooks/
Evitar el uso Git Hooks
Para evitar el uso de Git Hooks se suele incorporar sobre el comando de Git a ejecutar el parámetro : –no-verify o -n
# Ejemplo de uso 1
git commit --no-verify -m "hello world"
# Ejemplo de uso 2
git commit -nm "hello world"
Evitar el uso Git Hooks para el caso core.hooksPath
Ejecutar el siguiente comando para deshabilitar los Git Hooks
git config core.hooksPath no-hooks
Otra forma un poco más "friki" sería ejecutar
git config core.hooksPath /dev/null
De esta forma se evita que encuentre ningun Git Hook
Para re-habilitar los Git Hooks
git config --unset core.hooksPath
Mejoras
Para ayudar a diferenciar entre la operación que sí lo ejecuta y las que no algunos desarrolladores suelen crear unos alias para diferenciarlos
# Creación de alias
# ~/.bash_aliases
alias gc='git commit'
alias gcv='git commit --no-verify'
Ver configuración de Git Hooks
Pasos a seguir:
- Arrancar un terminal
- Ubicarse dentro de un repositorio Git local
- Ejecutar el siguiente comando
git config --list
Con este comando se podrá ver toda la configuración cargada en Git, aquí puede resultar interesante fijarse en lo relacionado con los Git Hooks
- Que no exista la propiedad "core.hooksPath" si no se esta utilizando
- El valor de directorio o de desactivación de la propiedad "core.hooksPath" cuando se esta utilizando
Se puede ver en que fichero se encuentra la configuración con el siguiente comando
git config --list --show-origin
Se podría acceder a cada fichero y retocar lo que fuera necesario.
Construir un Git Hook desde 0
Para construir un Git Hook desde 0" hay que realizar una serie de pasos:
- Definir las necesidades del Git Hook
- Implementar un fichero de script específico (opcional)
- Creación de un Git Hook
- Preparación de la configuración
1. Definir las necesidades del Git Hook
El primer paso a realizar para poder crear un Git Hook es poder contestar a las siguientes preguntas:
- ¿Qué queremos que haga de forma general el Git Hook?
- ¿Qué aspectos van a ser utilizados dentro del Git Hook de evento?
- Ejemplos: ejecución de test unitarios, revisión de cobertura de código, etc.
- *¿Qué comportamiento queremos que tenga cada aspecto anterior con respecto a que algo vaya mal durante su ejecución?
- Si se quiere que continue y que pueda ser meramente informativo
- Si se quiere que sea bloqueante y que no permita continuar
- ¿Qué momento (evento) utilizaremos para que se dispare?
- Ejemplo: pre-commit, push, etc.
Una vez tenemos claro todo, entonces podemos continuar 🙂
2. Implementar un fichero de script específico (opcional)
Notas
Hay que tener en cuenta que este paso es opcional ya que el Git Hook se podría desarrollar directamente, sin tener que desarrollar el script de un fichero aislado.Mi consejo es que leas este punto para saber lo que implica y luego decidas si te lo quieres saltar o no 😉
La idea es que como un Git Hook se trata de un script y por lo tanto es código, lo tratemos como el resto de código para que tenga versionado, una copia del código, etc.
Para este apartado podemos tener en cuenta los siguientes puntos:
- Crear un directorio específico dentro del proyecto para que contenga estos scripts como pueden ser los directorios a nivel del proyecto: scripts/, bin/, git-hooks/ o hooks/
- Los directorios scripts/ y bin/ se pueden reaprovechar de otros usos: preparación de entorno, instalación de dependencias desde un script, etc.
- Los directorios git-hooks/ y hooks/ se pueden utilizar para cosas más relacionadas con temática "hook" y así separarlos del resto de scripting del proyecto
- Otra forma de crearlo es de forma oculta con el carácter "." por delante del nombre
- Desarrollar los Git Hooks de la forma que sea más autocontenida posible (que tenga todo lo que necesita para funcionar) o bien que haga referencia a otros scripts
- Estas referencias pueden estar en el mismo directorio u otro
Buenas Prácticas
Algunos aspectos de buenas prácticas pueden ser los siguientes:
- Generales
- Testing
- Uso de fases del ciclo de desarrollo
- Repositorio independiente de Git Hooks
Generales
Dependiendo del lenguaje que se esté utilizando para implementar el Git Hook se podrán utilizar todas las buenas prácticas existentes para su desarrollo en su lenguaje y sobre la plataforma utilizada
- Estructuración del código
- Script autocontenido
- Referencias a ejecutar uno o más ficheros externos
- Ejecución de comandos de otras aplicaciones*
- …
Ejemplo: Git Hook "pre-commit" Ad-hoc implementado sobre Shell Script
Ejemplo de Git Hook "pre-commit" implementado sobre Shell Script para cualquier proyecto donde se usan los comandos propios de Shell y de la plataforma sobre la que se ejecutará, se requiere confirmar el uso de comandos que estén disponibles para esas condiciones.
#!/bin/sh
# Configuration
MESSAGE=$(cat $1)
COMMIT_FORMAT_PATTERN="^(feat|fix|docs|style|refactor|test|chore|perf|other)(((.*)))?: #([0-9]+) (.*)$"
# Execution
echo "Running Check Commit Message"
if ! [[ "$MESSAGE" =~ $COMMITFORMAT ]]; then
echo "Your commit was rejected due to the commit message.nSkipping..."
exit 1
fi
exit 0
Ejemplo 2: Git Hook "pre-commit" Referenciado implementado sobre Shell Script
Ejemplo de Git Hook "pre-commit" implementado sobre Shell Script para cualquier proyecto donde se usan los comandos propios de Shell y donde se procede a la ejecución de otro script implementado en Shell.
Requiere confirmar la localización del fichero y todo el tema de permisos de ejecución.
#!/bin/bash
echo "Running Build"
sh run-tests.sh
exit 0
Testing
Al desarrollarse como un script asilado en un fichero se pueden realizar pruebas de desarrollo para verificar que funciona correctamente.
Por lo tanto, podremos ver si funciona antes de utilizarlo y poder ver cuáles son las condiciones que requiere el entorno para ejecutarse.
Uso de fases del ciclo de desarrollo
Dependiendo del tipo de proyecto implementado y de los frameworks utilizados, se podrán referenciar para realizar una ejecución de una o varias de sus fases.
Esta parte se podrá implementar de diferentes maneras:
Ejemplo: Built-in de pre-commit
Ejemplo de Git Hook "pre-commit" implementado sobre NPM para un proyecto Node.js referenciando a un comando preparado para esta acción en la sección de "scripts"
Requerirá que se ejecute de forma específica, se detallaran los comandos, la ejecución de otros elementos "built-in" y/o la ejecución de un script externo
Con ejecución de comandos:
# Fichero package.json
{
"scripts": {
...
"test": "jest",
"pre-commit": "npm run lint && npm run test"
...
}
}
Con ejecución desde un script:
# Fichero package.json
{
"scripts": {
...
"test": "jest",
"pre-commit": "./scripts/git/pre-commit.sh"
...
}
}
# Fichero sh o Git Hook "pre-commit"
#! /bin/sh
npm run lint && npm run test
Hay que tener en cuenta que cualquier elemento "built-in" también puede ser lanzado desde un script, lo que nos crea un "mundo de posibilidades"
# Fichero sh o Git Hook "prepare-pre-commit"
#! /bin/sh
npm run pre-commit
Cuando se ejecute este fichero se procederá a lanzar el comando "npm run" que posteriormente referencia al definido en el fichero package.json
Repositorio independiente de Git Hooks
Una mejora de alto nivel y que requiere tener cierta experiencia práctica con este tema sería la de disponer de los Git Hooks en un repositorio independiente.
De esta forma los Git Hooks estarían centralizados en un único punto y al ser un repositorio de código estos además estarían versionados.
Por contra, habría que proporcionar un script para configurar el repositorio del proyecto para usar este repositorio como su directorio de Git Hooks o bien que se hiciera alguna adaptación para habilitar su uso.
Todo esto facilitaría enormemente la compartición entre los miembros del equipo. Y seguiríamos trabajando en la estandarización y normalización de los desarrollos :-).
3. Creación de un Git Hook
Existen varias formas de desarrollar un Git Hook
- Creación de un Git Hook: Script ad-hoc
- Creación de un Git Hook: Script enlazado
- Creación de un Git Hook: Script enlazado con la propiedad "core.hookspath"
Por lo tanto, habrá que decidir la forma a utilizar.
Creación de un Git Hook: Script ad-hoc
En este caso se va a crear directamente el script de Git Hook sobre la configuración del directorio .git/hooks.
Esta forma hace que se pueda desarrollar un poco más rápido pero que se pierda un poco el control sobre lo que se está haciendo, que cada persona lo tenga que implementar de forma individual, que no tenga una distribución automatizada, que esta dependa de la definición y seguimiento sobre una guía de desarrollo y sobre todo que al borrar el directorio de .git/ se perderán todos los Git Hooks implementados.
Pasos a seguir:
- Abrir el directorio .git/hooks del repositorio seleccionado
- Localizar el Git Hook de ejemplo que se quiere implementar. Por ejemplo: "pre-commit.sample"
- Crear una copia de seguridad del Git Hook seleccionado (Opcional)
- Eliminar la parte ".sample" del nombre del Git Hook o bien crear un archivo nuevo
- Verificar que el nombre del Git Hook se corresponde con uno de los considerados válidos. Por ejemplo: "pre-commit".
- Cambiar los permisos de ejecución del archivo
Si se creado una copia desde un fichero tipo ".sample" entonces este fichero ya tendrá los permisos, si el fichero es nuevo entonces habrá que establecer los permisos de ejecución
# Ejemplo para "pre-commit" desde el directorio
chmod +x pre-commit
# Ejemplo para "pre-commit" sobre el directorio
chmod +x .git/hooks/pre-commit
- Verificar que tiene el permiso asignado
ls -la .git/hooks
- Elegir el lenguaje de scripting que se quiere utilizar para implementar el Git Hook (Python, Bash, Shell, PowerShell, etc.)
- Editar el archivo con la implementación seleccionada
- Opción 1: Editar directamente sobre este fichero
- Opción 2: Disponer contenido de la edición en un script disponible previamente en algún directorio. Por ejemplo, en el directorio scripts/ y sobre el que únicamente habría que copiar el código de este script al fichero disponible en .git/hooks/
Este sería el contenido del fichero pre-commit:
#!/bin/sh
echo "[ad-hoc] This runs before your commits!!!"
Este código mostrará este mensaje antes de hacer el commit
- Probar el Git Hook
Ejemplo de ejecución de lo anterior
Creación de un Git Hook: Script enlazado
Esta forma de implementarlo soluciona el problema de la confirmación del código anterior, para ello implementa un enlace entre un script definido en el proyecto con el definido por defecto por Git.
Pasos a seguir:
- Crear un directorio custom dentro del proyecto para los Git Hooks
Hemos hablado antes de diferentes posibilidades para este directorio: scripts/, bin/, git-hooks/ o hooks/
- Crear el script en este directorio con el mismo nombre que tendría en .git/hooks/ Por ejemplo: "pre-commit".
- Opción 1: Copiar el archivo hook seleccionado del directorio .git/hooks/ sin ".sample"
- Opcion 2: Crea un fichero nuevo con el nombre del Git Hook
- Verificar el que el nombre del Git Hook se corresponde con uno de los considerados válidos. Por ejemplo: "pre-commit".
- Cambiar los permisos de ejecución del archivo
# Ejemplo para "pre-commit" desde el directorio git-hooks/
chmod +x pre-commit
# Ejemplo para "pre-commit" sobre el directorio git-hooks/
chmod +x git-hooks/pre-commit
- Verificar que tiene el permiso asignado
ls -la git-hooks/
- Crear un enlace simbólico entre ellos con el siguiente comando
Nota: Es muy importante ejecutar el siguiente comando desde el path del proyecto
ln -s -f ../../<hooks-dir>/[hook-name] .git/hooks/[hook-name]
# Ejemplo para "pre-commit" con el directorio "git-hooks"
ln -s -f ../../git-hooks/pre-commit .git/hooks/pre-commit
-
Verificar que se ha creado un fichero "pre-commit" tipo alias en el directorio .git/hooks/
-
Probar el Git Hook
Ejemplo de ejecución de lo anterior
Creación de un Git Hook: Script enlazado con core.hookspath
Desde la versión 2.9.0 de Git se puede establecer la propiedad "core.hookspath" que permite establecer un directorio global para los hooks en la máquina. Por lo que la idea sería referenciar a un directorio del proyecto donde se ubiquen los Git Hooks.
Hay que configurar Git para usar un directorio diferente donde localizar los hooks
Pasos a seguir:
- Crear un directorio custom dentro del proyecto para los Git Hooks
Hemos hablado antes de diferentes posibilidades para este directorio: scripts/, bin/, git-hooks/ o hooks/
- Cambiar la configuración de Git para usar el anterior directorio
# Ejemplo 1
git config --global core.hookspath git-hooks
# Ejemplo 2 Uso de un directorio oculto
git config --global core.hookspath ./.git-hooks
- Verificar que se ha establecido esta propiedad en la configuración de Git
git config --list --show-origin
Se va añadir esta propiedad en el fichero .gitconfig de tu usuario al utilizar el parámetro "–global" sino se va a configurar en el fichero "config" del directorio ".git/".
- Probar el Git Hook
Ejemplo de ejecución de lo anterior
4. Preparación de la configuración
Con todo lo anterior, se ha podido ver que configurar el tema de los Git Hooks lleva un rato y hay que saber un poco…jejeje.
Hasta el momento se ha enseñado a configurarlos de forma manual, pero la idea es que le demos una vuelta a esta parte y que facilitemos algun tipo de automatismos que realice lo mismo que la configuración manual, pero sin casi intervención humana y por lo tanto sin fallos.
Es decir… vamos a ver como podemos distribuir todo esto.
De esta forma se facilitaría a otros de forma sencilla la configuración por lo que seguiriamos estandarizando y homogeneizando la forma de hacer las cosas.
Formas de solucionarlo
- Scripting
- Operativa en ciclo de de desarrollo
- Fichero de configuración ".gitconfig"
Scripting
Hacer uso de scripts externo que sirvan para preparar/configurar el entorno y/o el proyecto
Cualquiera de los scripts implementados deberíon de ser explicados en la documentación dando detalles del punto en el que ejecutarse, la manera de hacerlo, etc.
Deberían de venir dados en el propio proyecto o bien desde el arquetipo
Tipos:
- Script específico de Git Hooks
- Script general
Script específico de Git Hooks
Disponer de un script específico en alguna sección del proyecto como puede ser el directorio scripts/ que contenga todo lo necesario para configurar los Git Hooks de forma específica.
Se puede crear algún tipo de subdirectorio en su interior para separarlos del resto de scripts que existan (Por ejemplo: scripts/git/).
Para cada uno de los script de Git Hooks existen muchas formas de implementarse
Por otro lado, existen también varias formas de configurar estos Git Hooks como podría ser la de copiar el script específico directamente sobre el directorio .git/hooks/" con los permisos adecuados.
Lo ideal es que todos los Git Hooks se hagan la misma manera.
Se puede ejecutar de forma específica desde el propio script o bien ser ejecutado desde el ciclo de desarrollo.
Ejemplo de script específico para "pre-commit"
# File: scripts/git/prepare-githooks-pre-commit.script.sh
#!/bin/bash
# Execution
echo "Prepare 'pre-commit' Git Hook With Script"
cp ./run-basic-pre-commit.sh ../../.git/hooks/pre-commit
chmod +x ../../.git/hooks/pre-commit
echo "'pre-commit' Git Hook preparation successfully!"
exit 0
Script general
Disponer de un script general en alguna sección del proyecto como puede ser el directorio scripts/ donde la configuración de Git Hooks pueda ser una parte concreta o bien definida de forma ad-hoc o bien referenciando a otro script.
Se puede crear algún tipo de subdirectorio en su interior para separarlos del resto de scripts que existan (Por ejemplo: scripts/git/).
Se puede ejecutar de forma específica desde el propio script o bien ser ejecutado desde el ciclo de desarrollo.
Ejemplo que instala y configura TODOS los Git Hooks necesarios
# File: scripts/git/prepare-githooks.script.sh
#!/bin/bash
./prepare-githooks-pre-commit.script.sh
...
exit 0
Operativa en ciclo de desarrollo
Si se usa alguna herramienta de gestión de ciclo de desarrollo para una aplicación, se puede ver como incorporar una fase que configure o bien que instale el tema de los Git Hooks.
Tipos:
- Configuración específica de Git Hooks en el ciclo de desarrollo
- Configuración estándar de Git Hooks en el ciclo de desarrollo
Configuración específica de Git Hooks en el ciclo de desarrollo
Crear una fase custom para realizar esta tarea
Características:
- Existen muchas formas de implementar este punto
- Habrá que indicar en la documentación en que momento se debe ejecutar y la forma
- Cualquier cambio importante requerirá retocar este punto
Ejemplo: Built-in script de Node.js con comandos ad-hoc
Se presentan dos posibilidade:
"prepare:githooks:pre-commit:adhoc": Implementación basada en una secuencia de comandos que afectaría sólo a pre-commit. En este ejemplo se supone que el script de pre-commit ya se encuentra implementado en el directorio scripts/
"prepare:githooks:config": Implementación basada en la ejecución de un comando de Git que facilita el cambio de directorio para los hooks
"scripts": {
...
"prepare:githooks:pre-commit:adhoc": "cp ./scripts/git/pre-commit .git/hooks/ && chmod +x .git/hooks/pre-commit && echo 'pre-commit hook copied!'",
"prepare:githooks:config": "git config core.hooksPath git-hooks",
...
},
Ejemplo 2: Built-in script de Node.js con comandos que ejecutan un script
Implementación basada en la ejecución de un script externo. Similar al anterior ejemplo pero con secuencia de comandos implementadas en un script
"scripts": {
...
"prepare:githooks:pre-commit:script": "./scripts/git/prepare-githooks-pre-commit.npm.sh",
...
},
Configuración estándar de Git Hooks en el ciclo de desarrollo
Importante
Dependerá del lenguaje seleccionado y de los frameworks que controlen el ciclo de desarrollo
Es otra forma de enfocar el anterior punto y que consiste en aprovechar alguna de las fases del ciclo de desarrollo
Para el caso que estabamos trabajando y que estaba montado en Node.js sería hace uso de las fases:
- "prepare": La fase "prepare" de npm se ejecuta tras realizar un
- "postinstall": la fase de "postinstall" de npm que se ejecuta justo despues de lanzar "npm install"
De esta forma en cuanto se instale el proyecto se configurar los Git Hooks
Ejemplo: Built-in script de Node.js con uso de postinstall
"scripts": {
...
"postinstall": "xxx,
...
},
Fichero de configuración ".gitconfig"
Hacer uso del fichero de configuración local de Git y que de esta forma cierta configuración pueda viajar con el proyecto y por lo tanto ser compartida de forma directa
Pasos a seguir:
- Crear un fichero global ".gitconfig" en el repo
git config -f .gitconfig core.hooksPath git-hooks
-
Revisar que se ha creado el fichero de forma local al proyecto
-
Commitear el fichero anterior
-
Adaptar la configuracion para que haga lectura de este fichero
git config --local include.path ../.gitconfig
- Verficar que al solicitar la configuración de Git aparece referenciada
git config --list --show-origin
Conclusiones
Los Git Hooks se convierten entonces en una herramienta muy potente para ayudar a cumplir las políticas definidas sobre los flujos de desarrollo de Git (evitar errores de codificación, cumplimiento de nomenclatura, cumplimiento de convenciones de código, etc.). Si estas políticas se encuentran definidas y sobre todo automatizadas podemos ahorrar mucho esfuerzo en las revisiones de código.
Para ver que pueden hacer por nosotros vuelve a leer la sección de este artículo de "Contexto del uso Hooks con repositorios"
Recordar que subir código con errores a los repositorios, tiene un coste muy alto y este se incrementa cuanto más tarde se detecte el error.
Su idea principal es poder utilizarlos en fases tempranas de desarrollo por lo que podemos mantener la coherencia de los desarrollos al poder asegurar el código en muchos de sus aspectos desde el minuto 1. Además, facilitan el poder personalizar estas operaciones según las necesidades de un proyecto o equipo.
Tienen una desventaja que es que pueden añadir algo de retardo a las subidas de código.
Con su implementación y uso entonces se puede conseguir una estandarización y homogenización de los desarrollos en una fase temprana, lo que significa una mejora de la calidad considerable
Ahora ya solo queda empezar a utilizarlos… (En el siguiente artículo)