Table of Contents
Ce HOW-TO explique comment utiliser le module Bugnicar 0.9 de Narval pour gérer le suivi des bugs et corrections associées d'un programme par l'intermédiaire du courrier électronique ou de formulaires web.
Téléchargez l'archive contenant les fichiers de Bugnicar et décompressez-la. Vous obtenez un répertoire bugnicar-0.9/ prêt à l'emploi que nous appellerons BUG_HOME.
Nous utiliserons BUG_HOME/data/bugnicar-memory.xml pour donner la bonne valeur à l'attribut path de l'élément mailbox.
Depuis un shell, lancez python, puis importez le module AccessControl qui figure dans BUG_HOME/modules/ et exécutez la commande AccessControl.compile_password('turlututu'). Recopiez la chaîne obtenue comme valeur de l'attribut "password" associé à un login "bugnicar" comme ci-dessous.
<memory> ... <access-control-list> <access-control-item login='bugnicar' password='resultat-de-turlututu'/> </access-control-list> <memory>
Pour ne pas prendre de risque, j'ai rajouté les lignes suivantes dans mon .procmailrc et j'ai donné cette boîte à lire à Bugnicar en mettant la même valeur pour l'attribut path de l'élément mailbox.
:0: * ^Subject: \[BUGNICAR\] mail/bugnicar
et
<memory> ... <mailbox path='/home/nico/mail/bugnicar'/> ... <memory>
Pour lancer l'application utilisons le script ~/bin/bugnicar.sh suivant :
#!/bin/sh cd ~/Narval export PYTHONPATH=~/Narval python narval/Engine.py --home ~/bugnicar-0.9/ \ --start-plan "email.Mail_Sensor" \ --start-plan "bugnicar.Catch-mail" \ --start-plan "bugnicar.Task-process" \ --load-memory-file ~/bugnicar-0.9/data/bugnicar-memory.xml \ --socket-manager $1
avec BUG_HOME égal à ~/bugnicar-0.9/.
Lancer ~/bin/bugnicar.sh --debug depuis la ligne de commande permet de tester la recette, dont le résultat doit apparaître dans BUG_HOME/data/bugnicar.html. Ce fichier peut-être obtenu simplement en transformant BUG_HOME/data/bugnicar-database.xml avec BUG_HOME/transforms/Bugnicar/bug2htmlreport.xslt.
Bugnicar sauvegarde la liste des bugs dans le fichier BUG_HOME/data/bugnicar-database.xml. Pour créer une nouvelle base de données, il suffit de remplacer ce fichier avec la chaîne <bugnicar-database/>. On peut éventuellement y spécifier dès maintenant le nom du projet et l'URL de sa page d'accueil en préférant cette seconde chaîne : <bugnicar-database project='Narval' url='http://www.logilab.org/narval/'/>.
Cette nouvelle version de Bugnicar autorise des commandes supplémentaires pour la gestion des bugs, et utilise en conséquence un format de sauvegarde différent pour sa base de données. Si vous utilisiez déjà Bugnicar 0.1, placez-vous dans le répertoire BUG_HOME et exécutez les commandes suivantes pour convertir votre base au nouveau format :
mv data/bugnicar-database.xml data/bugnicar-database.xml.old 4xslt data/bugnicar-database.xml.old extensions/bugnicar-convert-database.xslt \ > data/bugnicar-database.xml
Pour ajouter un nouveau bug à la base, il suffit d'envoyer un courriel dont le sujet est [BUGNICAR] bug report about toto et le corps du message contient les détails.
Pour ajouter un commentaire au rapport de bug numéro 1, il suffit d'envoyer un courriel dont le sujet est [BUGNICAR] bug comment 1 avec vos remarques dans le corps du message.
Pour assigner le bug numéro 1 à quelqu'un (identifié par son adresse électronique), il suffit d'envoyer un courriel ayant pour sujet [BUGNICAR] bug assign 1 pass turlututu to toi@la-bas.org, en joignant éventuellement un commentaire dans le corps du message. Cette commande n'est accessible qu'aux administrateurs en utilisant le mot de passe, ici 'turlututu'.
Pour changer le contenu du champ 'about' du bug numéro 1, il suffit d'envoyer un courriel ayant pour sujet [BUGNICAR] bug set 1 pass turlututu about titi, pas toto, en joignant éventuellement un commentaire dans le corps du message. Cette commande n'est accessible qu'aux administrateurs.
Pour classer le bug numéro 1 qui a été réparé, il suffit d'envoyer un courriel ayant pour sujet [BUGNICAR] bug close 1 pass turlututu , en joignant éventuellement un commentaire dans le corps du message. Cette commande n'est accessible qu'aux administrateurs.
Pour réouvrir le bug classé numéro 1, il suffit d'envoyer un courriel ayant pour sujet [BUGNICAR] bug reopen 1 pass turlututu , en joignant éventuellement un commentaire dans le corps du message. Cette commande n'est admissible qu'aux administrateurs.
Il est désormais également possible d'utiliser une interface web pour consulter les reports de bugs et envoyer des commandes ; NARVAL reçoit alors des requêtes HTTP et non plus des courriels. Un exemple d'interface utilisant HTML et PHP3 est fourni dans BUG_HOME/data/bugnicar/.
Pour adapter l'interface à votre système, placez-vous dans le répertoire BUG_HOME/data/bugnicar/ et exécutez le script suivant, où MACHINE doit être remplacé par le nom du serveur sur lequel tourne NARVAL ; ce script modifiera les formulaires en leur donnant la bonne adresse.
#!/bin/sh my_machine=MACHINE for i in `ls *.php3` do a=`cat $i`; printf "$a" | sed "s/action=\"http:\/\/.*:/action=\"http:\/\/$my_machine:/g" > $i done
<?xml version="1.0"?> <state-machine xmlns:xupdate="http://www.xmldb.org/xupdate" name="buggy"> <object nodename="bug"> <storage type="plain-file" uri="$NARVAL_HOME/data/bugnicar-database.xml"> <location>/bugnicar-database</location> </storage> <get-object-from-storage> <event> <element called="operation" nodename="bugnicar-task"> <match>@for</match> <match>not(bug-report)</match> </element> </event> <query>@id = #operation#/@for</query> </get-object-from-storage> </object> <!-- States declaration --> <state id="not-assigned"> <description> <match>@state = 'not-assigned'</match> </description> </state> <state id="assigned"> <description> <match>@state = 'assigned'</match> </description> </state> <state id="fixed"> <description> <match>@state = 'fixed'</match> </description> </state> <!-- Initialization declaration --> <transition type="init" id="add-new" out="not-assigned"> <event> <element called="operation" nodename="bugnicar-task"> <match>bug-report</match> </element> </event> <actions> <create-object> <xupdate:attribute name="id"> <xupdate:value-of select="position()"/> </xupdate:attribute> <xupdate:attribute name="state">not-assigned</xupdate:attribute> <xupdate:element name="label"> <xupdate:value-of select="#operation#/about/text()" /> </xupdate:element> <xupdate:element name="report-info"> <from><xupdate:value-of select="#operation#/bug-report/@sender" /></from> <date><xupdate:value-of select="#operation#/bug-report/@date" /></date> <description><xupdate:value-of select="#operation#/text()" /></description> </xupdate:element> <xupdate:element name="comments" /> </create-object> </actions> </transition> <!-- Destroy declaration --> <transition type="destr" id="remove" in="any"> <event> <element called="operation" nodename="bugnicar-task"> <match>remove</match> </element> </event> <actions> <xupdate:remove select="#object#" /> </actions> </transition> <!-- Transitions declaration --> <transition id="set-label-not-assigned" in="not-assigned" out="not-assigned"> <event> <element called="operation" nodename="bugnicar-task"> <match>set-label</match> </element> </event> <actions> <xupdate:remove select="#object#/label"/> <xupdate:element name="label"> <xupdate:value-of select="#operation#/about/text()" /> </xupdate:element> </actions> </transition> <transition id="set-label-assigned" in="assigned" out="assigned"> <event> <element called="operation" nodename="bugnicar-task"> <match>set-label</match> </element> </event> <actions> <xupdate:remove select="#object#/label"/> <xupdate:element name="label"> <xupdate:value-of select="#operation#/about/text()" /> </xupdate:element> </actions> </transition> <transition id="set-label-fixed" in="fixed" out="fixed"> <event> <element called="operation" nodename="bugnicar-task"> <match>set-label</match> </element> </event> <actions> <xupdate:remove select="#object#/label"/> <xupdate:element name="label"> <xupdate:value-of select="#operation#/about/text()" /> </xupdate:element> </actions> </transition> <transition id="add-comment" in="not-assigned" out="not-assigned"> <event> <element called="operation" nodename="bugnicar-task"> <match>bug-comment</match> </element> </event> <actions> <modify-object> <xupdate:append select="#object#/comments"> <xupdate:element name="comment"> <xupdate:attribute name='from'><xupdate:value-of select="#operation#/bug-comment/@sender" /></xupdate:attribute> <xupdate:attribute name='date'><xupdate:value-of select="#operation#/bug-comment/@date" /></xupdate:attribute> <xupdate:value-of select="#operation#/text()" /> </xupdate:element> </xupdate:append> </modify-object> </actions> </transition> <transition id="add-comment-when-assigned" in="assigned" out="assigned"> <event> <element called="operation" nodename="bugnicar-task"> <match>bug-comment</match> </element> </event> <actions> <modify-object> <xupdate:append select="#object#/comments"> <xupdate:element name="comment"> <comment> <xupdate:attribute name='from'><xupdate:value-of select="#operation#/bug-comment/@sender" /></xupdate:attribute> <xupdate:attribute name='date'><xupdate:value-of select="#operation#/bug-comment/@date" /></xupdate:attribute> <xupdate:value-of select="#operation#/text()" /> </comment> </xupdate:element> </xupdate:append> </modify-object> </actions> </transition> <transition id="assign" in="not-assigned" out="assigned"> <event> <element called="operation" nodename="bugnicar-task"> <match>bug-assign</match> <match>@password</match> </element> </event> <actions> <modify-object> <xupdate:append select="#object#"> <xupdate:attribute name="state">assigned</xupdate:attribute> <xupdate:element name="worker"> <xupdate:attribute name="id"><xupdate:value-of select="#operation#/worker-id/text()" /></xupdate:attribute> <xupdate:attribute name='date'><xupdate:value-of select="#operation#/bug-assign/@date" /></xupdate:attribute> </xupdate:element> </xupdate:append> </modify-object> </actions> </transition> <transition id="unassign" in="assigned" out="not-assigned"> <event> <element called="operation" nodename="bugnicar-task"> <match>bug-unassign</match> <match>@password</match> </element> </event> <actions> <modify-object> <xupdate:append select="#object#"> <xupdate:attribute name="state">not-assigned</xupdate:attribute> </xupdate:append> <xupdate:remove select="#object#/worker"/> </modify-object> </actions> </transition> <transition id="change-assignment" in="assigned" out="assigned"> <event> <element called="operation" nodename="bugnicar-task"> <match>bug-assign</match> <match>@password</match> </element> </event> <conditions> <match-cond>#operation#/worker-id/text()</match-cond> </conditions> <actions> <modify-object> <xupdate:remove select="#object#/worker"/> </modify-object> <modify-object> <xupdate:append select="#object#"> <xupdate:element name="worker"> <xupdate:attribute name="id"><xupdate:value-of select="#operation#/worker-id/text()" /></xupdate:attribute> <xupdate:attribute name='date'><xupdate:value-of select="#operation#/bug-assign/@date" /></xupdate:attribute> </xupdate:element> </xupdate:append> </modify-object> </actions> </transition> <transition id="close-bug" in="assigned" out="fixed"> <event> <element called="operation" nodename="bugnicar-task"> <match>bug-close</match> <match>@password</match> </element> </event> <actions> <modify-object> <xupdate:append select="#object#"> <xupdate:attribute name="state">fixed</xupdate:attribute> <xupdate:attribute name='date'><xupdate:value-of select="#operation#/bug-close/@date" /></xupdate:attribute> </xupdate:append> </modify-object> </actions> </transition> <transition id="reopen-bug" in="fixed" out="assigned"> <event> <element called="operation" nodename="bugnicar-task"> <match>bug-reopen</match> <match>@password</match> </element> </event> <actions> <modify-object> <xupdate:append select="#object#"> <xupdate:attribute name="state">assigned</xupdate:attribute> </xupdate:append> </modify-object> </actions> </transition> </state-machine>