Add a Discussion to a Rally Task/Defect using the python api bindings

OK so we’ve started using rally as our scrum tool in work. Since we use github a lot for tracking issues reported by external users, we wanted to enforce some github > rally integration. As part of my investigations into this, I found myself wanting to add a discussion item to a defect, using the pyral python bindings. This was not at all obvious (to me at least), and the documentation knocking around for the rally api, and the python bindings, also didn’t seem to contain the information needed.

Initially, I thought I could just update the defect with some text passed in to the ‘Discussion’ field, in the same way you would when updating the ‘Notes’ field. For example, to update the Notes for a defect, you would do this:

rally = Rally(server, user, password, project=project)

defectID = 'DE100'
notes = 'some text'

# build the data dict
defect_data = {"FormattedID": defectID, "Notes": notes}

# update the defect
defect = rally.update('Defect', defect_data)

# did it work?
print defect.Notes
some text

 

However, trying to do the same for the discussion does not:

rally = Rally(server, user, password, project=project)

defectID = 'DE100'
discussion = 'some discussion text'

# build the data dict
defect_data = {"FormattedID": defectID, "Discussion": discussion}

# update the defect
defect = rally.update('Defect', defect_data)

# did it work? (no)
print defect.Discussion
[]

 

OK, this *kind* of makes sense. ‘Notes’ is a single field associated with the defect. When we update it, we literally wipe out what was there with our new text.  Fields like ‘Title’ and ‘Description’ behave in the same way.  However, discussions in rally are different – each discussion post has at least a user and some text associated with it, and each one is in effect it’s own item. There’s a hint to this in the output at the end of the last script:

print defect.Discussion
[]

 

We see here that if there were any discussion entries, they would be returned in a list.  And in fact, not just a list of text entries, but a list of objects.  Here’s what the output from a defect object with some discussion entries looks like:

print defect.Discussion
[<pyral.entity.ConversationPost at 0x10968e350>,
<pyral.entity.ConversationPost at 0x10969c050>,
<pyral.entity.ConversationPost at 0x10969c250>,
<pyral.entity.ConversationPost at 0x10969c1d0>,
<pyral.entity.ConversationPost at 0x10969c390>]

 

Interesting…what’s a pyral.entity.ConversationPost object when it’s at home? Well, to cut a long story short, it turns out that a Discussion entry (or ConversationPost as we’ll call it from now on), is actually an artifact in rally, just the same as a defect, or a story, or a task.  In this is the crux of the matter…

To add a discussion to a defect, what we actually need to do is create a new ConversationPost, and pass it some data so it knows which defect to associate itself with.

Turns out this is pretty easy:

rally = Rally(server, user, password, project=project)

defectID = 'DE100'
discussion_text = 'this is a discussion entry'

# get the defect object so we can extract it's oid (unique object number)
defect = rally.get('Defect', query='FormattedID = %s' % defectID, instance=True)

# build the data dict
discussion_data = {"Artifact": defect.oid, "Text": discussion_text}

# create the discussion
discussion = rally.create('ConversationPost', discussion_data)

# did it work?
print discussion.Text
this is a discussion entry

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>