Tobias and I have differing expectations of what links should do, and
what actions should occur. Here is what I propose. Rather than having
multiple types of tickets (bugs, tasks, group), have just one ticket
type. Any ticket can link to or be linked to by 1 or many other tickets.
However there are multiple types of links. When a link is created, or
a ticket is resolved (or a change is made to a ticket), an external
script is called that performs the actions associated with that link
type. This has the advantage of not imposing a particular action model
on the rt users, making the system much more flexible and able to be
tailored to a site’s requirements.
The examples below are meant to be /bin/sh scripting, but I probably
have syntax errors. Also I am trying to use the rt 1.x commands, but
some extensions are used (e.g. link query syntax), but I don’t have
any rt docs available as I write this. Also rtq -format uses field
names rather than the proper format strings.
I assume that links point from a source to a destination. Further I
assume that the database has a table called link with fields, data
linktype string source ticketID dest ticketID LinkInfo string
The actions Tobias describes, stalling a ticket when it links to a
newly spawned ticket and opening the parent ticket when the spawned
ticket is resolved can be handled by a tobiaslink. When a tobiaslink
is created, an external script called tobiaslink.create is called with
the following arguments:
by using rtq and rt, all other information about the tickets can
be obtained including ticket states, priorities etc. The
tobiaslink.create script may look like:
stall original ticket when a new ticket is spawned from it
rt -stall $sourceTicketId
-summary “stalled by tobiaslink to $destTicketId”
set a default due date on the new ticket iff it has not been set.
if [ “
rtq -noheader -format 'duedate'” == “” ] ; then
prtdate +2weeks $destTicketId
When the destination (spawned) ticket is resolved, the script
tobiaslink.resolved is called with the sourceTicketId and
destTicketId. The script can look like:
open the source ticket if it is still stalled.
if [ “
rtq -noheader -format status $sourceTicketId” == “stall” ]; then
rt -open $sourceTicketId
-summary "Reopened by tobiaslink to ticket $destTicketId"
I think this implements the actions Tobias is using in his
system. Tobias feel free to correct me if I have misunderstood your
Also, a noActionLink can be used to link a “buy more disk for mail
spool space” to the 47 tickets reporting that mail isn’t being
delivered because your out of space. A noActionLink does exactly what
its name implies. The noactionlink.create script is empty as is the
noactionlink.resolved script. As Tobias said there are some spawned
tickets where the requestor of the original ticket doesn’t need to be
kept up to date. You want to see how many complaints have been caused
by this ticket not being solved, its a one line shell script:
rtq -noheader -linktype noactionlink -format sourceTicketID \ -dest <ticketID> | wc -l
You can also implement a mergelink (my model) that has the semantics
of resolving source tickets when the destination ticket is resolved if
the source ticket doesn’t have any unresolved destination tickets. In
the example of a full mail spool I can create a ticket “fix the stupid
mail spool” and mergelink my 47 tickets to it. When I resolve the
ticket, all 47 tickets that link to this ticket get resolved if no
other links from those tickets are unresolved. The script to do that
may look like:
make sure that $sourceLinkId doesn’t have any linked to tickets
that are still open. Iterate over destination ticket ID’s for
links that aren’t noaction links. Finish with the destLinkId that
triggered calling of this script.
for i in
rtq -noheader -format 'dest' -notlinktype noActionLink \ $sourceLinkId $destLinkId
if [ “
rtq -noheader -format "status" $i” != “resol” ]; then
if [ $i -eq $destLinkId ] ; then
# $i was set to the link that triggered this script therefore # all other links must have been resolved. rt -resolve $sourceLinkId \ -summary "Autoresolved by merge link to $destLinkId"
The rt -resolve command would force rt to analyze $sourceLinkID as the
destination of mergelinks and call this script recusively if needed.
In addition for mergelinks, the priority of the destination should be
the same as the source with the highest priority, so I create the
script mergelink.create to contain:
srcprio=`rtq -noheader -format prio $sourceTicketId` dstprio=`rtq -noheader -format prio $destTicketId` # propigate change in priority along merge links. # so that priority of destination is the same as the source # with the highest priority. if [ $srcprio -gt $destprio ]; then rt -prio $destTicketId $srcprio fi
All rt has to provide is to call the hooks on link creation and for
each link to a ticket being resolved. In fact different link types can
be used between tickets. This allows resolution of a single ticket
(say ticket 3) to reopen some tickets (say ticket 1) and resolve other
tickets (say ticket 2 and 4), depending on whether ticket3 was a
prerequisite for solving ticket1, or was the solution to the problem
(ticket 2 and 4).
To further clarify this how about an example.
1 can’t connect to hosts with netscape
2 ping is broken
3 Can’t send email: error no space on spool/mqueue
You have the above in the queue. You realize that DNS is down. Spawn
4 DNS is down
mergelink 1 and 2 to it (if you choose to stall 1 and 2 automatically
feel free, its just a shell script change). The person working on 3
has come to the conclusion that outgoing mail is backing up because of
the DNS failure. She has cleared space by copying the mail queue to
another disk, but can’t really get email working till DNS is up. So
she does a tobiaslink to ticket 4 stalling ticket 3.
We finally get DNS working and resolve ticket 3. What happens? Tickets
1 and 2 are resolved and email is sent to requestors notifying them of
the resolution. Ticket 4 is reopened and the person working on it
starts flushing the mail queue and the moved mailq by hand.
In addition to the above other semantics such as propigating the
highest priority down the chain can be done by calling a script on any
mergelink.doSourceaction sourceTicketID destTicketID prio
when priority is changed on the sourceTicket. A script like this may
case $3 in
rtq -noheader -format prio $sourceTicketId
rtq -noheader -format prio $destTicketId
# propigate change in priority along merge links.
# so that priority of destination is the same as the source
# with the highest priority.
if [ $srcprio -gt $destprio ]; then
rt -prio $destTicketId $srcprio
If the rt command is executed, the rt program will need to look at all
of the links with source $destTicketId and call apropriate action
programs on them. In this way the link tree can have data propigated
The scripts themselves can be written in any language, sh, perl, tcl,
python etc. All interactions with rt are done via the CLI.
Quips, comments, suggestions, evasions or answers anybody? This seems
a bit too simple, so I am pretty sure that there is something I am
The pseudoarguments to rtq and rt are described below:
-noheader suppresses rt headerlines leaving only the data.
-source treat ticket id as source ticket in link lookups (default)
-dest treat ticket id as destination ticket in link lookups.
-summary allows a one line comment to be included in all transactions