Table of Contents
This HOW-TO explains how to use NARVAL's Bugnicar 0.9 module to manage bugs and patches for a project, using e-mail or web forms.
Download the Bugnicar tarball and unpack it. You will get a bugnicar-0.9/ directory, that will be refered to as BUG_HOME in this document.
We will use the memory file for NARVAL located at BUG_HOME/data/bugnicar-memory.xml; you need to edit it to enter your settings.
From a shell, launch python, and import the AccessControl module which is in BUG_HOME/modules/. Run AccessControl.compile_password('turlututu'). Copy the resulting string in the password attribute associated to a "bugnicar" login as shown below:
<memory> ... <access-control-list> <access-control-item login='bugnicar' password='result-of-turlututu'/> </access-control-list> </memory>
In order to operate without risk, I added the following lines to my .procmailrc and assigned this mailbox to Bugnicar by setting the path attribute of the mailbox element.
:0: * ^Subject: \[BUGNICAR\] mail/bugnicar
and
<memory> ... <mailbox path='/home/nico/mail/bugnicar'/> ... <memory>
The ~/bin/bugnicar.sh script could look like:
#!/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
using BUG_HOME equal to ~/bugnicar-0.9/.
Launching ~/bin/bugnicar.sh --debug from the command enables testing the recipe. The result of the recipe should appear in BUG_HOME/data/bugnicar.html. This file can be regenerated by applying an XSL Transformation on BUG_HOME/data/bugnicar-database.xml; a sample transformation is BUG_HOME/transforms/Bugnicar/bug2htmlreport.xslt.
Bugnicar writes the bug database in the file BUG_HOME/data/bugnicar-database.xml. To create a new database just replace this file with the string <bugnicar-database/>. You can specify at this time the name of your project and the URL of its homepage with this second string: <bugnicar-database project='Narval' url='http://www.logilab.org/narval/'/>.
This new version of Bugnicar allows more commands for managing bugs than the previous one, and so uses a different format for saving its database. If you were already managing your bugs with Bugnicar 0.1, change the current directory to BUG_HOME and use the following commands to convert your base to the new 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
To insert a new bug to the database, you just have to send an email with the subject looking like [BUGNICAR] bug report about foo and with the details in the body of the message.
To add a comment to the bug report #1, you must send a mail with subject [BUGNICAR] bug comment 1 and with your observation in the body of the mail.
To change the 'about' field for the bug #1, you must send a mail with subject [BUGNICAR] bug set 1 pass turlututu about other foo, and you can join a comment in the body of the mail. This command needs the admin password to work, here it is turlututu.
To assign the bug #1 to somebody (identified by an email address), you must send a mail with subject [BUGNICAR] bug assign 1 pass turlututu to somebody@somewhere.org , and you can join a comment in the body of the mail. This command needs the admin password to work.
To close the bug #1 which has been fixed, send a mail with subject [BUGNICAR] bug close 1 pass turlututu and details in the body of the mail. This command needs the admin password to work.
To reopen the bug #1 which has been closed, send a mail with subject [BUGNICAR] bug reopen 1 pass turlututu and details in the body of the mail. This command needs the admin password to work.
Now you can use Bugnicar with a web interface for listing the bug reports and sending commands; then NARVAL will recept HTTP requests instead of emails. A sample interface using HTML and PHP3 is located at BUG_HOME/data/bugnicar/.
To fit the interface to your system, change directory to BUG_HOME/data/bugnicar/ and execute the following script, where MACHINE must be replaced by the name of the server where NARVAL is running; it will write the right URL in the forms.
#!/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>