Crear un proyecto nuevo con Eslint, Stylelint, CommitLint y Husky
Tags: webdev, programming, spanish, tutorial
Published: 2024-06-21 22:47:33

En este artículo vamos a ver cómo configurar tu proyecto utilizando herramientas de revisión de código y vamos a modificar Git para que podamos ejecutar estas herramientas antes de subir nuestro código al repositorio, asegurándonos de mantener unas reglas, estructuras y configuraciones que homogenicen y limpien nuestro código.

  - [El comienzo](#el-comienzo)
  - [Formateador Airbnb](#formateador-airbnb)
  - [StyleLint y CommitLint](#stylelint-y-commitlint)
  - [Husky](#husky)
  - [Package.json](#packagejson)
  - [Integración con Husky](#integración-con-husky)
  - [Bonus Track: Comprobación de ramas](#bonus-track-comprobación-de-ramas)
  - [Repositorio de ejemplo](#repositorio-de-ejemplo)
  - [Final](#final)

---

## El comienzo

Para comenzar, me centraré en el uso de Angular, esta configuración puedes adaptarla fácilmente en los frameworks más populares cómo React, Vite y Astro.

En este artículo vamos a usar la última versión de Angular disponible al momento de escribirlo, que es la 18. Para ello, comenzaremos creando nuestro proyecto usando:

```sh
ng new proyectoArticulo
```

---

Asegúrate de cambiar "proyectoArticulo" por el nombre que desees utilizar. Sigamos los pasos del Angular CLI. No es el objetivo de este artículo explicarte cómo funciona el CLI de Angular, así que te mostraré la configuración que he elegido para el proyecto:

- He utilizado SCSS y no vamos a usar SSR.

Una vez finalice la creación del proyecto, pasamos a instalar la integración de ESLint con Angular usando el esquema @angular-eslint/schematics. Esta es una herramienta para el CLI de Angular, por lo que usaremos:

```sh
ng add @angular-eslint/schematics
```

---

De esta manera, al usar ng lint, directamente nos saltará ESLint.

Una vez instalado el Angular schematics, pasamos a la instalación de ESLint. Es muy popular el uso de Prettier cómo formateador de código junto a ESLint. Aunque este último puede modificarse, personalmente prefiero usar ESLint con las normas de formateo de Airbnb. Esta es una preferencia totalmente personal y es la que usaremos en el artículo.

## Formateador Airbnb

Para instalar ESLint junto a las normas de Airbnb, necesitaremos un listado de paquetes:

```sh
npm install eslint-config-airbnb-base eslint-config-airbnb-typescript eslint-plugin-simple-import-sort --save-dev
```

---

Como ves, las estamos guardando en dev, ya que estas dependencias solo nos interesan en desarrollo y no tiene sentido añadirlas a la versión de producción.

¿Qué son todas estas dependencias? Hemos añadido la normativa de Airbnb a ESLint, la variante para TypeScript, y el último paquete es para ordenar las importaciones.

Una vez tengamos esto, podrás ver que se ha creado el archivo .eslintrc.json, que es el que usa ESLint para guardar su configuración.

Si utilizas “_” para declarar valores que no se van a usar, te recomiendo que añadas dentro de overrides >> rules:

```json
"@typescript-eslint/no-unused-vars": [
  "error",
  { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }
]
```

---

Ahora vamos a configurar la extensión simple-import-sort que hemos instalado anteriormente y, además, vamos a compatibilizar un poco las reglas de Airbnb con el convenio de Angular deshabilitando los default imports. Al igual que el paso anterior, esto va dentro de rules:

```json
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"import/prefer-default-export": "off"
```

---

Ahora añadimos a ESLint que use los paquetes que hemos descargado de Airbnb. Dentro de extends añadimos:

```json
"airbnb-base",
"airbnb-typescript/base"
```

---

Una vez instalado ESLint, le indicaremos que ignore las carpetas node_modules y dist para evitar problemas tanto en las librerías como en el bundle de dist. Para ello, creamos el archivo .eslintignore y añadimos estas dos carpetas, similar a como haríamos con .gitignore, quedando así:

```sh
dist
node_modules
```

---

## StyleLint y CommitLint

Una vez tenemos esto, vamos a instalar StyleLint y CommitLint:

```sh
npm install --save-dev stylelint stylelint-config-standard-scss
npm install @commitlint/cli @commitlint/config-conventional --save-dev
```

---

Verás que se ha añadido la carpeta de configuración de StyleLint al estilo de ESLint, pero en cambio para CommitLint no. Así que vamos a crearla:

Creamos el archivo ``.commitlintrc.json`` y dentro de este archivo debemos poner:

```json
{
  "extends": ["@commitlint/config-conventional"]
}
```

---

## Husky

Ahora vamos a instalar la herramienta que nos permite utilizar los hooks de Git para comprobar que todo nuestro código pasa las normas establecidas antes de subirlo al repositorio. Para ello, usaremos:

```sh
npx husky-init
```

---

El comando nos pedirá instalar la dependencia de Husky, por lo tanto, le decimos que sí. Una vez instalada, en el directorio raíz de nuestro proyecto tendremos la carpeta .husky con varios archivos dentro. El que nos interesa es ``pre-commit``. Si lo abres, tendrás algo similar a esto:

```sh
# !/usr/bin/env sh
"$(dirname -- "$0")/_/husky.sh"
npm test
```

---

Como puedes ver, esto ejecutaría el comando npm test de nuestro proyecto antes de hacer el commit, y si estos presentan algún error, no nos dejará hacer el commit. Ahora nos faltaría añadir los formateadores de código.

## Package.json

Ahora vamos a crear nuestros propios comandos para que Husky pueda ejecutarlos de una manera limpia. Para ello, nos dirigimos al archivo ``package.json`` y dentro de la propiedad scripts añadimos:

```json
"lint:fix": "ng lint --fix",
"lint:scss": "stylelint src/**/*.scss"
```

---

Ahora tenemos nuestros linters preparados tanto para comprobar los archivos cómo para forzar estos cambios al subirlos al repositorio.

## Integración con Husky

Vamos a añadir estas sentencias a Husky. Para ESLint es bastante sencillo, ya que solo necesitamos dirigirnos al archivo pre-commit del directorio ``.husky`` y añadir:

```sh
npm run lint
npm run lint:scss
npm run test
```

---

Tendrás algo cómo esto dentro del directorio ``.husky/pre-commit``:

```sh
# !/usr/bin/env sh

. "$(dirname -- "$0")/_/husky.sh"

npm run lint
npm run lint:scss
```

---

Te preguntarás que pasó con CommitLint, para este último necesitamos añadirlo a través de la utilidad de comando de Husky para ello ejecutamos:

```bash
npx husky add .husky/commit-msg  'npx --no --commitlint --edit ${1}'     
```

---

¿Por qué está dentro de commit-msg y no dentro de  pre-commit como todo lo anterior?

El hook ``commit-msg`` se enfoca en la validación del mensaje de commit este se ejecuta después de que el mensaje de commit ha sido introducido, pero antes de que el commit sea finalizado, además de que nos permite obtener el nombre y el mensaje del commit.

## Bonus Track: Comprobación de ramas

Es frecuente que no quieras subir los cambios directamente a tu repositorio y que estos sean aprobados mediante una pull request. Para esto, podemos crear nuestro propio script para comprobar en qué rama estamos y si podemos o no hacer commit.

Dentro de la carpeta .husky, añadimos el archivo ``prevent-commit.sh`` y dentro de este añadimos el siguiente código en sh:

```sh
# !/bin/sh

branch_name=$(git symbolic-ref --short HEAD)
if [[ "$branch_name" != feature* ]] && [[ "$branch_name" != test* ]]; then
  echo "Commits are only allowed on feature and test branches. Current branch: $branch_name"
  exit 1
fi
```
---
 
Como puedes ver, en la sentencia if he especificado que solo se pueda hacer commit en el caso de que la rama comience con feature o test, siguiendo siempre la estructura base de los conventional commits. Recuerda que puedes ampliarlo o cambiarlo según tu gusto o necesidad.

Ahora para ejecutar nuestro .sh debemos añadirlo al hook de ``commit-msg`` añadiendo la siguiente línea

``bash .husky/prevent-commit.sh``

## Repositorio de ejemplo

Te dejo un enlace a un proyecto de GitHub vacío con la configuración que acabas de ver:

[AngularConventionalCommitsTemplate](https://github.com/altaskur/AngularConventionalCommitsTemplate)

## Final

Con este artículo tienes una estructura completa y avanzada del uso de linters y hooks de Git en un repositorio de Angular.

Espero que te haya sido de ayuda y que puedas aplicar estas configuraciones en tus proyectos. Si tienes alguna duda o sugerencia, no dudes en dejar un comentario.

¿Y tú? ¿Utilizas linters en tus proyectos? ¿Qué herramientas utilizas? ¡Déjame tu opinión en los comentarios!