web-dev-qa-db-fra.com

Crochets pré-Push Git

Je voudrais exécuter des tests unitaires avant chaque Git Push et si les tests échouent, annulez le Push, mais je n'arrive même pas à trouver le hook pré-Push. 

95
sheepwalker

Je préférerais exécuter le test avec un crochet de pré-validation. Parce que le changement est déjà enregistré lors de la validation. Poussez et tirez uniquement sur les informations d’échange concernant les modifications déjà enregistrées. Si un test échoue, vous avez déjà une révision "cassée" dans votre référentiel. Que vous le poussiez ou pas.

17
ordnungswidrig

Git a eu le hook pre-Push dans la version 1.8.2.

Exemple de script pre-Push: https://github.com/git/git/blob/87c86dd14abe8db7d00b0df5661ef8cf147a72a3/templates/hooks--pre-Push.sample

Notes de mise à jour 1.8.2 concernant le nouveau point d'ancrage pré-Push: https://github.com/git/git/blob/master/Documentation/RelNotes/1.8.2.txt

189
manojlds

Git a obtenu le crochet pré-Push dans la version 1.8.2.

Les crochets de pré-push sont ce dont j'avais besoin avec les crochets de pré-validation. Outre la protection d'une branche, ils peuvent également fournir une sécurité supplémentaire combinée à des hooks de pré-validation. 

Et pour un exemple sur la façon d'utiliser (pris et adopté et amélioré de cette entrée de Nice )

Exemple simple pour vous connecter à vagrant, exécuter des tests, puis Push

#!/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 [email protected] -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

Comme vous pouvez le voir, l'exemple utilise une branche protégée, sujet du hook pre-Push. 

19
Jimmy Kane

Si vous utilisez la ligne de commande, le moyen le plus simple consiste à écrire un script Push qui exécute vos tests unitaires et, s’ils réussissent, termine le Push.

Modifier

Depuis git 1.8.2, cette réponse est obsolète. Voir la réponse de manojlds ci-dessus.

13
kubi

Il n'y a pas de crochet pour cela, car un Push n'est pas une opération qui modifie votre référentiel. 

Vous pouvez toutefois effectuer les vérifications du côté destinataire, à l’aide du crochet post-receive. C’est là que vous rejetteriez généralement un Push entrant. Exécuter des tests unitaires peut être un peu intensif, mais c'est à vous de décider.

7
Jakob Borg

Pour mémoire, il y a un patch dans Git 1.6 qui ajoute un hook pré-Push . Je ne sais pas si cela fonctionne contre 1.7.

Plutôt que de jouer avec cela, vous pourriez exécuter un script Push comme @kubi recommandé. Vous pouvez également en faire une tâche Rake afin que ce soit dans votre référentiel. Ruby-git pourrait aider avec cela. Si vous vérifiez le référentiel cible, vous pouvez exécuter des tests uniquement lorsque vous appuyez sur le référentiel de production.

Enfin, vous pouvez exécuter vos tests dans votre hook pre-commit tout en vérifiant quelle branche est validée. Ensuite, vous pourriez avoir une branche, disons une production qui exige que tous les tests soient réussis avant d'accepter un commit, mais votre master s'en fiche. limerick_rake peut être utile dans ce scénario.

5
Turadg

Le script lié par la réponse hautement votée montre les paramètres, etc., au crochet pre-Push ($1 est le nom distant, $2 URL) et comment accéder aux commits (les lignes read de stdin ont la structure <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
0
serv-inc