Implementar ganchos Git

Concluído

A priorização da qualidade do código no processo de desenvolvimento deve começar com o desenvolvimento do código local. É importante identificar oportunidades para essa prática antes mesmo de iniciar solicitações pull para detetar e corrigir possíveis problemas de qualidade do código.

Os ganchos Git oferecem uma ótima oportunidade. Eles servem como um mecanismo para executar scripts personalizados em resposta a eventos significativos dentro do ciclo de vida do Git, como confirmações, mesclagens e pushes. Os scripts, localizados dentro do diretório .git\hooks do repositório, fornecem flexibilidade praticamente ilimitada na automatização de tarefas de desenvolvimento de software e na aplicação de padrões de desenvolvimento.

Como implementar ganchos Git

Vamos começar explorando os ganchos Git do lado do cliente. Navegue até o diretório repo .git\hooks – você encontrará muitos arquivos com a extensão sample. Esta extensão não só indica o seu propósito, mas também efetivamente impede que sejam executados. Os nomes de arquivo designam as ações do Git que acionam sua execução depois que você remove a extensão sample.

Captura de ecrã de arquivos de ganchos do Git para automação.

Renomeie o ficheiro pre-commit sample para pre-commit. Como o nome do arquivo indica, o script que ele contém será executado sempre que você invocar a ação git commit. A confirmação só será efetuada se o script de pré-confirmação terminar com o valor de retorno 0.

No entanto, é importante notar que, por padrão, isso não funcionará como pretendido em nenhum dos sistemas operacionais Windows. O motivo comumente negligenciado para esse comportamento é a primeira linha do script:

#!/bin/sh

Em sistemas operacionais Linux, o #! prefix indica ao carregador de programas que o restante do arquivo contém um script a ser interpretado e /bin/sh é o caminho completo para o interpretador que deve ser usado.

Embora o Git para Windows suporte comandos Bash e shell scripts, ele não segue a mesma convenção ao designar caminhos do sistema de arquivos. Em vez disso, você precisa fornecer o caminho completo para o arquivo sh.exe, começando com a letra da unidade.

No entanto, há uma ressalva extra, que resulta do fato de que o Git para Windows por padrão é instalado no diretório C:\Program Files. Como esse diretório contém um espaço em seu nome, o caminho resultante para o arquivo sh.exe seria interpretado como dois caminhos separados, resultando em uma falha. Para evitá-lo, é necessário adicionar uma única barra invertida (\) na frente do espaço para servir como um caractere de escape. Efetivamente, ao usar a versão de 64 bits do Git para Windows, a primeira linha do script deve ter o seguinte formato:

#!C:/Program\ Files/Git/usr/bin/sh.exe

Como fazê-lo

Como você pode usar a funcionalidade recém-descoberta dos scripts de pré-confirmação do Git? Que tal impedir que você vaze segredos acidentalmente para o GitHub?

Vamos usar o hook do Git para analisar o código que está a ser submetido no seu repositório local em busca de palavras-chave específicas. Substitua o conteúdo do arquivo de shell de pré-confirmação pelo seguinte código:

#!C:/Program\ Files/Git/usr/bin/sh.exe
matches=$(git diff-index --patch HEAD | grep '^+' | grep -Pi 'password|secret')
if [ ! -z "$matches" ]
then
  cat <<\EOT
Error: Words from the blocked list were present in the diff:
EOT
echo $matches
exit 1
fi

Este exemplo destina-se a ilustrar o conceito em vez de uma solução completa, de modo que a lista de palavras-chave é intencionalmente trivial. Usando expressões regulares, você pode estender significativamente seu escopo e flexibilidade. Você também tem a opção de referenciar um arquivo externo, o que simplificaria consideravelmente a manutenção contínua.

Como funciona

Uma vez acionado, o script de pré-confirmação usa os comandos git diff e grep para identificar palavras-chave ou padrões dentro das alterações incrementais no código a serem confirmadas. Se alguma correspondência for detetada, o script gerará uma mensagem de erro e bloqueará o processo de confirmação.

Ainda há mais:

Outros casos de uso comuns de scripts de gancho de pré-confirmação incluem formatação de código, forro ou execução de testes personalizados para garantir que a confirmação siga os padrões do projeto. Prepare-commit-msg é executado antes que o editor de mensagens de confirmação seja iniciado. Ele permite a geração dinâmica de mensagens de confirmação para impor convenções de nomenclatura, como o uso de prefixos designados (por exemplo, feat: para recursos ou fix: para correções de bugs).

Por exemplo, o script prepare-commit-msg a seguir precede automaticamente o nome da ramificação atual à mensagem de confirmação ao criar uma nova confirmação. Ele modifica o arquivo de mensagem de confirmação ($1) adicionando o nome da ramificação seguido por dois pontos e espaço no início do arquivo.

#!C:/Program\ Files/Git/usr/bin/sh.exe
# Get the current branch name
branch_name=$(git branch --show-current)
# Check if the commit message file exists
if [[ -f "$1" ]]; then
  # Prepend the branch name to the commit message
  sed -i "1s/^/$branch_name: /" "$1"
fi

Os scripts de pós-confirmação são executados após a conclusão de uma confirmação. Ele pode ser usado para disparar notificações ou gerar documentação.

Por exemplo, o script a seguir envia uma notificação por e-mail para um destinatário designado após cada confirmação. O script pode ser personalizado modificando o endereço de e-mail do destinatário, o servidor SMTP e o assunto e corpo do e-mail. Além disso, talvez seja necessário configurar seu sistema para enviar emails usando o cmdlet Send-MailMessage PowerShell ou usar um método diferente para enviar notificações, dependendo do seu ambiente e requisitos.

#!C:/Program\ Files/Git/usr/bin/sh.exe
# Set the recipient email address
$recipient="your@email.com"
# Set the subject of the email
$subject="Git Commit Notification"
# Set the body of the email
$body="A new commit has been made to the repository."
# Send the email notification
Send-MailMessage -To $recipient -Subject $subject -Body $body -SmtpServer "your.smtp.server"

Vale a pena notar que a pasta repo .git\hooks não está comprometida no controle do código-fonte. Você pode se perguntar se há uma maneira de compartilhar os scripts que você desenvolveu com outro membro da sua equipe de desenvolvimento. A boa notícia é que, a partir da versão 2.9 do Git, podes mapear hooks do Git para uma pasta que pode ser adicionada ao controlo de código-fonte. Você pode fazer isso atualizando a configuração de definições globais para seu repositório Git:

Git config --global core.hooksPath '~/.githooks'

Se você precisar substituir os ganchos do Git que configurou no lado do cliente, poderá fazê-lo usando a opção no-verify:

Git commit --no-verify

Server-Side Ganchos

Enquanto os ganchos Git do lado do cliente oferecem recursos robustos para aprimorar o fluxo de trabalho de desenvolvimento, o Azure Repos também fornece ganchos do lado do servidor para aumentar ainda mais o processo de desenvolvimento, incluindo suporte para a criação de solicitações pull. Para obter mais informações, consulte Azure Repos Service hooks events reference.