Implementare hook Git

Completato

Dare priorità alla qualità del codice nel processo di sviluppo inizia con lo sviluppo di codice locale. È importante identificare le eventuali opportunità per mettere in atto questa pratica, anche prima di avviare le richieste pull per rilevare e correggere potenziali problemi di qualità del codice.

Gli hook Git offrono un'ottima opportunità. Fungono da meccanismo per l'esecuzione di script personalizzati in risposta a eventi significativi all'interno del ciclo di vita Git, ad esempio commit, merge e push. Gli script, che si trovano all'interno della directory .git\hooks del repository, offrono una flessibilità praticamente illimitata per automatizzare le attività di sviluppo del software e l'applicazione degli standard di sviluppo.

Come implementare hook Git

Si inizierà ora ad esplorare gli hook Git lato client. Passare alla directory repository .git\hooks. Sono disponibili molti file con l'estensione sample. Questa estensione non solo ne indica lo scopo, ma ne impedisce anche l'esecuzione. I nomi dei file designano le azioni Git che attivano la loro esecuzione dopo aver rimosso l'estensione sample.

Screenshot dei file di hook Git per l'automazione.

Rinominare il file di pre-commit sample per eseguire il pre-commit. Come indica il nome del file, lo script che contiene verrà eseguito ogni volta che si richiama l'azione di Git commit. Il commit segue solo se lo script di pre-commit viene chiuso con il valore restituito 0.

Tuttavia, è importante notare che, per impostazione predefinita, questo non funzionerà come previsto in nessun sistema operativo Windows. Il motivo, comunemente trascurato, per cui succede si trova nella prima riga dello script:

#!/bin/sh

Nei sistemi operativi Linux, il prefisso #! indica al caricatore del programma che il resto del file contiene uno script da interpretare e /bin/sh è il percorso completo dell'interprete che deve essere usato.

Anche se Git per Windows supporta i comandi e gli script della shell Bash, non segue la stessa convenzione durante la progettazione dei percorsi del file system. È invece necessario specificare il percorso completo del file sh.exe, a partire dalla lettera di unità.

Tuttavia, esiste una precisazione aggiuntiva da fare, che deriva dal fatto che Git per Windows per impostazione predefinita viene installato nella directory C:\Programmi. Poiché questa directory contiene uno spazio nel nome, il percorso risultante del file sh.exe verrebbe interpretato come due percorsi separati, causando un errore. Per evitarlo, è necessario aggiungere una singola barra rovesciata (\) davanti allo spazio per fungere da carattere di escape. In effetti, quando si usa la versione a 64 bit di Git per Windows, la prima riga dello script deve avere il formato seguente:

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

Procedura

Come è possibile usare la funzionalità appena scoperta degli script di pre-commit Git? Per sempio, per evitare di rilasciare segretti accidentalmente in GitHub

Si userà ora l'hook Git per analizzare il codice di cui è stato eseguito il commit nel repository locale per individuare parole chiave specifiche. Sostituire il contenuto del file della shell di pre-commit con il codice seguente:

#!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

Questo esempio è progettato per illustrare il concetto, piuttosto che una soluzione completa, quindi l'elenco di parole chiave è intenzionalmente semplice. Usando le espressioni regolari, è possibile estenderne significativamente l'ambito e la flessibilità. È anche possibile fare riferimento a un file esterno, semplificando notevolmente la manutenzione in corso.

Come funziona

Una volta richiamato, lo script hook di pre-commit usa i comandi git diff e grep per identificare parole chiave o modelli all'interno delle modifiche incrementali al codice di cui viene eseguito il commit. Se vengono rilevate corrispondenze, lo script genera un messaggio di errore e impedisce l'esecuzione del commit.

Altre opzioni disponibili:

Altri casi d'uso comuni degli script hook di pre-commit includono formattazione del codice, linting o esecuzione di test personalizzati per garantire che il commit sia conforme agli standard di progetto. Prepare-commit-msg viene eseguito prima dell'avvio dell'editor dei messaggi di commit. Consente la generazione dinamica di messaggi di commit per applicare convenzioni di denominazione, come l'uso di prefissi designati (ad es. feat: per funzionalità o fix: per la correzione di bug).

Ad esempio, lo script prepare-commit-msg seguente antepone automaticamente il nome del ramo corrente al messaggio di commit durante la creazione di un nuovo commit. Modifica il file di messaggio di commit ($1) aggiungendo il nome del ramo seguito da due punti e uno spazio all'inizio del file.

#!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

Gli script post-commit sono eseguiti al termine di un commit. Può essere usato per attivare le notifiche o generare documentazione.

Ad esempio, lo script seguente invia una notifica tramite posta elettronica a un destinatario designato dopo ogni commit. Lo script può essere personalizzato modificando l'indirizzo di posta elettronica del destinatario, il server SMTP e l'oggetto e il corpo del messaggio di posta elettronica. Inoltre, potrebbe essere necessario configurare il sistema affinché invii messaggi di posta elettronica usando il cmdlet PowerShell Send-MailMessage o usi un metodo diverso per inviare notifiche, a seconda dell'ambiente e dei requisiti.

#!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 la pena far notare che la cartella repository .git\hooks non è sottoposta a commit nel controllo del codice sorgente. Ci si potrebbe chiedere se esiste un modo per condividere gli script sviluppati con altri membri del team di sviluppo. La buona notizia è che, a partire dalla versione 2.9 di Git, è possibile eseguire il mapping degli hook Git a una cartella di cui si può eseguire il commit nel controllo del codice sorgente. A tale scopo, è possibile aggiornare la configurazione delle impostazioni globali per il repository Git:

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

Se è necessario sovrascrivere gli hook Git configurati sul lato client, è possibile usare l'opzione no-verify:

Git commit --no-verify

Hook lato server

Mentre gli hook Git sul lato client offrono funzionalità affidabili per migliorare il flusso di lavoro di sviluppo, Azure Repos fornisce anche hook sul lato server per aumentare ulteriormente il processo di sviluppo, incluso il supporto per la creazione di richieste pull. Per altre informazioni, vedere le informazioni di riferimento sugli eventi degli hook del servizio Azure Repos.