Introducción
El uso de sistemas de control de versiones en proyectos de desarrollo de software permite principalmente a los desarrolladores trabajar en forma rápida, coordinada y a la vez algo despreocupada, pues les brinda muchas posibilidades de gestión de los archivos versionados. Son herramientas esenciales en todo proyecto de software y hoy por hoy existe una amplia variedad disponibles para su elección, subversion, git, bazaar y otras por mencionar solo algunas alternativas libres. Cual de ellas usar sera algo totalmente dependiente de nuestras necesidades especificas post análisis de las ventajas y desventajas provistas por cada una. Otro componente muy necesario durante la etapa de madurado de un proyecto de software son las herramientas conocidas como sistemas de seguimiento/traceo de errores/incidencias; estas permiten a los desarrolladores/testers reportar/documentar los distintos tipos de problemas/errores que se vayan descubriendo en el sistema, asi es que se generan reportes de incidencias o tickets, los que normalmente tienen asociados valores comunes tales como: una prioridad, un encargado, detalle del tipo de error, archivos adjuntos que brinden mas datos al reporte, un estado del reporte (incidencia abierta, asignada, cerrada, corregida, o algún estado personalizado, solo por decir algunas).
trac es una herramienta que combina un grupo funcionalidades bastante útiles que son un sistema de reporte de incidencias (o issues como lo llaman sus creadores), una wiki para generar en forma colaborativa la documentación, una visualización del avance del desarrollo por linea de tiempo, seguimiento del avance del proyecto por hitos/metas y una excelente combinación con subversion. trac esta desarrollada en lenguaje python y es distribuida con licencia GNU/GPL.
Al finalizar se tendrá un servidor de subversion funcionando via protocolo http, junto a trac como gestor de incidencias, wiki , etc… , también voy a configurar el repositorio svn para permitir gestionar los estados de los tickets de trac desde los commits realizados via subversion. Esta implementacion la realice en un sistema debian linux, con una versión de trac 0.11 (la actual es la 0.12, esta versión trae mejoras en particular la actualización de tickets vía commits varia un poco respecto de la 0.11.ya escribiré sobre ella mas adelante).
1. Empecemos con Subversion (svn)
Bueno, para empezar no nos olvidemos que lo principal es contar con un repositorio de subversion donde alojar nuestro proyecto de software. Asi que manos a la obra:
Crear un repositorio svn
Paquetes a instalar:
# apt-get install subversion
El repositorio va a estar ubicado en el path /ruta/svn y es importante que esa ruta este accesible por el usuario/grupo de apache. Ahora si, creo el repositorio subversion:
# svadmin create /ruta/svn/repositorio-proyecto1
y realizo la importación inicial de proyecto1:
# svn import /home/sources/proyecto1 file:///ruta/svn/repositorio-proyecto1
Donde en /home/sources/proyecto1 tengo la estructura del fuente del proyecto que quiero versionar, el cuarto parámetro del comando indica el repositorio donde se va a subir este código. Es importante ejecutar este comando como usuario root. Luego se debe asignar al repositorio el usuario/grupo con el cual se esta ejecutando el servidor web Apache2, en el caso de sistemas basados en debian este es www-data.
# chown www-data: -R /ruta/svn/repositorio-proyecto1
Si miramos este directorio veremos una serie de sub-directorios y archivos que conforman la estructura típica de un repositorio subversion, donde deberán prestar atención al directorio llamado hooks, al que volveremos luego mas adelante en esta guía.
2. Ahora a crear el entorno trac
Al crear un entorno trac generamos un directorio con una estructura de sub-directorios asociada a un entorno subversion.
Paquetes a instalar:
# apt-get install trac
Iniciamos el ambiente de trac, se nos solicitara algunos parámetros de configuración donde /ruta/trac/trac-entorno1 es la ruta donde se va a crear el entorno de trac.
# trac-admin /ruta/trac/trac-repositorio1 initenv Creating a new Trac environment at /ruta/trac/trac-repositorio1 Trac will first ask a few questions about your environment in order to initialize and prepare the project database. Please enter the name of your project. This name will be used in page titles and descriptions. Project Name [My Project]> Mi Proyecto de Prueba Please specify the connection string for the database to use. By default, a local SQLite database is created in the environment directory. It is also possible to use an already existing PostgreSQL database (check the Trac documentation for the exact connection string syntax). Database connection string [sqlite:db/trac.db]> <ENTER> Please specify the type of version control system, By default, it will be svn. If you don't want to use Trac with version control integration, choose the default here and don't specify a repository directory. in the next question. Repository type [svn]> <ENTER> Please specify the absolute path to the version control repository, or leave it blank to use Trac without a repository. You can also set the repository location later. Path to repository [/path/to/repos]> /ruta/svn/repositorio-proyecto1 Creating and Initializing Project Installing default wiki pages TracTickets imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracTickets TracNotification imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracNotification TracBrowser imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracBrowser InterTrac imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/InterTrac TracModWSGI imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracModWSGI TracImport imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracImport WikiFormatting imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/WikiFormatting TracSyntaxColoring imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracSyntaxColoring TracWorkflow imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracWorkflow TracIni imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracIni WikiPageNames imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/WikiPageNames TracNavigation imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracNavigation WikiDeletePage imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/WikiDeletePage SandBox imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/SandBox WikiMacros imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/WikiMacros TracRevisionLog imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracRevisionLog TracFineGrainedPermissions imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracFineGrainedPermissions TracStandalone imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracStandalone TracUpgrade imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracUpgrade TracQuery imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracQuery TracFastCgi imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracFastCgi TracEnvironment imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracEnvironment TitleIndex imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TitleIndex TracAdmin imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracAdmin InterWiki imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/InterWiki WikiRestructuredText imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/WikiRestructuredText TracReports imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracReports WikiProcessors imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/WikiProcessors TracChangeset imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracChangeset InterMapTxt imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/InterMapTxt TracAccessibility imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracAccessibility TracSearch imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracSearch TracWiki imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracWiki TracCgi imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracCgi TracInstall imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracInstall TracLinks imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracLinks TracInterfaceCustomization imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracInterfaceCustomization WikiHtml imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/WikiHtml PageTemplates imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/PageTemplates TracPermissions imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracPermissions TracUnicode imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracUnicode WikiRestructuredTextLinks imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/WikiRestructuredTextLinks TracTicketsCustomFields imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracTicketsCustomFields WikiStart imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/WikiStart TracRss imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracRss CamelCase imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/CamelCase TracGuide imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracGuide RecentChanges imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/RecentChanges TracPlugins imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracPlugins TracRoadmap imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracRoadmap WikiNewPage imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/WikiNewPage TracTimeline imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracTimeline TracModPython imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracModPython TracLogging imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracLogging TracBackup imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracBackup TracSupport imported from /usr/lib/python2.6/dist-packages/trac/wiki/default-pages/TracSupport Indexing repository [6] --------------------------------------------------------------------- Project environment for 'Mi Proyecto de Prueba' created. You may now configure the environment by editing the file: /ruta/trac/trac-repositorio1/conf/trac.ini If you'd like to take this new project environment for a test drive, try running the Trac standalone web server `tracd`: tracd --port 8000 /ruta/trac/trac-repositorio1 Then point your browser to http://localhost:8000/trac-repositorio1. There you can also browse the documentation for your installed version of Trac, including information on further setup (such as deploying Trac to a real web server). The latest documentation can also always be found on the project website: http://trac.edgewall.org/ Congratulations!
Luego de esto si necesitamos cambiar algunos de estos parámetros recordemos que podemos hacerlo modificando el archivo de configuración del ambiente trac generado, en nuestro caso en:
/ruta/trac/trac-repositorio1/conf/trac.ini
Siempre que queremos podremos modificar nuestro entorno generado con trac, mediante el comando:
# trac-admin /ruta/trac/trac-repositorio1 Welcome to trac-admin 0.11.7 Interactive Trac administration console. Copyright (c) 2003-2009 Edgewall Software Type: '?' or 'help' for help on commands. Trac [/ruta/trac/trac-repositorio1]>
que nos da acceso a una consola de administración desde donde se pueden gestionar muchos de los parámetros del entorno trac vía comandas propios. Un problema que se puede presentar es que les suceda como a mi que cambie de lugar del repositorio de subversion y por consiguiente el entorno trac empezó a tirar errores a pesar de haber realizado las modificaciones del nuevo path en trac.ini. Para ello desde la consola administrativa de trac y ejecutar el comando resync:
Trac [/ruta/trac/trac-repositorio1]> resync
3. Configuración de Apache2
Trac viene por defecto con su propio servidor web para gestionar los entornos creados que corre por defecto en el puerto 80. En mi caso en el servidor donde voy a usar trac voy a poner un apache con dominios virtuales en el mismo puerto. Instalo tanto el servidor web como la librería que me permite acceder a repositorios subversion desde apache y la que me permite gestionar trac desde apache via python. En mi caso particular voy a dedicar un subdominio interno asociado al repositorio por lo cual voy a crear un dominio virtual. Paquetes a instalar:
# apt-get install apache2 libapache2-svn libapache2-mod-python
Habilito los módulos necesarios en Apache, el modulo para reescritura de urls:
# a2enmod rewrite
y el modulo con soporte de python para apache, que es necesario para que apache reemplazar al web server interno que viene con trac.
# a2enmod python
Creo mi archivo de subdominio en /etc/apache/sites-availiable/ :
# touch /etc/apache2/sites-availiable/trac.midominio.org.ar
con el siguiente contenido:
<VirtualHost *:80>
ServerName trac.midominio.org.ar
ServerAlias www.trac.midominio.org.ar
ServerAdmin webmaster@midominio.org.ar
DocumentRoot /ruta/trac
<Directory /ruta/trac>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
##### Logs: Configuración de LOGs
ErrorLog ${APACHE_LOG_DIR}/midominio.org.ar.error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/midominio.org.ar.access.log combined
##### Ruta a TRAC : http://trac.midominio.com.ar/
# Rewrite ./trac to ./trac/
# RewriteEngine on
# RewriteRule ^(.*)\/trac$ $1/ [NC]
<Location />
SetHandler mod_python
PythonHandler trac.web.modpython_frontend
PythonInterpreter main
PythonOption TracEnvParentDir /ruta/trac
PythonOption TracUriRoot /
SetEnv PYTHON_EGG_CACHE /tmp
</Location>
### Validacion de acceso a TRAC : http://midominio.org.ar/*/login
<LocationMatch ^(/[^/]+)?/login>
AuthType Basic
AuthName "Login a TRAC"
AuthUserFile /etc/apache2/passwd-trac
Require valid-user
</LocationMatch>
### Referencia al repositorio SVN : http://midominio.org.ar/svn
<Location /svn>
DAV svn
SVNParentPath /ruta/svn
SVNListParentPath on
AuthType Basic
AuthName "Repositorio SVN"
AuthUserFile /etc/apache2/passwd-trac
Require valid-user
</Location>
</VirtualHost>
Una ves hechas esta modificaciones reniciamos el servicio de apache con:
# /etc/init.d/apache2 restart
4. Accediendo al repositorio subversion a traves de Apache2
Los usuarios serán creados en un archivo común que sera usado tanto por trac para la validación en su interfaz como por subversion para la autenticacion de los usuarios en su proyecto. Creación de usuarios:
# htpasswd -c /etc/apache2/passwd-trac usuario
Al añadir un segundo usuario debo quitar el parámetro -c del comando anterior, sino creara nuevamente el archivo passwd-trac. Este archivo es al que referenciamos desde la configuración del virtualhost de apache2, donde también lo usamos para realizar el acceso de nuestros usuarios a trac. La forma de referenciar al repositorio al hacer un checkout es:
# svn co http://trac.midominio.org.ar/svn/repositorio-proyecto1
Accediendo a la interfaz de trac
Según he armado esta guía la interfaz de trac estaría disponible en la dirección http://trac.midominio.org.ar y se vería así:
5. Asociando los commits a la actualización de los tickets en trac
La funcionalidad comit ticket updater hasta donde he visto es fabulosa, porque permite que cada usuario de subversion que se baje una copia de código al momento de redactar un comentario por cada commit realizada tenga la opción de interactuar con el sistema de tickets que provee trac. Bueno empecemos, creo un directorio donde este accesible el script
# mkdir /usr/share/trac/contrib # cp /usr/share/trac/contrib/trac-post-commit-hook /usr/share/trac/contrib
Dentro del directorio hooks del repositorio de mi proyecto en svn, el que mencionamos anteriormente, crear el archivo post-comit :
# touch /home/svn/repositorio-proyecto1/hooks/post-commit
Luego lo hago ejecutable:
# chmod 755 /home/svn/repositorio-proyecto1/hooks/post-commit
y, asigno usuario y grupo del servidor web
# chown www-data. /ruta/svn/repositorio-proyecto1/hooks/post-commit
y lo edito con el siguiente contenido :
#!/bin/sh REPOS="$1" REV="$2" LOG=`svnlook log -r $REV $REPOS` AUTHOR=`svnlook author -r $REV $REPOS` TRAC_ENV='/ruta/trac/trac-proyecto1' /usr/bin/python /usr/share/trac/contrib/trac-post-commit-hook \ -p "$TRAC_ENV" \ -r "$REV" \ -u "$AUTHOR" \ -m "$LOG"
ATENTI! que es necesario setear la variable TRAC_ENV de la linea 6 con el valor correcto sobre la ruta al entorno trac que corresponda al proyecto.
¿Como redactar los commits para interactuar con los tickets de trac?
Un vez hecho esto, como ya dije, los usuarios al hacer un commit contra el repositorio tendrán la opción de gestionar el estado de los tickets disponibles. Esto se hace añadiendo en los comentarios algunos comandos, estos son:
| Comandos | Detalles |
| close, closed, closes, fix, fixed, fixes | Los números de ticket especificados con estos comandos son cerrados con el contenido del mensaje del commit añadido como detalle |
| references, refs, addresses, re, see | Los números de problemas especificados con estos comandos son dejados en su estado actual, pero el contenido del mensaje del commit es agregado a las notas de los tickets |
Ahora la pregunta obvia seria ¿ como escribo los comandos?, es bastante simple, se debe respetar la siguiente notación:
comando #1 comando #1, #2 comando #1 & #2 comando #1 and #2
Donde #1 y #2 son números de tickets existentes en trac. O también puede usarse esta otra notación:
comando ticket:1 comando ticket:1, ticket:2 comando ticket:1 & ticket:2 comando ticket:1 and ticket:2
Estos comandos se analizan desde el script post-commitubicado en el directorio hooks del repositorio svn. Se parsea todo el mensaje de detalle de un commit cada vez que este se ejecuta y si se encuentran los comandos en los formatos especificados se realiza la acción que corresponda. Pongamos un ejemplo, podemos enviar un “commit” con el siguiente comentario:
“Cambios en tales modulos y mejoras en otros componentes. fixes #12 and #20, and refs #22″
Con lo cual cerrariamos los tickets 12 y 20 con un estado fixes y agregariamos este mensaje tambien como nota al ticket 22.
6. Conclusiones:
En mi experiencia he trabajado y he visto entornos donde tanto el sistema de seguimiento de errores como el de control de versiones estaban implementados en forma separada, por consiguiente la tarea del desarrollador era doble, ademas de comentar en los commits debían redundar en tareas al tener que escribir exactamente lo mismo en respuesta a alguna incidencia reportada. Tener integradas ambas herramientas, sumado a la posibilidad de interactuar con los tickets creados permite al grupo reducir tiempo valioso dedicado en escribir documentación del proceso de desarrollo, que es algo que los desarrolladores no suelen tener en en top de la lista de sus prioridades principales. La experiencia dentro de la interfaz de trac es muy ágil para el usuario, se tiene las linea de tiempo (timeline) donde se puede visualizar todas las modificaciones hechas dentro del entorno, desde una nueva entrada en la wiki a cambios en los tickets o la hoja de ruta (roadmap) desde donde se pueden seguir los estados del proyecto en cada Hito/Meta (o milestones como los llama trac).
Una ventaja, si se la puede ver así, es que al finalizar esta guía quedara configurado un servidor web donde podemos tranquilamente escalar la configuración para ubicar otros repositorios subversion en el path /ruta/svn y sus entornos trac asociados en el path /ruta/trac/, es decir podremos situar múltiples proyectos de software.



