Mejorando nuestro código con pre-commit

Cuando revisamos código, a menudo empleamos tiempo repasando pequeños fallos o detalles de estilo que nos desvían de lo verdaderamente importante. En este post presentaremos pre-commit, una herramienta que ataca este problema corrigiendo nuestro código automáticamente.

¿Qué hace pre-commit?

Antes de explicar lo que hace pre-commit, conviene tener claros ciertos aspectos de Git, y en concreto, de los Git Hooks. Se trata del mecanismo que ofrece Git para ejecutar scripts en diferentes puntos clave, como podrían ser un commit o un merge. De esta forma, podremos definir un script (Hook) que se ejecute justo antes de hacer push o después de hacer un merge.

Considerando lo anterior, podemos decir que pre-commit es un framework que nos permite añadir, gestionar y ejecutar esos hooks de forma sencilla. Como veremos a continuación en el ejemplo práctico, ofrece un sinfín de hooks  listos para usar en múltiples lenguajes.

Ejemplo práctico

Lo primero que haremos será instalar pre-commit con pip:

pip install pre-commit

Podemos validar la instalación y su versión con:

pre-commit --version

Una vez tengamos instalado pre-commit, abriremos el proyecto en el que lo queramos usar y crearemos el fichero .pre-commit-config.yaml, que contendrá la configuración con la que queremos que la herramienta funcione.

Un ejemplo de fichero de configuración podría ser el siguiente:

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v3.2.0
    hooks:
    -   id: trailing-whitespace
    -   id: end-of-file-fixer
    -   id: check-yaml
    -   id: check-added-large-files

Vemos cómo se definen los repositorios de los que se van a tomar los hooks (de momento, solo estamos usando un repositorio) y los respectivos hooks. Se trata de comprobaciones generales, pero podemos ir añadiendo nuevos hooks en función de nuestras preferencias. 

En Supported Hooks puedes encontrar una lista con diferentes hooks disponibles. En nuestro caso, vamos a personalizar el fichero de configuración de la siguiente manera: 

default_stages:
  - commit
  - push
fail_fast: true
repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v3.2.0
    hooks:
    -   id: trailing-whitespace
    -   id: end-of-file-fixer
    -   id: check-yaml
    -   id: check-added-large-files
    -   id: detect-private-key
    -   id: double-quote-string-fixer
-   repo: https://github.com/asottile/dead
    rev: v1.5.0
    hooks:
    -   id: dead
-   repo: https://github.com/dannysepler/rm_unneeded_f_str
    rev: v0.1.0
    hooks:
    -   id: rm-unneeded-f-str

En primer lugar, notamos que se ha añadido default_stages, donde definimos las etapas en las que queremos que se disparen los hooks. En este caso, hemos definido que se disparen antes de un commit o un push. Esto solo tendrá efecto sobre los hooks que no tengan etapas definidas.

A continuación encontramos fail_fast, que define la política de actuación tras encontrar un fallo: seguir con la ejecución (false) o parar (true).

También hemos añadido nuevos hooks, tanto del repositorio usado anteriormente como de nuevos repositorios.

Una vez que tenemos listo nuestro fichero de configuración, ejecutamos el siguiente comando para configurar los Git Hooks.

pre-commit install

Con esto, pre-commit estaría listo para mejorar nuestros commits. Sin embargo, si vamos a usarlo en un proyecto ya existente, quizá tenga sentido revisar todo el código actual en lugar de ir revisando los ficheros que van entrando a nuevos commits. Podemos hacer esto con el siguiente comando:

pre-commit run --all-files

Tanto ejecutando pre-commit contra todos los ficheros como al hacer un commit, nos mostrará el resultado y las acciones realizadas. En la siguiente captura podemos ver cómo se muestra la fase en la que ha fallado (Fix End of Files) y los ficheros afectados, en este caso, main.py. 

Observamos que no se han seguido ejecutando hooks tras el fallo. Esto es debido a la configuración fail_fast que definimos anteriormente.

Si revisamos los ficheros implicados, veremos que el hook ha aplicado los cambios necesarios por nosotros.

También podemos ver cómo se identifican claves privadas con el respectivo hook:

Conclusión

En este post hemos introducido pre-commit, una herramienta que nos permite encontrar fallos en nuestro código de forma automática. Hemos visto cómo la podemos instalar y un breve caso de uso.

¡Eso es todo! Si este artículo te ha resultado interesante, te animamos a visitar la categoría Software para ver todos los posts relacionados y a compartirlo en redes. ¡Hasta pronto!
Sergio Pérez
Sergio Pérez
Artículos: 12