Integrating Plastic SCM with Trac Issue Tracking

Friday, December 03, 2010 0 Comments

Hello, Plastic SCM user community! My name is John Posner, and I'm happy to introduce myself as a new member, having joined the Codice team as a technical writer. Actually, the technical writer. I arrive with some pretty good SCM credentials, having spent most of the past two decades in this field. I was on the original team that developed Rational ClearCase, and was also the first tech writer at AccuRev. (AccuRev claimed to be "ClearCase done better" -- with some justification, IMHO. An AccuRev stream managed to serve as both a branch and a label – pretty cool, but hard for many people to understand and use.)

I've spent the past couple of weeks learning Plastic SCM, and now I'd like to share some of what I've learned. Codice makes a big deal of "task-based development" and a "branch per task" approach, so that's one of the areas I focused on. Since Codice doesn't have its own issue-tracking system (ITS), this approach can work only if Plastic SCM plays well with existing, popular ITSs. And since this sort of thing is pretty complex, I was hoping to find some juicy bugs -- one of a tech writer's greatest joys!

I took a look at Codice's list of ITS integrations, currently eight of them, and decided that Trac was in my comfort zone. This open-source ITS is built in Python, which I've used a lot over the past decade. (The Codice guys seem to be into Ruby for scripting, but I forgive them.) So I fired up my Windows 7 laptop, an HP Pavilion dv7, and jumped in.

Download Party!

Here's a list of the software I downloaded, all of it free:

Whoa – what's Subversion doing on that list? It turns out that the XML-RPC plugin code is stored in a Subversion repository -- go figure!

In this age of Windows wizards, software installation is pretty straightforward, so here's just a brief outline of how I proceeded:

  1. I installed Plastic SCM in the standard way, into the standard location C:\Program Files\PlasticSCM.
  2. I installed Python in the standard way, into the standard location C:\Python26.
    (OK, I confess: both Plastic SCM and Python were already installed on this machine when I started this little exercise.)
  3. I installed Python's distutils 0.6 module using the wizard in setuptools-0.6c11.win32-py2.6.exe. This places easy_install.exe in folder C:\Python26\Scripts.
  4. At a command prompt, I used this command to install Trac:
    easy_install Trac==0.12

    As with distutils programs, Trac programs get placed in folder C:\Python26\Scripts.
  5. In a Web browser, I went to trac.edgewall.org/wiki/TracStandalone and copied this script for creating username-password entries, storing it as file trac_digest.py:

    from optparse import OptionParser
    # The md5 module is deprecated in Python 2.5
    try:
        from hashlib import md5
    except ImportError:
        from md5 import md5
    realm = 'trac'
    
    # build the options
    usage = "usage: %prog [options]"
    parser = OptionParser(usage=usage)
    parser.add_option("-u", "--username",action="store",
        dest="username", type = "string",
        help="the username for whom to generate a password")
    parser.add_option("-p", "--password",action="store",
        dest="password", type = "string",
        help="the password to use")
    parser.add_option("-r", "--realm",action="store",
        dest="realm", type = "string",
        help="the realm in which to create the digest")
    (options, args) = parser.parse_args()
    
    # check options
    if (options.username is None) or (options.password is None):
        parser.error("You must supply both the username and password")
    if (options.realm is not None):
        realm = options.realm
    
    # Generate the string to enter into the htdigest file
    kd = lambda x: md5(':'.join(x)).hexdigest()
    print ':'.join((options.username, realm,
                    kd([options.username, realm, options.password])))
    
  6. It was a bit too soon to install the Trac XML-RPC plugin at this point, so I didn't. A little massaging of the Trac environment is required first.

Setting Up the SCM and ITS

With both the SCM and ITS systems installed, I set up some data to be used by their integration. Chances are you're like me: more familiar with Plastic SCM than with Trac. So I'll gloss over the Plastic SCM details and spend more time on the Trac details.

To set up a Plastic SCM environment for the integration, I performed the following operations in Plastic SCM's beautiful, capable, speedy GUI: create a new repository; create a new workspace; create a few text files in the workspace; in the Items view, place the files under source control:


... and in the Labels view, create label BL_01 and attach it to everything in sight:


I just had to illustrate those last two commands; they're right there when you need them, sitting at the top of their context menus. Sweet! (Another confession: to create files in the workspace, you need to go outside the Plastic SCM GUI.)

Next, I set up a Trac issue-tracking environment in folder c:\nov9trac:

  • Go to the Python scripts folder, where the Trac executables were installed, and initialize a new environment:
    > cd C:\Python26\Scripts
    > trac-admin C:\nov9trac initenv
  • Create a digest entry for user jjp (that's me), using the script I download in Step #5 above, and store it as a one-line text file
    > python trac_digest.py –-username=jjp –-password=any > auth_digest.txt
  • Give myself permission to do just about anything in this Trac environment
    > trac-admin C:\nov9trac permission add jjp TRAC_ADMIN
  • Start a Trac Web server for this environment, listening on port 8765 and using the one-entry digest as its username-password database. The command prompt window becomes the Trac Web server's console
    > tracd -–port=8765 --auth=nov9trac,auth_digest.txt,trac C:\nov9trac


With the Web server up and running, I fired up a Web browser and connected to the server. I made sure to enter a URL that included the exact hostname/portnumber combo that appeared in the Web server's startup console message:


A Trac intro page appeared, where I logged in as jjp (the only Trac user so far):


Then, I created some Trac issue records, called "tickets".


For Ticket #1, I chose the title Alpha Project; for ticket #2, Beta Project, and so on. (Inspired choices, huh?)

Setting Up the Integration

Just about all the work I had done so far was to set up the Plastic SCM and Trac environments separately. Now for the fun part: getting the systems to work together. The integration is based on a tried-and-true (that is, old) network communication technology: XML-RPC. Here's the basic idea:

When a particular branch is selected in the BranchExplorer, Plastic SCM makes a remote procedure call (RPC) to the Trac server. The server returns field values from the Trac ticket that is associated with the branch.

Each Plastic SCM branch is associated with a Trac ticket, and each Trac ticket represents an engineering task. Et voila (or the Spanish equivalent), "branch per task" is a reality.

Setting up the integration was just as straightforward – configuring the Trac server to use XML-RPC, and establishing a protocol in Plastic SCM for associating branches with tickets/tasks. Here's how I enabled XML-RPC support in Trac:

  1. I downloaded and installed Trac's XML-RPC plugin (which involved performing a Subversion checkout):
    > cd C:\Python26\Scripts
    > easy_install -Z -U http://trac-hacks.org/svn/xmlrpcplugin/trunk
  2. I enabled the XML-RPC plugin by adding these lines to the end of the Trac environment's configuration file, C:\nov9trac\conf\trac.ini:
    [components]
    tracrpc.* = enabled
  3. XML-RPC calls are to be made by an unauthenticated Trac user, named anonymous. So I created this user and give him (her? it?) permission to make the calls:
    > python trac_digest.py -–username=anonymous –-password=X >> auth_digest.txt
    > trac-admin C:\nov9trac permission add anonymous XML_RPC
And here's how I turned on the Trac integration in Plastic SCM:

  1. In the GUI, I selected Issue Tracking in the top-level toolbar:

  2. In the Issue Tracking dialog, I (1) selected Trac as the issue tracking system; (2) specified a branch prefix, establishing the protocol that all Plastic SCM branches with names of the form tktNNN are to be linked with Trac ticket NNN; and (3) specified the URL of the Trac server – the same URL I used when creating the Trac tickets.


    To make sure that I'd done my work correctly, I (4) clicked the Test Connection button (and held my breath). It worked the very first time – no kidding!

Using the Integration

Finally, it was time to test the integration between the Plastic SCM and Trac issue tracking systems! Using the BranchExplorer, I created a subbranch of /main, naming it tkt0011. (Would those leading zeros cause a problem?) I refreshed the BranchExplorer display, and sure enough – the new subbranch was annotated with the title of Trac ticket #11: Kappa Project.


So far, so good!

Next, I clicked Show Extended Information in the BranchExplorer's toolbar, and then clicked Edgewall Trac Extension in the extended info panel. Uh-oh, the panel was blank. Then I figured out that the BranchExplorer is not telepathic – I was thinking about the /main/tkt0011 branch, but I hadn't selected that branch. Clicking on the branch revealed a very nice extended information display:


And to get access to the actual Ticket #11, I double-clicked in the extended information panel:


That's the integration – simple to set up and simple to use!

I know what you're thinking: did I find any bugs in this facility? Sure I did! If Trac's Web server is not running, trying to launch the BranchExplorer causes the Plastic SCM GUI to hang. I also thought of an enhancement: when looking at a ticket, the Trac user should be able to see what files have been created/changed for that task. It should be easy to implement, since it's just the set of revisions created on a particular Plastic SCM branch. That's one of the beauties of a branch-per-task approach. I'll try to get the Codice guys to address both these items. Bye for now!

0 comentarios: