Automatiza como un Pro. Git Hooks con Flutter y Dart 🪝

Alfredo Bautista Santos
6 min readAug 3, 2024

--

Photo by Yancy Min on Unsplash

Como desarrolladores, buscamos constantemente herramientas que nos ayuden a ser más eficientes y a producir código de mayor calidad. Una de estas herramientas, a menudo desconocida, son los Git Hooks. En este artículo, exploraremos qué son los Git Hooks y cómo podemos aprovechar su poder para automatizar tareas en nuestro flujo de trabajo con Flutter.

¿Qué son los Git Hooks?

Los Git Hooks son scripts que se ejecutan automáticamente cada vez que ocurre un evento específico en un repositorio Git. Estos eventos pueden ser acciones como hacer un commit, un push, un merge, etc. Los Hooks nos permiten personalizar el comportamiento de Git, ejecutando tareas personalizadas antes o después de cada evento.

Imagina, por ejemplo, que quieres asegurarte de que el código de tu proyecto Flutter esté bien formateado antes de cada commit. En lugar de ejecutar manualmente el formateador de Dart cada vez, puedes usar un Git Hook llamado pre-commit que se ejecute automáticamente antes de cada commit y formateará el código por ti.

En esencia, los Hooks nos brindan la capacidad de “conectar” scripts personalizados al flujo de trabajo de Git, permitiéndonos automatizar tareas y personalizar el comportamiento del sistema de control de versiones.

Tipos de Git Hooks: Locales vs. Remotos

Los Git Hooks se dividen en dos categorías principales: Locales y Remotos. Los Hooks Locales se ejecutan únicamente en la máquina del desarrollador, mientras que los Hooks Remotos se ejecutan en el servidor que aloja el repositorio Git.

  • Hooks Locales: Son ideales para automatizar tareas que afectan solo al flujo de trabajo individual del desarrollador, como el formateo de código, la ejecución de tests unitarios o la validación de mensajes de commit. Al ser locales, no afectan a otros colaboradores del repositorio.
  • Hooks Remotos: Se ejecutan en el servidor, generalmente en respuesta a eventos como la recepción de un push o la creación de una merge request. Son útiles para implementar políticas de control de calidad a nivel del repositorio, como la ejecución de tests de integración o el análisis estático del código. Los Hooks Remotos afectan a todos los colaboradores del repositorio.

Hooks Locales: Tu arsenal de automatización personal con Flutter y Dart

En el contexto del desarrollo con Flutter, los Hooks Locales son especialmente útiles para automatizar tareas repetitivas y asegurar la calidad del código. Veamos algunos de los Hooks Locales más comunes y cómo podemos usarlos para mejorar nuestro flujo de trabajo:

  • pre-commit: Este Hook se ejecuta antes de que se cree un commit. Es ideal para ejecutar tareas de validación y formateo de código. Por ejemplo, podemos usar dart format para formatear automáticamente el código Dart antes de cada commit, asegurando la consistencia del estilo de código en todo el proyecto.
  • prepare-commit-msg: Este Hook se ejecuta después de que se crea el mensaje de commit, pero antes de que se abra el editor para editarlo. Se puede usar para modificar el mensaje de commit automáticamente, por ejemplo, añadiendo información como la versión del proyecto o la rama actual.
  • commit-msg: Este Hook se ejecuta después de que el usuario ha editado el mensaje de commit. Se puede usar para validar el mensaje de commit, asegurándose de que cumple con un formato específico o que contiene la información necesaria.
  • post-commit: Este Hook se ejecuta después de que se ha creado un commit. Se puede usar para notificar a otros sistemas sobre el nuevo commit, enviar un correo electrónico al equipo de desarrollo o actualizar un tablero Kanban.
  • pre-push: Este Hook se ejecuta antes de que se realice un push al repositorio remoto. Es ideal para ejecutar tests de integración o realizar un análisis estático del código, asegurándose de que no se está subiendo código con errores al repositorio principal.

Vamos con un ejemplo de git hook

Uno de los ejemplos más comunes y útiles de Git Hooks locales es el pre-commit, que nos permite ejecutar acciones antes de la creación de un commit. Imaginemos que queremos asegurar que todo el código Dart de nuestro proyecto Flutter esté formateado de forma consistente, evitando así discrepancias de estilo entre diferentes desarrolladores y mejorando la legibilidad del código.

El siguiente script bash, que podemos usar como pre-commit, realiza precisamente eso

Desglosando el script:

  1. Función format_if_required: Esta función recibe una lista de archivos como argumento y ejecuta dart format en ellos. Posteriormente, utiliza grep para filtrar los archivos que no han sido modificados por el formateador, mostrando un mensaje de confirmación solo si se han aplicado cambios.
  2. Identificación de archivos Dart modificados: El script utiliza git diff para obtener una lista de los archivos que han sido modificados y que están a punto de ser incluidos en el commit. Se filtra esta lista para obtener solo los archivos con la extensión .dart.
  3. Condicional de formateo: Si se han encontrado archivos Dart modificados, se llama a la función format_if_required para formatearlos. En caso contrario, se muestra un mensaje indicando que no hay archivos para formatear.
  4. Salida del script: Finalmente, el script muestra un mensaje indicando que el commit está listo para ser creado y termina con un código de salida 0, indicando que no ha habido errores.

Un paso más allá: Dart para la creación de Git Hooks

Si bien los Git Hooks suelen ser scripts bash, podemos utilizar Dart para crearlos, aprovechando la potencia y flexibilidad del lenguaje, además de la sencillez para poder compilar a código nativo para ejecutar estos hooks en el SO del desarrollador o el servidor. Dart nos permite acceder a un amplio conjunto de librerías y herramientas, lo que nos brinda la posibilidad de crear Hooks más sofisticados y adaptados a nuestras necesidades específicas.

Por ejemplo, podemos utilizar las librerías dart:io y dart:convert para interactuar con el sistema de archivos y procesar datos JSON o YAMLs, respectivamente. También podemos aprovechar las herramientas de análisis estático de Dart, como dart analyze, para realizar verificaciones de código en nuestros Hooks.

Un ejemplo en Dart

Veamos un ejemplo de cómo utilizar Dart para escribir un Hook prepare-commit-msg, que nos permite modificar el mensaje de commit de forma automática antes de que el usuario pueda editarlo. En este caso, añadiremos la versión del proyecto al mensaje de commit, lo cual facilitará el seguimiento de los cambios y la identificación de la versión del código asociada a cada commit:

Analizando el script Dart:

  1. Importaciones: El script comienza importando las bibliotecas necesarias: dart:io para interactuar con el sistema de archivos y package:yaml/yaml.dart para procesar archivos YAML, en este caso, el archivo pubspec.yaml del proyecto Flutter.
  2. Función main: La función main es el punto de entrada del script. Recibe los argumentos pasados por Git, que incluyen la ruta al archivo del mensaje de commit y la fuente del commit (por ejemplo, “message” para un commit normal, “merge” para un merge, etc.).
  3. Validación de argumentos: El script verifica si se ha proporcionado el archivo del mensaje de commit. En caso contrario, muestra un mensaje de error y sale con un código de salida 1, indicando un error. También comprueba la fuente del commit para no modificar mensajes de commit para merges, squashs, etc.
  4. Obtención de la versión del proyecto: La función getProjectVersion lee el archivo pubspec.yaml del proyecto Flutter, extrae la versión del proyecto utilizando la biblioteca yaml y la devuelve como un String.
  5. Modificación del mensaje de commit: El script lee el mensaje de commit actual del archivo proporcionado, añade la versión del proyecto al final del mensaje y lo escribe de vuelta al archivo.
  6. Salida del script: Finalmente, el script muestra un mensaje de confirmación indicando que se ha añadido la versión del proyecto al mensaje de commit y sale con un código de salida 0, indicando éxito.

Git Hooks: Una herramienta para mejorar la calidad y eficiencia del desarrollo

Los Git Hooks son una herramienta valiosa para cualquier desarrollador que busca mejorar la calidad y la eficiencia de su flujo de trabajo. Automatizar tareas repetitivas, asegurar la consistencia del código y detectar errores antes de que lleguen al repositorio principal son solo algunos de los beneficios que nos ofrecen los Git Hooks.

En el desarrollo con Flutter, los Git Hooks son especialmente útiles, ya que nos permiten integrar las herramientas y librerías de Dart en nuestro flujo de trabajo de Git.

Amplia este tutorial con el vídeo en Youtube

Y si quieres seguir ampliando lo explicado en este tutorial, te recomiendo echarle un vistazo a mi vídeo de youtube donde vemos paso por paso los hooks y los implementamos en tiempo real, además de algunos consejos o como configurar todo el flujo de trabajo.

Te dejo el vídeo por aquí

Además de la documentación oficial de Git Hooks: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks

Por último dejo os mi twitter donde me encontraréis hablando sobre tecnología en general pero sobre todo Flutter 💙

¡Un saludo y hasta la próxima!

--

--

Alfredo Bautista Santos

Sysadmin and web developer. Co-organizer of GDGMarbella & FlutterConf in Marbella, Spain. Flutter enthusiastic.