Developing Frogtek

El blog del Departamento de Tecnología

Bloqueo de SVN en caso de build fallida

Hace poco tuvimos una agradable visita aquí en Frogtek. Una de las muchas aportaciones de Emma fue hacernos replantear nuestro sistema de lanzamiento de builds en Jenkins, pasando de uno más pesado en recursos a otro más eficiente. A raíz de dicho cambio hemos aprovechado y mejorado el procedimiento de bloqueo que tenemos configurado en Jenkins y la forma en la que lo realizamos. Vamos a explicarlo para que nos ayudéis a mejorarlo todavía mas.

En sí, el procedimiento consiste en no permitir commits al servidor SVN si hay una build rota. Excepto al usuario que haya provocado dicha rotura. De esta forma nos aseguramos de varias cosas:

  • No se avanza en el desarrollo si el código subido no es de una calidad mínima, pasa los test y se construye correctamente.
  • Los desarrolladores se hacen responsables de los problemas que ellos han generado y los arreglan.
  • Cuando existe un problema en una parte del proyecto, y dicho problema tarda en resolverse, todo el equipo se preocupa por saber qué pasa y ayudar a resolverlo para poder seguir avanzando.


Para conseguir este funcionamiento usamos dos scripts. Uno, invocado al comienzo y finalización de cada proyecto en Jenkins, encargado de realizar el bloqueo en sí. Y otro, invocado desde el hook de SVN de pre-commit, que comprueba que no haya nadie bloqueando el servidor en el momento del commit.

El primero de ellos:

#!/bin/bash
#
# Script that creates and fill the data for the lock or empty the files
# in order to unblock jenkins
#
case $# in
	3)
		LOCK=$1
		AUTHOR=$2
		PROJECT=$3
	;;
	*) # Error 
	 	echo  "Usage: $0 [lock|unlock] AUTHOR PROJECT_NAME" >&2
		exit 1
	;;
esac

AUTHORFILE=/frogtek/locks/$PROJECT

if [ "unlock" = "$LOCK" ]; then
	cat /dev/null > $AUTHORFILE
	exit 0;	
else
	echo $AUTHOR > $AUTHORFILE	
	exit 0;
fi

Simplemente escribe el autor del bloqueo en un archivo por proyecto, un especie de lock. Al inicio de cualquier trabajo de Jenkins invocamos al script con el párametro lock el nombre del proyecto y el autor. Así :

lockOrUnlockJenkins.sh lock `svnlook author REPOS_PATH` ${JOB_NAME}

Y como último paso del mismo trabajo, hacemos un unlock:

lockOrUnlockJenkins.sh unlock jenkins ${JOB_NAME}

El segundo script cumple tres funciones:

  • Comprobar que el mensaje que se envía con el commit no está vacío.
  • Comprobar que tiene una longitud de entre 10 y 3000 caracteres.
  • Asegurarse de que no se permiten commits si hay builds rotas en Jenkins, excepto aquellas del causante de la rotura.

A continuación podemos ver el script que nos permite esto:

#!/bin/bash
REPOS="$1"
TXN="$2"
SVNLOOK=/usr/local/bin/svnlook

PROJECTS=( PROJECT1 PROJECT2 PROJECT3 PROJECT4 )

AUTHOR=`$SVNLOOK author -t $TXN $REPOS`
HUDSONUSER="hudson"

NUM_CHARS=`$SVNLOOK log -t $TXN $REPOS | wc -c`

COMMENT=`$SVNLOOK log -t $TXN $REPOS`

if [ "$COMMENT" = "" ]; then
  echo "" 1>&2
  echo "*** Your commit has been blocked because you did not give any log message or your log message was too short." 1>&2
  echo "Please write a log message describing the purpose of your changes and then try committing again." 1>&2
  exit 1
else
  if [ "$NUM_CHARS" -lt 10 -o "$NUM_CHARS" -gt 300 ]; then
  	echo "" 1>&2
  	echo "*** Your commit has been blocked because you give a log message very short or very large.(10-300 characters)" 1>&2
  	echo "Please write a log message describing the purpose of your changes and then try committing again." 1>&2
  	exit 1
  fi		

  for i in 0 1 2 3
  do
	lock=`cat /frogtek/locks/${PROJECTS[i]}`
        if [ "$lock" != "" -a  "$lock" != $AUTHOR ]; then
 		echo "SVN LOCKED BY COMPILATION FAILED IN " ${PROJECTS[i]} " COMMITED BY "$lock 1>&2
      		exit 1
      	fi
  done
  exit 0
fi

Como veis nada muy complicado de configurar. ¿Qué os parece? ¿Cómo lo mejoraríais? ¿Utilizáis algo parecido?

2 Comentarios

  1. Mmmm… interesante. Aunque no tengo muy clara su utilidad. ¿Puedo hacer unas preguntas? Por si acaso, aqui van:

    ¿Por qué decidistéis tomar esta medida?
    ¿Rompiais mucho la build?
    ¿Romper significa que falle un test o solo que se ponga en rojo?
    ¿Estaba mucho tiempo la build rota?
    ¿Se observa algún cambio?

    Saludos.

  2. Julio García

    4 abril, 2011 at 10:50

    Buenas Julio te intento responder, dentro de mis posibilidades:

    ¿Por qué decidisteis tomar esta medida?
    No se cual fue la motivación para tomar esta medida, pues ya estaba implantada cuando yo llegue. De todas formas durante el tiempo que he estado aquí, he visto más de una situación donde ha sido útil.

    ¿Rompíais mucho la build?
    Lo mismo de la anterior aplica. Eso sí aún hoy en día seguimos rompiendo la build de vez en cuando. El hecho de que nadie pueda commitear si hay algo roto nos ayuda a que no se dejen pasar esos descuidos y se arreglen lo más rápido posible.

    ¿Romper significa que falle un test o solo que se ponga en rojo?
    Para nosotros ambos casos es romper la build.

    Intento que alguien que estuviera al principio te responda Julio para ver si aclaran más sobre las razones de implantación y su historia.

    A parte de eso unas preguntas para tí:
    ¿Que pegas le ves en si al procedimiento?
    ¿Lo cambiarías de alguna forma o modificarías?

    Saludos

Deja un comentario

Tu dirección de correo electrónico no será publicada.

*