Husky e lint-staged para pré-commit em React
Tags: react, webdev, tutorial
Published: 2024-02-07 21:33:23

## Introdução

Quem já se deparou com o problema de esquecer de rodar os testes ou ajustar o formato do código antes de subir ele, se deparando com uma falha na pipeline que faz a validação deles? Ou precisa executar rotinas sempre manualmente para seguir os padrões de projeto?
A ideia desse artigo é apresentar duas libs que em conjunto permitem configurar ações na etapa de pré-commit, para já bloquear um commit com falha em testes, formatar o código antes da realização de um commit ou realizar outra ação que for definida.

## Libs

- husky: é a lib que vai permitir rodar ações pré-commit.
- lint-staged: é a lib que vai definir as ações a serem executadas para os arquivos que estão adicionados em stage no git.

## Setup das libs

### 1- Husky

Para adicionar o husky na aplicação é necessário rodar o seguinte comando:

`yarn add --dev husky`

Para começar a configuração sugiro a execução do seguinte comando:

`npx husky init`

Ele vai gerar um arquivo `pre-commit` dentro da pasta `.husky`, o qual vai definir a executação das ações pré-commit. Com o seguinte conteúdo:

```
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm test
```

A princípio por default ele está configurado para rodar npm test, mas com a adição do lint-staged vamos atualizar esse arquivo.

Também vai ser gerado dentro de `package.json` o script para instalar o husky:

```
"scripts": {
  (...)
  "prepare": "husky install"
},
```

### 2 - lint-staged

Para adicionar o lint-staged é necessário rodar o seguinte comando:

`yarn add --dev lint-staged`

Para configurar as ações que serão executadas pré-commit, adicionar em package.json:

```
"lint-staged": {
  "*.js": [
  ]
}
```

`*.js` é o tipo dos arquivos adicionados em stage que vão ser executadas as ações pré-commit (usei esse tipo como exemplo, mas vai do tipo que estiver definido em sua aplicação), dentro de "[ ]" é onde serão colocadas as ações que serão executadas na etapa pré-commit.

Por fim para o uso do lint-staged a partir do husky, será necessário atualizar o arquivo `pre-commit`, ficando da seguinte forma:

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

npx --no-install lint-staged
```

Para começar a rodar o husky para realizar as ações pré-commit é necessário fazer a instalação dele rodando: `yarn prepare`

## Exemplo de execução

Agora vou apresentar um exemplo de execução com dois objetivos: formatar o código antes de realizar o commit e validar se os testes estão passando para permitir que o commit seja realizado.

Será levado em consideração para esse exemplo, uma app com um componente dentro de `App.js` e um arquivo de teste `App.test.js`, ambos dentro da pasta `src`. App a qual usa a lib do `Jest` para realizar os testes e o `prettier` para formatação do código.

No package.json, tem-se os seguintes scripts:
```
"scripts": {
  "test": "jest",
  "format": "prettier --write \"**/src/*.js\"",
  "prepare": "husky install"
  }
```

O `test` é responsável pela execução dos testes e o `format` pela formatação do código.

Para definir o que vai ser executado no pré-commit, colocar dentro de `package.json` os comandos a serem executados dentro de `lint-staged`:

```
"lint-staged": {
  "src/*.js": [
    "yarn format",
    "yarn test --findRelatedTests --bail"
  ]
}
```

Dessa forma está definido que para os arquivos que foram adicionados em stage no git, executar o `yarn format` e o `yarn test --findRelatedTests --bail` pré-commit.

O `--findRelatedTests` permite que uma vez que o componente App.js é modificado, ele rode os testes associados a ele (os dentro de App.test.js), e o `--bail` que se executar os testes e tiver uma falha cancelar a realização do commit. Esses comandos são para testes executados com Jest, dependendo da lib podem ser outros para não permitir o commit.

Por fim para realizar um teste do funcionamento das libs, seria realizar uma alteração no componente App.js, dar o `git add` nele e realizar um commit. Antes do commit ser realizado, vão ser executadas as ações definidas dentro de `lint-staged`, no caso desse exemplo será formatado o arquivo que foi modificado e será executado os testes associados ao componente, caso algum teste falhe o commit não será realizado, caso os testes passem o commit será concluído.

Execução no terminal:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gf0pnsyqpchlzv2obqlz.gif)

No caso de querer gerar um commit sem que as ações pré-commit ocorram, é só adicionar no final do git commit o `--no-verify` que o husky não será executado.

## Conclusão

Por fim, a ideia desse artigo é apresentar duas libs que em conjunto permitem realizar ações pré-commit, para evitar falhas em pipeline ou permitir executar processos que são usados de forma recorrente na app, para os arquivos que estão adicionados em stage no git, buscando facilitar o processo de desenvolvimento.