DEV Community

Eduardo Rabelo
Eduardo Rabelo

Posted on

10 1

Aplicando Padrões de Código com Pré-Commit Hook usando Husky

Neste artigo, aprenderemos como configurar o Husky para evitar git commits ruins e impor padrões de código em seu projeto.

Introdução

Na maioria dos projetos em que já trabalhei de forma colaborativa, alguém assume o papel de campeão de limpeza de código. Geralmente é o líder da equipe e, muitas vezes, sua função envolve revisar os PRs e garantir que o amor e o cuidado sejam colocados na qualidade do código.

A qualidade inclui as convenções e padrões de código escolhidas, além da formatação do código.

Hoje, é uma boa prática em projetos JavaScript utilizar ESLint para definir as convenções de código do projeto. Por exemplo, como sua equipe se sente em relação ao uso de for loops? E o ponto-e-vírgula - são obrigatórios? Etc.

Essas são convenções.

A outra peça do quebra-cabeça é a formatação. Essa é a aparência visual do código. Quando há mais de um desenvolvedor trabalhando em um projeto, garantir que o código pareça consistente é algo a ser abordado.

Prettier é a ferramenta correta para isso.

No artigo anterior, aprendemos como combinar ESLint e Prettier, mas não aprendemos como realmente aplicar as convenções e a formatação em um projeto da vida real com vários desenvolvedores.

Neste artigo, aprenderemos como usar o Husky para fazer isso em um projeto baseado em Git.

Husky

Husky é um pacote npm que "torna os hooks Git fáceis".

Quando você inicializa o Git (a ferramenta de controle de versão com a qual você provavelmente está familiarizado) em um projeto, ele vem automaticamente com um recurso chamado hooks.

Se você for até a raiz de um projeto inicializado com Git e digitar:

ls .git/hooks
Enter fullscreen mode Exit fullscreen mode

Você verá uma lista de ganchos de exemplo, como pre-push, pre-rebase, pre-commit e assim por diante. Esta é uma maneira de escrevermos algum código de plugin para executar alguma lógica antes de realizar a ação do Git.

Se quisermos garantir que seu código foi devidamente lintado e formatado, antes de alguém criar um commit usando o comando git commit, poderíamos escrever um hook Git de pre-commit.

Escrever isso manualmente provavelmente não seria divertido. Também seria um desafio distribuir e garantir que os hooks fossem instalados nas máquinas de outros desenvolvedores.

Esses são alguns dos desafios que o Husky pretende resolver.

Com o Husky, podemos garantir que, para um novo desenvolvedor trabalhando em nossa base de código (usando pelo menos o Node versão 10):

  • Hooks são criados localmente
  • Hooks são executados quando o comando Git é chamado
  • Aplicar uma regra que define como alguém pode contribuir para o projeto

Vamos configurá-lo.

Instalando Husky

Para instalar o Husky, execute:

npm install husky --save-dev
Enter fullscreen mode Exit fullscreen mode

Configurando Husky

Para configurar o Husky, na raiz do nosso projeto no package.json, adicione a seguinte chave husky:

{
  "husky": {
    "hooks": {
      "pre-commit": "", // seu comando vai aqui
      "pre-push": "", // seu comando vai aqui
      "...": "..."
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Quando executamos o comando git commit ou git push, o respectivo hook executará o script que fornecemos em nosso package.json.

Fluxo de trabalho de exemplo

Seguindo os exemplos dos artigos anteriores, se configurarmos o ESLint e Prettier, sugiro utilizar dois scripts:


{
  "scripts": {
    "prettier-format": "prettier --config .prettierrc 'src/**/*.ts' --write",
    "lint": "eslint . --ext .ts",
    ...
  },
  "husky": {
    "hooks": {
      "pre-commit": "npm run prettier-format && npm run lint"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Inclua esses scripts no objeto scripts em seu package.json. E execute prettier-format e depois lint com um hook pre-commit.

Isso garantirá que você não possa completar um commit sem que seu código seja formatado de acordo com as convenções do seu time.

Exemplo - Bloqueando um commit

Eu gosto de usar o pacote no-loops como exemplo. Esta convenção não permite aos desenvolvedores usar for loops, ao invés disso, sugere que usamos funções de utilidade do Array como forEach, map e afins.

Adicionando o plug-in e sua regra ao .eslintrc:

{
  "root": true,
  "parser": "@typescript-eslint/parser",
  "plugins": [
    "@typescript-eslint",
    "no-loops",
    "prettier"
  ],
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier"
  ],
  "rules": {
    "no-loops/no-loops": 2, // 2 singifica "retornar um errro"
    "no-console": 1,
    "prettier/prettier": 2
  }
}
Enter fullscreen mode Exit fullscreen mode

E vamos colocar um for loop no código-fonte:

console.log('Hello world!');

for (let i = 0; i < 12; i++) {
  console.log(i);
}
Enter fullscreen mode Exit fullscreen mode

E ao tentar commitar, veremos um código de saída diferente de zero, o que, como sabemos, significa que ocorreu um erro:

simple-typescript-starter git:(prettier) ✗ git commit -m "Test commit"
husky > pre-commit (node v10.10.0)

> typescript-starter@1.0.0 prettier-format simple-typescript-starter
> prettier --config .prettierrc 'src/**/*.ts' --write

src/index.ts 191ms

> typescript-starter@1.0.0 lint /simple-typescript-starter
> eslint . --ext .ts


/simple-typescript-starter/src/index.ts
  1:1  warning  Unexpected console statement  no-console
  3:1  error    loops are not allowed         no-loops/no-loops
  4:3  warning  Unexpected console statement  no-console

✖ 3 problems (1 error, 2 warnings)
Enter fullscreen mode Exit fullscreen mode

E aí está!

Outras considerações

Se você perceber que o lint está demorando muito, verifique este pacote, lint-staged. Ele executa o linter, mas apenas nos arquivos que estão em git stage (arquivos que você está pronto para commitar). Isso me foi sugerido por @glambertmtl. Obrigado!

Créditos

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (0)

Cloudinary image

Optimize, customize, deliver, manage and analyze your images.

Remove background in all your web images at the same time, use outpainting to expand images with matching content, remove objects via open-set object detection and fill, recolor, crop, resize... Discover these and hundreds more ways to manage your web images and videos on a scale.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay