2010-11-16 12 views
77

Me gustaría ejecutar una unidad de pruebas antes de cada git push y si las pruebas fallan, cancele el push, pero no puedo encontrar el pre-push hook, hay pre-commit y pre-commit rebase soloGit pre-push hooks

Respuesta

20

Prefiero ejecutar la prueba en un pre-commit-hook. Porque el cambio ya está registrado al comprometerse. Push and pull solo intercambia información sobre cambios ya registrados. Si una prueba falla, ya tendría una revisión "rota" en su repositorio. Ya sea que lo estés presionando o no.

+112

Generalmente estoy de acuerdo, aunque si tienes el hábito de hacer un montón de compromisos incrementales para aplastar más tarde, y el conjunto de pruebas es grande, esto podría ser poco práctico. – Cascabel

+0

Ya veo. Así que sugeriría que las pruebas se ejecuten antes de fusionarse con la rama principal, pero tampoco hay un enlace previo a la fusión. Sin embargo, hay un gancho de "actualización" que se puede usar para evitar la actualización de una referencia en el repositorio remoto: "Justo antes de actualizar la referencia en el repositorio remoto, se invoca el enlace de actualización. Su estado de salida determina el éxito o el fracaso de la referencia. . actualización el gancho se ejecuta una vez para cada árbitro que actualizarse, y toma tres parámetros: el nombre de la ref siendo actualizada, el antiguo nombre de objeto almacenados en el árbitro, y el nuevo objectname para ser almacenados en el árbitro." – ordnungswidrig

+0

Decidí hacer la variante @ordnungswidrig - solo use el enlace de precompilación, causa de revisiones "rotas". Aquí está mi variante (pruebas php + phpUntit):

#!/bin/sh /usr/bin/php /srv/www/wf/tests/run.php /srv/www/wf/tests > /tmp/result if grep 'OK' /tmp/result then exit 0 else echo 'Your tests is failed, you cannot commit' exit 1 fi 
sheepwalker

13

Si está utilizando la línea de comandos, la forma más sencilla de hacerlo es escribir un guión de inserción que ejecute las pruebas de su unidad y, si lo logran, completa el impulso.

Editar

A partir de 1.8.2 git esta respuesta no está actualizado. Ver la respuesta de manojlds arriba.

+0

es lo que no significa utilizar ganchos en ¿todas? simplemente reemplace "git pull" con, por ejemplo, "git uinttestspull"? eso no es exactamente lo que necesito – sheepwalker

+1

@sheepwalker: s/pull/push /, y use un alias para hacerlo agradable y corto. – Cascabel

+0

@sheepwalker Sí, eso no es exactamente lo que pediste, pero como dijo @calmh, no hay ganchos pre-push. – kubi

7

No tiene gancho, porque un empuje no es una operación que modifica su repositorio.

Sin embargo, puede hacer las comprobaciones en el lado de recepción, en el gancho post-receive. Ahí es donde generalmente rechazarías un empujón entrante. Ejecutar pruebas unitarias puede ser un poco intensivo en un anzuelo, pero eso depende de usted.

5

Para el registro, hay un patch to Git 1.6 that adds a pre-push hook. No sé si funciona en contra de 1.7.

En lugar de meterse con eso, podría ejecutar el script push como se recomienda @kubi. También puede convertirlo en una tarea de Rake para que esté en su repositorio. ruby-git podría ayudar con esto. Si comprueba el repositorio objetivo, puede ejecutar pruebas solo cuando avance al repositorio de producción.

Finalmente, podría ejecutar sus pruebas en su gancho pre-commit pero verifique para qué rama se está comprometiendo. Entonces podría tener una, por ejemplo, una sucursal production que requiere que todas las pruebas pasen antes de aceptar una confirmación, pero su master no le importa. limerick_rake puede ser útil en ese escenario.

+0

gracias, en realidad ya he elegido la última variante (Finalmente, podrías ejecutar tus pruebas en tu gancho precompromiso ...) – sheepwalker

155

Git obtuvo el gancho pre-push en la versión 1.8.2.

Muestra pre-push guión: https://github.com/git/git/blob/87c86dd14abe8db7d00b0df5661ef8cf147a72a3/templates/hooks--pre-push.sample

notas de la versión 1.8.2 que hablan sobre el nuevo pre-push gancho: https://github.com/git/git/blob/master/Documentation/RelNotes/1.8.2.txt

+1

Hola amigo ... Gracias .. :) –

+0

@manojlds ¿sabes qué es lo que este gancho diseñó? para ser utilizado? Me gustaría utilizarlo para enviar mis archivos binarios a mis clientes cuando se dirijan a una sucursal específica (es decir, compilar la versión nocturna y cargarla con curl, antes de presionar). El problema es que lleva un tiempo construir y cargar, y el remoto cierra la conexión. Así que termino con mi binario construido y cargado a clientes pero no empujado a un repositorio, porque el repositorio remoto cierra la conexión. ¿Alguna idea de cómo solucionar esto? O tal vez es una mala idea en su raíz. – igrek

+0

@igrek ¿Encontró una solución para el problema de cierre de la conexión? –

17

Git consiguió el gancho pre-impulso en la liberación 1.8.2.

Los ganchos de pre-empuje son los que necesitaba junto con los ganchos pre-commit. Además de proteger una sucursal, también pueden proporcionar seguridad adicional combinada con ganchos de precompromiso.

Y para un ejemplo de cómo usar (tomada y adoptada y mejorada, a partir this nice entry)

ejemplo simple para acceder a vagabundo, las pruebas realizadas y luego empujar

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

Como se puede ver el ejemplo usa una rama protegida, sujeto del gancho de pre-push.

0

El script linked by the highly-voted answer muestra los parámetros, etc., para la pre-push hook ($1 es el nombre remoto, $2 URL) y cómo acceder a las confirmaciones (líneas read desde la entrada estándar tienen una estructura <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 
Cuestiones relacionadas