The email addresses used by the system by default are:
|/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
Stand-alone:
------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
If users attempt to use roundup in any manner and are not identified to roundup, they will be using the database in a read-only mode. That is, if roundup doesn't know who they are, they can't change anything. This has the following repurcussions:
There has been only a half-hearted attempt to restrict certain activities to the "admin" user. For example, the "extended" schema web interface enables some fnuctionality for the "admin" user. On the fil-side, it is possible to obtain the admin user's password using the read-only access on the command line (it would also be possible to access the database files directly to obtain this information).
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 |
Command Help | |
---|---|
history | history designator Lists the journal entries for the node identified by the designator. |
find | find classname propname=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 | list classname [property] 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 | retire designator[,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 | create classname property=value ... 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 | get property designator[,designator]* Retrieves the property value of the nodes specified by the designators. |
spec | spec classname This lists the properties for a given class. |
set | set designator[,designator]* propname=value ... Sets the property to the value for all designators given. |
init | init [template [backend [admin password]]] 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 | freshen **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... |
help | help [command] Short help about roundup-admin or the specific command. |
morehelp | morehelp All available help from the roundup-admin tool. |
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:
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" |
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".
:sort - sort by prop name, optionally preceeded with '-' to give descending or nothing for ascending sorting. :group - group by prop name, optionally preceeded with '-' or to sort in descending or nothing for ascending order. :filter - selects which props should be displayed in the filter section. Default is all. :columns - selects the columns that should be displayed. Default is all. propname - selects the values the node properties given by propname must have (very basic search/filter).Not sure what to put in here...
instance_config.py | Holds the basic instance configuration |
dbinit.py | Holds the instance schema |
interfaces.py | Defines the Web and E-Mail interfaces for the instance |
select_db.py | Selects the database back-end for the instance |
db/ | Holds the instance's database |
db/files/ | Holds the instance's upload files and messages |
detectors/ | Auditors and reactors for this instance |
html/ | Web interface templates, images and style sheets |
MAIL_DOMAIN=MAILHOST=HTTP_HOST=None HTTP_PORT=0 # roundup home is this package's directory INSTANCE_HOME=os.path.split(__file__)[0] # The SMTP mail host that roundup will use to send mail if not MAILHOST: MAILHOST = 'localhost' # The domain name used for email addresses. if not MAIL_DOMAIN: MAIL_DOMAIN = 'fill.me.in.' # the next two are only used for the standalone HTTP server. if not HTTP_HOST: HTTP_HOST = '' if not HTTP_PORT: HTTP_PORT = 9080 # This is the directory that the database is going to be stored in DATABASE = os.path.join(INSTANCE_HOME, 'db') # This is the directory that the HTML templates reside in TEMPLATES = os.path.join(INSTANCE_HOME, 'html') # The email address that mail to roundup should go to ISSUE_TRACKER_EMAIL = 'issue_tracker@%s'%MAIL_DOMAIN # The web address that the instance is viewable at ISSUE_TRACKER_WEB = 'http://some.useful.url/' # The email address that roundup will complain to if it runs into trouble ADMIN_EMAIL = 'roundup-admin@%s'%MAIL_DOMAIN # Somewhere for roundup to log stuff internally sent to stdout or stderr LOG = os.path.join(INSTANCE_HOME, 'roundup.log')
pri = Class(db, "priority", name=String(), order=String()) pri.setkey("name") pri.create(name="critical", order="1") pri.create(name="urgent", order="2") pri.create(name="bug", order="3") pri.create(name="feature", order="4") pri.create(name="wish", order="5") stat = Class(db, "status", name=String(), order=String()) stat.setkey("name") stat.create(name="unread", order="1") stat.create(name="deferred", order="2") stat.create(name="chatting", order="3") stat.create(name="need-eg", order="4") stat.create(name="in-progress", order="5") stat.create(name="testing", order="6") stat.create(name="done-cbb", order="7") stat.create(name="resolved", order="8") keyword = Class(db, "keyword", name=String()) keyword.setkey("name") user = Class(db, "user", username=String(), password=String(), address=String(), realname=String(), phone=String(), organisation=String()) user.setkey("username") user.create(username="admin", password=adminpw, address=instance_config.ADMIN_EMAIL) msg = FileClass(db, "msg", author=Link("user"), recipients=Multilink("user"), date=Date(), summary=String(), files=Multilink("file")) file = FileClass(db, "file", name=String(), type=String()) issue = IssueClass(db, "issue", assignedto=Link("user"), topic=Multilink("keyword"), priority=Link("priority"), status=Link("status")) issue.setkey('title')
We define the "priority" and "status" classes to allow two things: reduction in the amount of information stored on the issue and more powerful, accurate searching of issues by priority and status. By only requiring a link on the issue (which is stored as a single number) we reduce the chance that someone mis-types a priority or status - or simply makes a new one up.
Class
Class is the basic store of information.
FileClass
FileClasses save their "content" attribute off in a separate file from the
rest of the database. This reduces the number of large entries in the
database, which generally makes databases more efficient, and also allows
us to use command-line tools to operate on the files. They are stored in
the files sub-directory of the db directory in your instance.
IssueClass
IssueClasses automatically include the "messages", "files", "nosy", and
"superseder" properties.
The messages and files properties list the links to the messages and files related to the issue. The nosy property is a list of links to users who wish to be informed of changes to the issue - they get "CC'ed" e-mails when messages are sent to or generated by the issue. The nosy reactor (in the detectors directory) handles this action. The superceder link indicates an issue which has superceded this one.
They also have the dynamically generated "creation", "activity" and "creator" properties.
The value of the "creation" property is the date when an item was created, and the value of the "activity" property is the date when any property on the item was last edited (equivalently, these are the dates on the first and last records in the item's journal). The "creator" property holds a link to the user that created the issue.
roundup-admin set issue assignedto=2
or
roundup-admin set issue assignedto=richard
Note, the same thing can be done in the web and e-mail interfaces.
Most customisation of the web view can be done by modifying the templates in the instance html directory. These are divided into index, item and newitem views. The newitem view is optional - the item view will be used if the newitem view doesn't exist.
Properties appear in the user interface in three contexts: in indices, in editors, and as filters. For each type of property, there are several display possibilities. For example, in an index view, a string property may just be printed as a plain string, but in an editor view, that property should be displayed in an editable field.
The display of a property is handled by functions in the htmltemplate module.
Displayer functions are triggered by <display> tags in templates. The call attribute of the tag provides a Python expression for calling the displayer function. The three standard arguments are inserted in front of the arguments given. For example, the occurrence of
in a template triggers a call the "plain" function. The displayer functions can accept extra arguments to further specify details about the widgets that should be generated. By defining new displayer functions, the user interface can be highly customized.<display call="plain('status')">
The displayer functions are | |
---|---|
plain | Display a String property directly.
Display a Date property in a specified time zone with an option to omit the time from the date stamp. For a Link or Multilink property, display the key strings of the linked nodes (or the ids if the linked class has no key property).
Options: |
field | Display a property like the
plain displayer above, but in a form field
to be edited. Strings, Dates and Intervals use TEXT fields, Links use
SELECT fields and Multilinks use SELECT MULTIPLE fields.
Options: |
menu | For a Links and Multilinks, display the same field as would be generated using field. |
link | For a Link or Multilink property, display the names of the linked
nodes, hyperlinked to the item views on those nodes. For other properties,
link to this node with the property as the text.
Options: |
count | For a Multilink property, display
a count of the number of links in the list.
Arguments: |
reldate | Display a Date property in terms
of an interval relative to the current date (e.g. "+ 3w", "- 2d").
Arguments:
Options: |
download | Show a Link("file") or Multilink("file")
property using links that allow you to download files.
Arguments: |
checklist | For a Link or Multilink property,
display checkboxes for the available choices to permit filtering.
Arguments: |
note | Display the special notes field, which is a text area for entering a note to go along with a change. |
list | List the items specified by property using the standard index for
the class.
Arguments: |
history | List the history of the item. |
submit | Add a submit button for the item. |
An index view contains two sections: a filter section and an index section. The filter section provides some widgets for selecting which items appear in the index. The index section is a table of items.
An index view specifier (URL fragment) looks like this (whitespace has been added for clarity):
/issue?status=unread,in-progress,resolved& topic=security,ui& :group=+priority& :sort=-activity& :filters=status,topic& :columns=title,status,fixer
The index view is determined by two parts of the specifier: the layout part and the filter part. The layout part consists of the query parameters that begin with colons, and it determines the way that the properties of selected nodes are displayed. The filter part consists of all the other query parameters, and it determines the criteria by which nodes are selected for display.
The filter part is interactively manipulated with the form widgets displayed in the filter section. The layout part is interactively manipulated by clicking on the column headings in the table.
The filter part selects the union of the sets of items with values matching any specified Link properties and the intersection of the sets of items with values matching any specified Multilink properties.
The example specifies an index of "issue" nodes. Only items with a "status" of either "unread" or "in-progres" or "resolved" are displayed, and only items with "topic" values including both "security" and "ui" are displayed. The items are grouped by priority, arranged in ascending order; and within groups, sorted by activity, arranged in descending order. The filter section shows filters for the "status" and "topic" properties, and the table includes columns for the "title", "status", and "fixer" properties.
Associated with each item class is a default layout specifier. The layout specifier in the above example is the default layout to be provided with the default bug-tracker schema described above in section 4.4.
The template for a filter section provides the filtering widgets at the top of the index view. Fragments enclosed in <property>...</property> tags are included or omitted depending on whether the view specifier requests a filter for a particular property.
Here's a simple example of a filter template.
<property name=status> <display call="checklist('status')"> </property> <br> <property name=priority> <display call="checklist('priority')"> </property> <br> <property name=fixer> <display call="menu('fixer')"> </property>
The standard index generation code appends a section to the index pages which allows selection of the filters - from those which are defined in the filter template.
The template for an index section describes one row of the index table. Fragments enclosed in <property>...</property> tags are included or omitted depending on whether the view specifier requests a column for a particular property. The table cells should contain <display> tags to display the values of the item's properties.
Here's a simple example of an index template.
<tr> <property name=title> <td><display call="plain('title', max=50)"></td> </property> <property name=status> <td><display call="plain('status')"></td> </property> <property name=fixer> <td><display call="plain('fixer')"></td> </property> </tr>
String and Date values are sorted in the natural way. Link properties are sorted according to the value of the "order" property on the linked nodes if it is present; or otherwise on the key string of the linked nodes; or finally on the node ids. Multilink properties are sorted according to how many links are present.
An item view contains an editor section and a spool section. At the top of an item view, links to superseding and superseded items are always displayed.
The editor section is generated from a template containing <display> tags to insert the appropriate widgets for editing properties.
Here's an example of a basic editor template.
<table> <tr> <td colspan=2> <display call="field('title', size=60)"> </td> </tr> <tr> <td> <display call="field('fixer', size=30)"> </td> <td> <display call="menu('status')> </td> </tr> <tr> <td> <display call="field('nosy', size=30)"> </td> <td> <display call="menu('priority')> </td> </tr> <tr> <td colspan=2> <display call="note()"> </td> </tr> </table>
As shown in the example, the editor template can also request the display of a "note" field, which is a text area for entering a note to go along with a change.
When a change is submitted, the system automatically generates a message describing the changed properties.
If a note is given in the "note" field, the note is appended to the description. The message is then added to the item's message spool (thus triggering the standard detector to react by sending out this message to the nosy list).
The message also displays all of the property values on the item and indicates which ones have changed. An example of such a message might be this:
Polly's taken a turn for the worse - this is now really important! ----- title: Polly Parrot is dead priority: critical status: unread -> in-progress fixer: terry keywords: parrot,plumage,perch,nailed,dead
The spool section lists messages in the item's "messages" property. The index of messages displays the "date", "author", and "summary" properties on the message nodes, and selecting a message takes you to its content.
The <property> tag used in the index may also be used here - it checks to see if the nominated Multilink property has any entries. This can be used to eliminate sections of the spool section if the property has no entries.
<property name="files"> <tr class="strong-header"> <td><b>Files</b></td> </tr> <tr> <td><display call="list('files')"></td> </tr> </property>