Pular para o conteúdo principal

Git Hooks: Elevando a Qualidade no Lado do Desenvolvedor

A rotina de trabalho de um desenvolvedor de software, em muitos pontos, não é diferente da de outras profissões. Temos processos, atividades repetitivas, ritos importantes a serem seguidos, principalmente em questões de compliance. Sendo assim, é sempre interessante quando somos apresentados a ferramentas que possuem a capacidade de assumir algumas das nossas responsabilidades, dentre elas, existem as Git Hooks.

Este guia serve como base para uma breve exploração sobre automatizar validações de aplicações em desenvolvimento diretamente na máquina do desenvolvedor. A fim de garantir um fluxo de trabalho mais limpo, coerente com os processos internos, simplificado e seguro.


1. O que são Git Hooks?

Git Hooks são scripts que o Git executa automaticamente em pontos estratégicos do ciclo de vida do desenvolvimento. Eles são divididos em dois grupos:

  • Client-Side: Executados na máquina local (nosso foco neste artigo).
  • Server-Side: Executados no servidor (recebimento de pushes).
Localização

Todo repositório Git possui uma pasta oculta em .git/hooks contendo exemplos de scripts que podem ser ativados ao remover a extensão .sample. Apesar de os executáveis ficarem nesse diretório por padrão, podemos alterá-lo via configuração do git, como veremos logo mais.

Atenção

Lembrando que a pasta .git não sofre influência de versionamento. Logo, isso pode gerar uma certa dificuldade pra atualizar as hooks sempre que necessário. Trataremos disso mais ao final.

2. Requisitos

  1. Git instalado em sua máquina
  2. Clonar o repositório para estudos: git-hooks-client-side
  3. Suporte de alguma linguagem executável como script de linha de comando: bash, sh, php, python...
  4. Dar permissão de execução para os scripts que veremos à frente. Exemplo no linux: sudo chmod +x <caminho_do_arquivo>
  5. npm instalado para rodar nossa rotina de testes unitários

3. Implementações práticas

Vejamos abaixo dois exemplos simples de hooks muito úteis para o trabalho diário.

3.1 Padronização de mensagens (prepare-commit-msg)

Este hook é acionado antes da mensagem de commit ser salva nos arquivos de gerenciamento do git. Ele permite que enxerguemos a mensagem, façamos alguma tratativa e, caso necessário, abortemos o commit.

Criaremos um novo script para ser executado em linux. Ele nos ajudará a validar se a mensagem segue o padrão convential commits. Ex.: fix: Mensagem de commit

Caminho: .git/hooks/prepare-commit-msg

#!/bin/bash

# Arquivo temporário que armazena a mensagem
COMMIT_MSG_FILE=$1

# Regex para validar o padrão: TIPO: Descrição
# Tipos permitidos: feat, fix, task, chore
PATTERN="^(feat|fix|task|chore): .+"

COMMIT_MSG=$(cat $COMMIT_MSG_FILE)

if [[ ! $COMMIT_MSG =~ $PATTERN ]]; then
echo -e "\n\033[31m❌ ERRO: Mensagem de commit inválida!\033[0m"
echo "-------------------------------------------------------"
echo "Sua mensagem deve seguir o padrão: \"TIPO: Descrição\""
echo "Exemplo: \"feat: Adicionando integração com API de pagamentos\""
echo "-------------------------------------------------------"
exit 1
fi

3.2 Prevenção contra código problemático no push (pre-push)

Como o nome autoexplicativo já nos sugere. Essa rotina é chamada antes que o evento de push ocorra. Nesta etapada podemos criar uma série de critérios para garantir um determinado nível de qualidade ao subirmos um código no repositório remoto.

No exemplo em questão, nosso script chamará os goals de teste de uma aplicação em node js, caso falhem os testes, o push será abortado.

Caminho: .git/hooks/pre-push

#!/bin/bash

echo "🔍 Verificando integridade do código antes do push..."

# Substitua pelo comando de teste do seu projeto (ex: npm test, pytest, go test)
npm test

RESULT=$?

if [ $RESULT -ne 0 ]; then
echo -e "\n\033[31m🚨 PUSH CANCELADO!\033[0m"
echo "Os testes unitários falharam. Corrija-os antes de tentar subir o código."
exit 1
fi

echo -e "\033[32m✅ Testes aprovados. Enviando para o remoto...\033[0m"
exit 0

4. Compartilhando com o time

Como dito mais cedo, infelizmente a pasta .git/hooks não é versionada, sendo assim, precisamos de algumas estratégias para evitar a péssima prática de ficar compartilhando versões de scripts sem controle entre o time de forma privada. Para isso, vamos estudar algumas opções

Opção A: Configuração nativa

Podemos criar uma pasta qualquer na raiz do nosso projeto. No repositório fornecido ao início do artigo temos a pasta oculta .githooks, ela contém os dois scripts que abordamos mais cedo.

Para selecioná-la como pasta padrão, basta executarmos o comando git config core.hooksPath .githooks. A partir disso, teremos scripts versionados dentro do projeto.

Opção B: Repositorio universal

É possível criar um repositório universal para as hooks, onde podemos, por exemplo, separá-las por tipo de projeto. Tais como:

minhasHooks/
-- java/
---- prepare-commit-msg
-- node/
---- pre-push

Tendo isso em mente, podemos criar links simbólicos na nossa aplicação, nos fazendo utilizar esses scripts de forma centalizada.

Opção C: Ferramentas

Há várias soluções para gerenciamento de git hooks, uma delas, construída em node js, é o Husky. Para entender seu funcionamento, acompanhe a documentação aqui.

5. Conclusão

  1. Entendemos hoje o básico do funcionamento de uma git hook do lado cliente.
  2. Aprendemos que podemos automatizar algumas ações em cada ciclo de vida do nosso código, economizando tempo com tarefas repetitivas.
  3. A gestão de código é mais segura quando criamos salvaguardas que nos impedem de fazer besteira.