Vorrei eseguire un test unitario prima di ogni push git e se i test falliscono, annulla il push, ma non riesco nemmeno a trovare l'hook pre-push, ci sono solo pre-commit e pre-rebase.
Vorrei eseguire un test unitario prima di ogni push git e se i test falliscono, annulla il push, ma non riesco nemmeno a trovare l'hook pre-push, ci sono solo pre-commit e pre-rebase.
Risposte:
Preferisco eseguire il test in un pre-commit-hook. Perché la modifica è già registrata al momento del commit. Push e pull scambiano solo informazioni su modifiche già registrate. Se un test fallisce, avresti già una revisione "non funzionante" nel tuo repository. Che tu lo stia spingendo o meno.
Git ha ottenuto il file pre-push
gancio nel 1.8.2
rilascio.
Campione pre-push
Script di : https://github.com/git/git/blob/87c86dd14abe8db7d00b0df5661ef8cf147a72a3/templates/hooks--pre-push.sample
Note sulla versione 1.8.2 che parlano del nuovo hook pre-push: https://github.com/git/git/blob/master/Documentation/RelNotes/1.8.2.txt
Git ha ottenuto il pre-push hook nella versione 1.8.2.
Gli hook pre-push sono ciò di cui avevo bisogno insieme agli hook pre-commit. Oltre a proteggere un ramo, possono anche fornire una sicurezza aggiuntiva combinata con hook pre-commit.
E per un esempio sull'utilizzo (ripreso e adottato e valorizzato da questa simpatica voce )
Semplice esempio per accedere a vagrant, eseguire test e quindi premere
#!/bin/bash
# Run the following command in the root of your project to install this pre-push hook:
# cp git-hooks/pre-push .git/hooks/pre-push; chmod 700 .git/hooks/pre-push
CMD="ssh vagrant@192.168.33.10 -i ~/.vagrant.d/insecure_private_key 'cd /vagrant/tests; /vagrant/vendor/bin/phpunit'"
protected_branch='master'
# Check if we actually have commits to push
commits=`git log @{u}..`
if [ -z "$commits" ]; then
exit 0
fi
current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
if [[ $current_branch = $protected_branch ]]; then
eval $CMD
RESULT=$?
if [ $RESULT -ne 0 ]; then
echo "failed $CMD"
exit 1
fi
fi
exit 0
Come puoi vedere l'esempio utilizza un ramo protetto, oggetto del pre-push hook.
Se stai utilizzando la riga di comando, il modo più semplice per farlo è scrivere uno script push che esegua i tuoi unit test e, se riescono, completa il push.
modificare
A partire da git 1.8.2 questa risposta è obsoleta. Vedi la risposta di manojlds sopra.
Non c'è un hook per questo, perché un push non è un'operazione che modifica il tuo repository.
Puoi fare i controlli sul lato ricevente, però, nel post-receive
gancio. È qui che di solito rifiuteresti un push in arrivo. L'esecuzione di unit test potrebbe essere un po 'impegnativa da fare in un gancio, ma dipende da te.
Per la cronaca, c'è una patch a Git 1.6 che aggiunge un hook pre-push . Non so se funziona contro 1.7.
Invece di scherzare con questo, potresti eseguire script push come consigliato da @kubi. Puoi anche renderlo un'attività Rake, quindi è nel tuo repository. ruby-git potrebbe aiutare con questo. Se controlli il repository di destinazione, puoi eseguire i test solo quando esegui il push nel repository di produzione.
Infine, potresti eseguire i tuoi test nel tuo pre-commit
hook ma controllare per quale ramo è stato eseguito il commit. Quindi potresti avere, diciamo, un production
ramo che richiede il superamento di tutti i test prima di accettare un commit ma a te master
non interessa. limerick_rake può essere utile in quello scenario.
Lo script collegato dalla risposta altamente votata mostra i parametri ecc. pre-push
All'hook ( $1
è il nome remoto, $2
URL) e come accedere ai commit (le righe read
dallo stdin hanno una struttura <local ref> <local sha1> <remote ref> <remote sha1>
)
#!/bin/sh
# An example hook script to verify what is about to be pushed. Called by "git
# push" after it has checked the remote status, but before anything has been
# pushed. If this script exits with a non-zero status nothing will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
# <local ref> <local sha1> <remote ref> <remote sha1>
#
# This sample shows how to prevent push of commits where the log message starts
# with "WIP" (work in progress).
remote="$1"
url="$2"
z40=0000000000000000000000000000000000000000
while read local_ref local_sha remote_ref remote_sha
do
if [ "$local_sha" = $z40 ]
then
# Handle delete
:
else
if [ "$remote_sha" = $z40 ]
then
# New branch, examine all commits
range="$local_sha"
else
# Update to existing branch, examine new commits
range="$remote_sha..$local_sha"
fi
# Check for WIP commit
commit=`git rev-list -n 1 --grep '^WIP' "$range"`
if [ -n "$commit" ]
then
echo >&2 "Found WIP commit in $local_ref, not pushing"
exit 1
fi
fi
done
exit 0