Saturday, March 15, 2008

Create Bugs with Bugzilla's XMLRPC Web Service and Groovy

The other day I was looking into moving development bugs from one bug system over to Bugzilla. Someone in my group pointed out that Bugzilla had an XMLRPC Web service exposed at:
http://bugzilla-address/xmlrpc.cgi.

The current bug system had a feature that would export the bugs into XML data. I exported the bug data, moved the XML file to my local machine, and opened the Groovy Console. Let's check out how simple things can be.

Here is sort of what the XML looks like:

...
<issues>
<issue>
<product>Product Name</product>
<component>Component Name</component>
<summary>Summary</summary>
<version>1.0</version>
<description>Description</description>
<opsys>Operating System</opsys>
<platform>Platform</platform>
<priority>High</priority>
<severity>Low</severity>
<status>Open</status>
</issue>
</issues>
...


Here is what we need to import into our Groovy script:

...
import groovy.util.XmlSlurper

import java.util.Map
import java.util.HashMap
import java.net.ServerSocket

import org.apache.commons.httpclient.*
import org.apache.xmlrpc.client.*
...


Here is our class, main method, dependencies, and setup of the XMLRPCClient (I needed the HTTPClient and XMLRpcCommonsTransportFactory because Bugzilla likes to deal with Cookies after logged in):

...
public class BugzillaCreateFromXML {

// get the xml data of our issues in the .xml file
def xmlData = new XmlSlurper().parse(new File("C:/issues.xml"))

def httpClient = new HttpClient()
def rpcClient = new XmlRpcClient()
def factory = new XmlRpcCommonsTransportFactory(rpcClient)
def config = new XmlRpcClientConfigImpl()factory.setHttpClient(httpClient)

rpcClient.setTransportFactory(factory)
config.setServerURL(new URL("http://bugzilla-addres/xmlrpc.cgi"))
rpcClient.setConfig(config)

public static void main(String[] args) {
    // here is where the work getting done
    // map of the login data
    Map loginMap = new HashMap()
    loginMap.put("login", "admin")
    loginMap.put("password", "admin")
    loginMap.put("rememberlogin", "Bugzilla_remember")

    // login to bugzilla
    def loginResult = rpcClient.execute("User.login", loginMap)
    println loginResult

    // map of the bug data
    Map bugMap = new HashMap()

    // iterate through each issue
    xmlData.issue.each {
        bugMap.put("product", it.product.text())
        bugMap.put("component", it.component.text())
        bugMap.put("summary", it.summary.text())
        bugMap.put("version", it.version.text())
        bugMap.put("description", it.description.text())
        bugMap.put("op_sys", it.opsys.text())
        bugMap.put("platform", it.platform.text())
        bugMap.put("priority", it.priority.text())
        bugMap.put("severity", it.severity.text())
        bugMap.put("status", it.status.text())

        // create bug
        def createResult = rpcClient.execute("Bug.create", bugMap)
            println createResult

            // clear bugMap so we can re-populate it with the next issue
            bugMap.clear()
        }
    }
}
...

That is it. It took me about 30 minutes to parse the XML file and loop through each node with Groovy. I spent about an hour finding out that HTTPClient was also needed, I originally started working with Groovy's XMLRPC library. You need to have the appropriate Apache XMLRPC Client libraries in place in your Groovy lib directory. I ran this from the Groovy Console and it did exactly what I needed it to do. The Groovy file is available for download .