Roundup

An Issue-Tracking System for Knowledge Workers

Contents


Installation

Prerequisites

Either:
Python 2.0 with pydoc installed. See http://www.lfw.org/ for pydoc.
or
Python 2.1 or later
Download the latest version from http://www.python.org/.

Getting Roundup

Download the latest version from http://roundup.sf.net/.

Installing Roundup

  1. Run:
    python setup.py install
  2. If you would prefer the scripts installed in somewhere other than /usr/local/bin, add "--install-scripts=<dir>" to the command:
    python setup.py install --install-scripts=<dir>
  3. The command:
    python setup.py install --help
    gives all the options available for installation.


Getting Started

The following instructions assume that you have installed roundup. If you haven't, you may still proceed - just preface all commands with "./" ie. "./roundup-admin init".

The Instance

We'll be referring to the term "instance" a lot from now on. An instance is a directory in your filesystem that is where all the information about a live issue tracker database is stored. The data that is entered as issues, the users who access the database and the definition of the database itself all reside there:
  1. Hyperdatabase
    This is the lowest component of Roundup and is where all the issues, users, file attachments and messages are stored.
  2. Database schema
    This describes the content of the hyperdatabase - what fields are stored for issues, what user information, etc. Being stored in the instance, this allows it to be customised for a particular application. It also means that changes in the Roundup core code do not affect a running instance.
  3. Web Interface
    The web interface templates are defined in the instance too - and the actual CGI interface class is defined (mostly using base classes in the Roundup core code) so it, like the database, may be customised for each instance in use.
Instances are created using the roundup-admin tool.

Command Line Tool

To initiliase a new instance, run roundup-admin init. You will be asked a series of questions:
  1. Instance home directory
  2. Schema to use
  3. Database back-end to use
  4. Administration user "admin" password.
Roundup is configurable using a localconfig.py file in the instance home. It may have the following variable declarations:
  1. MAILHOST
    The SMTP mail host that roundup will use to send mail
  2. MAIL_DOMAIN
    The domain name used for email addresses
Any further configuration should be possible by editing the instance home's __init__.py directly.

The email addresses used by the system by default are:

  1. issue_tracker@MAIL_DOMAIN
    submissions of issues
  2. roundup-admin@MAIL_DOMAIN
    roundup's internal use (problems, etc)
Note: We run the instance as group "issue_tracker" and add the mail and web user ("mail" and "apache" on our RedHat 7.1 system) to that group, as well as any admin people.

E-Mail Interface

Set up a mail alias called "issue_tracker" as:
|/usr/bin/python /usr/local/bin/roundup-mailgw <instance_home>
In some installations (e.g. RedHat 6.2 I think) you'll need to set up smrsh so sendmail will accept the pipe command. In that case, symlink /etc/smrsh/roundup-mailgw to /usr/local/bin/roundup-mailgw and change the command to:
|roundup-mailgw <instance_home>
To test the mail gateway on unix systems, try:
echo test |mail -s '[issue] test' issue_tracker@your.domain

Web Interface

This software will work through apache or stand-alone.

Stand-alone:

  1. Edit roundup-server at the top - ROUNDUP_INSTANCE_HOMES needs to know about your instance. *** command-line option
  2. roundup-server [hostname port] (hostname may be "")
  3. Load up the page /<instance name>/index where instance name is the name you nominated in ROUNDUP_INSTANCE_HOMES. *** command-line option
Apache:
  1. Make sure roundup.cgi is executable. Edit it at the top - ROUNDUP_INSTANCE_HOMES needs to know about your instance.
  2. Edit your /etc/httpd/conf/httpd.conf and make sure that the /home/httpd/html/roundup/roundup.cgi script will be treated as a CGI script.
  3. Add the following to your /etc/httpd/conf/httpd.conf:
    ------8<------- snip here ------8<-------
    RewriteEngine on
    RewriteCond %{HTTP:Authorization} ^(.*)
    RewriteRule ^/roundup/roundup.cgi(.*) /home/httpd/html/roundup/roundup.cgi$1 [e=HTTP_CGI_AUTHORIZATION:%1,t=application/x-httpd-cgi,l]
    ------8<------- snip here ------8<-------
    
    note: the RewriteRule must be on one line - no breaks
  4. Re-start your apache to re-load the config
  5. Load up the page /roundup/roundup.cgi/<instance name>/index where instance name is the name you nominated in ROUNDUP_INSTANCE_HOMES.

Users

To add users, use one of the following interfaces:
  1. On the web, access the URL .../<instance name>/newuser to bring up a form which may be used to add a new user.
  2. On the command-line, use:
    roundup-admin -i <instance home> create user username=bozo password=bozo address=richard@clown.org
    Supply the admin username and password. roundup-admin will print the id of the new user.
  3. Any e-mail sent to roundup from an address that doesn't match an existing user in the database will result in a new user entry being created for that user.

Issues

To add issues, use one of the following interfaces:
  1. On the web, access the URL .../<instance name>/newissue to bring up a form which may be used to add a new issue.
  2. On the command-line, use:
    roundup-admin -i <instance home> create issue title="test issue"
    Supply the admin username and password. roundup-admin will print the id of the new issue.
  3. Any e-mail sent to roundup with the subject line containing [issue] will automatically created a new issue in the database using the contents of the e-mail.


User Guide

Command Line Tool

Usage: roundup-admin [-i instance home] [-u login] [-c] <command> <arguments>

Commands:
create classname property=value ...
find classname propname=value ...
freshen
get property designator[,designator]*
history designator
init [template [backend [admin password]]]
list classname [property]
retire designator[,designator]*
set designator[,designator]* propname=value ...
spec classname
Help:
roundup-admin -h
roundup-admin help -- this help
roundup-admin help -- command-specific help
roundup-admin morehelp -- even more detailed help
Options:
-i instance home -- specify the issue tracker "home directory" to administer
-u -- the user[:password] to use for commands
-c -- when outputting lists of data, just comma-separate them

All commands (except help) require an instance specifier. This is just the path to the roundup instance you're working with. A roundup instance is where roundup keeps the database and configuration file that defines an issue tracker. It may be thought of as the issue tracker's "home directory". It may be specified in the environment variable ROUNDUP_INSTANCE or on the command line as "-i instance".

A designator is a classname and a nodeid concatenated, eg. bug1, user10, ...

Property values are represented as strings in command arguments and in the printed results:

When multiple nodes are specified to the roundup get or roundup set commands, the specified properties are retrieved or set on all the listed nodes.

When multiple results are returned by the roundup get or roundup find commands, they are printed one per line (default) or joined by commas (with the -c) option.

Where the command changes data, a login name/password is required. The login may be specified as either "name" or "name:password".

If either the name or password is not supplied, they are obtained from the command-line.

Date format examples:
Input of...Means...
"2000-04-17.03:45"2000-04-17.08:45:00
"2000-04-17"2000-04-17.00:00:00
"01-25"yyyy-01-25.00:00:00
"08-13.22:13"yyyy-08-14.03:13:00
"11-07.09:32:43"yyyy-11-07.14:32:43
"14:25"yyyy-mm-dd.19:25:00
"8:47:11"yyyy-mm-dd.13:47:11
".""right now"

Specific Command help

history:
    Usage: history designator
    Show the history entries of a designator.

    Lists the journal entries for the node identified by the designator.
    
find:
    Usage: find classname propname=value ...
    Find the nodes of the given class with a given property value.

    Find the nodes of the given class with a given property value. The
    value may be either the nodeid of the linked node, or its key value.
    
list:
    Usage: list classname [property]
    List the instances of a class.

    Lists all instances of the given class along. If the property is not
    specified, the  "label" property is used. The label property is tried
    in order: the key, "name", "title" and then the first property,
    alphabetically.
    
retire:
    Usage: retire designator[,designator]*
    Retire the node specified by designator.

    This action indicates that a particular node is not to be retrieved by
    the list or find commands, and its key value may be re-used.
    
create:
    Usage: create classname property=value ...
    Create a new entry of a given class.

    This creates a new entry of the given class using the property
    name=value arguments provided on the command line after the "create"
    command.
    
get:
    Usage: get property designator[,designator]*
    Get the given property of one or more designator(s).

    Retrieves the property value of the nodes specified by the designators.
    
spec:
    Usage: spec classname
    Show the properties for a classname.

    This lists the properties for a given class.
    
set:
    Usage: set designator[,designator]* propname=value ...
    Set the given property of one or more designator(s).

    Sets the property to the value for all designators given.
    
init:
    Usage: init [template [backend [admin password]]]
    Initialise a new Roundup instance.

    The command will prompt for the instance home directory (if not supplied
    through INSTANCE_HOME or the -i option. The template, backend and admin
    password may be specified on the command-line as arguments, in that order.
    
freshen:
    Usage: freshen
    Freshen an existing instance.  **DO NOT USE**

    This currently kills databases!!!!

    This action should generally not be used. It reads in an instance
    database and writes it again. In the future, is may also update
    instance code to account for changes in templates. It's probably wise
    not to use it anyway. Until we're sure it won't break things...

Web Interface

T.B.D.

E-Mail Gateway

Incoming messages are examined for multiple parts:

Summary

The "summary" property on message nodes is taken from the first non-quoting section in the message body. The message body is divided into sections by blank lines. Sections where the second and all subsequent lines begin with a ">" or "|" character are considered "quoting sections". The first line of the first non-quoting section becomes the summary of the message.

Addresses

All of the addresses in the To: and Cc: headers of the incoming message are looked up among the user nodes, and the corresponding users are placed in the "recipients" property on the new "msg" node. The address in the From: header similarly determines the "author" property of the new "msg" node. The default handling for addresses that don't have corresponding users is to create new users with no passwords and a username equal to the address. (The web interface does not permit logins for users with no passwords.) If we prefer to reject mail from outside sources, we can simply register an auditor on the "user" class that prevents the creation of user nodes with no passwords.

Actions

The subject line of the incoming message is examined to determine whether the message is an attempt to create a new item or to discuss an existing item. A designator enclosed in square brackets is sought as the first thing on the subject line (after skipping any "Fwd:" or "Re:" prefixes). If an item designator (class name and id number) is found there, the newly created "msg" node is added to the "messages" property for that item, and any new "file" nodes are added to the "files" property for the item. If just an item class name is found there, we attempt to create a new item of that class with its "messages" property initialized to contain the new "msg" node and its "files" property initialized to contain any new "file" nodes.

Triggers

Both cases may trigger detectors (in the first case we are calling the set() method to add the message to the item's spool; in the second case we are calling the create() method to create a new node). If an auditor raises an exception, the original message is bounced back to the sender with the explanatory message given in the exception.


Acknowledgements

Go Ping, you rock! Also, go Bizar Software for letting me implement this system on their time.