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>