Como usar o husky para garantir a qualidade do seu código
O que é o Husky?
O próprio Husky se denomina como:
Ultra-fast modern native git hooks
Eu particularmente acho que isso é muito abrangente e não explica muita coisa para quem não entende muito de Git. O Husky é basicamente uma ferramenta que te permite rodar scripts automaticamente (scripts npm de teste e lint) em ações específicas do Git (commit, push, etc).
Por que usar o Husky?
Dentro do desenvolvimento de software, é muito importante manter padrões, mesmo que esses padrões sejam somente entre o seu time, garantindo que esse código seja minimamente manutenível ao longo prazo. Como é uma ferramenta de scripts com base em hooks Git, o Husky funciona como um workflow de CI básico que roda na sua máquina. Permitindo que você automatize ações que vão desde lintar seu código antes de commitar o mesmo ou limitar quem pode dar push na master/main de um projeto.
Como funciona a base?
Você precisa adicionar o pacote do Husky ao seu projeto JS.
pnpm add --save-dev husky
Rode o comando Husky init para ele criar uma pasta .husky
e adiciona um script prepare
no package.json
para ele rodar os scripts corretamente em qualquer máquina.
pnpm exec husky init && pnpm prepare
Na pasta .husky
é onde você irá colocar os arquivos com os nomes dos hooks que deseja ativar.
touch .husky/pre-commit
Dentro desse arquivo, se você e seu time usarem Linux, podem escrever um shell script padrão para rodar no seu projeto e toda vez que o hook do nome do arquivo for ativado, ele irá ser ativado.
# .husky/pre-commit
echo "Commitando aqui pae"
Caso queira testar um script sem ele acionar a ação do Git hook, é só adicionar exit 1
no final do script.
# .husky/pre-commit
echo "Commitando aqui pae"
exit 1
Quando você escrever git commit
, ele executará o comando, mas antes de commitar, ele aborta a execução do comando e só executa o script.
Caso queira parar de executar alguma ação específica do Husky, é só passar a flag -n
no comando que tem a mesma. Para ser mais efetivo em comando que não tem essa flag, podemos definir a env HUSKY
como 0
.
# Caso comando tenha suporte a flag -n
git commit -m "Commit sem triggar husky" -n
# Caso não tenha suporte a flag -n
HUSKY=0 git ...
Essa env pode ser adicionada em imagens Docker ou servidores de CI passando esse valor dentro de Env
na imagem. Isso é principalmente útil caso sua imagem Docker faça alguma ação com Git e você queira deixar o comando sem ações que não sejam as que você definiu ou você tenha alguma ação em um GitHub Actions da vida que execute algum commit no seu repo.
# .github/workflows/ci.yml
env:
HUSKY: 0
Casos de uso
Onde podemos usar o Husky para facilitar nossa vida com o Git? Aqui irei abordar 2 cenários: um bem comum e outro que pode servir de ajuda para quem colabora com mais de uma pessoa em um repo privado no GitHub.
1. Rodar Prettier e Linter em arquivos que foram recentemente editados
Rodar Prettier e Linter nos seus arquivos deve ser algo periodicamente feito, a fim de tratar erros que fogem das regras do projeto e que serão barrados em um eventual build. Não queremos descobrir e corrigir erros na hora do deploy.
- Instalar o
lint-staged
- Adicionar a configuração de quais scripts vão rodar no
lint-staged
no seupackage.json
- No hook da sua preferência (recomendo o
pre-commit
), defina o comando para executar olint-staged
2. Travando commits na main em projetos privados
Sempre que iniciamos um projeto, é importante definirmos regras de proteção para nossa branch master/main. Mas em alguns casos, em repos privados, não conseguimos fazer isso sem um plano pro do GitHub. Nesses casos, uma automação com script vai te ajudar a deixar sua branch segura (na maior parte do tempo).
- Crie um arquivo
pre-push
na pasta.husky
e cole o seguinte script, adaptando para seu caso:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
BRANCH_NAME=$(git symbolic-ref --short HEAD)
GIT_USER=$(git config user.name)
AUTHORIZED_USER="Pilu Vitu" # Coloque exatamente seu git user.name
# Verifica se está na branch master/main
if [ "$BRANCH_NAME" = "master" ]; then
if [ "$GIT_USER" != "$AUTHORIZED_USER" ]; then
echo "Você não tem permissão para commitar diretamente na branch '$BRANCH_NAME'."
echo "Usuário atual: $GIT_USER | Usuário autorizado: $AUTHORIZED_USER"
exit 1
fi
fi
exit 0
- Mude o último
exit
para1
e teste. Se tudo tiver dado certo, altere oexit
para0
novamente e commite.
Considerações Finais
Dê preferência a executar comandos rápidos em fluxos de commit e push. É normal as pessoas terem resistência a usar Husky, mas boa parte é por erro na configuração e escolha errada de quais scripts rodar. Comandos que rodam testes são mais efetivos em push do que em commit. Fique atento a isso quando for implementar na sua empresa ou projeto.
O Husky não substitui uma pipeline rodando nativamente no seu provedor Git, mas já ajuda em projetos de escopo menor e como uma alternativa para economizar minutos de run. Analise os prós e contras para cada script que tiver no seu projeto. Às vezes, não compensa integrar em determinados cenários, como testes de integração com TestContainers e testes em front com Playwright.