Creating the Python script

The Python script for bug system integration is called review_action.py. This script needs to

  • identify your bug tracking system
  • define the actions that need to take place for the integration
  • specify the issue information you want to send to the bug tracker

Optionally, you can also

  • customize the text for the 'Create a ticket' button to appear on the issue details page
  • display a hyperlink on the issue details page to the bug entry in your bug tracking system, as well as showing comments from the bug tracker
  • include diagnostic messages in your script

Example: Creating a connection to Bugzilla

Requirement: In order to fully run this example, you will need to include an external Python JSON library in order to de-serialize and parse the JSON object. You can find a working implementation of the library used in our example here: http://sourceforge.net/projects/json-py/ Alternatively, you can use a different third-party Python JSON library.

In this example, the Python script specifies a connection to the open-source bug tracking system Bugzilla when the user clicks the 'Send to Bugzilla' button in Static Code Analysis. As is typical for the review_action.py script, it defines the issue data that should be sent to Bugzilla, such as the issue ID, the checker that found the issue, the checker message, and the issue's URL. (For a list of the predefined variables for the script, see Using predefined variables.)

The script also includes definition #ui.name to define the custom name for the button, Send to Bugzilla, instead of the default value (Create a ticket). The set_bug_id method specifies a link to Bugzilla, which will become a hyperlink to the issue's corresponding Bugzilla bug, and the success_msg method defines a diagnostic message.

The variable below for current_path is dependent on where you unpack your Python library.

import os.path, urllib, urllib2, getpass, sys, inspect, os, re
import sys
current_path = "<path to unpacked json script>"
sys.path.append(current_path)
import json

#Button name
#ui.name:Send to Bugzilla

# Parse the project name based on the issue URL
def getProjectName():
        #Retrieve project name
        m = re.search('project=(\w*),', issue.url)
        project_name = m.group(1)
        return project_name

# Send a request to Bugzilla REST API
def bugzillaAPIRequest(proj_name):

        # URL with authentication information
        host = "https://api-dev.bugzilla.mozilla.org/test/latest/bug?username=prezioso@gmail.com&password=klocwork"

        # Bugzilla attributes
        product = "FoodReplicator"
        component = "Salt"
        version = "1.0"
        target = "---"
        summary = "%s | %s | %s | %s | %s | %s | %s" % (issue.id, issue.code, issue.severity, issue.severityCode, issue.status, issue.url, proj_name)
        op_sys = "Linux"
        platform = "All"
        
        # JSON object
        jdata = '''{"product": "%s", "component": "%s", "version": "%s", "target": "%s", "summary": "%s", "opsys": "%s", "platform": "%s"}''' % (product, component, version, target, summary, op_sys, platform)   
        clen = len(jdata)
        
        # HTTP Request
        req = urllib2.Request(host, jdata, {'Content-Type': 'application/json', 'Accept': 'application/json', 'Content-Length': clen})
        try:
                resp = urllib2.urlopen(req)
        except urllib2.URLError, e:
                success(e.code)
                # Expecting 201, resource created status code
                if (e.code is 201):
                        content = e.read()
                        string = str(content)
                        obj = json.read(string)
                        # Retrieving ref URL and the id
                        ref=obj['ref']
                        id=obj['id']
                        set_bug_id(id)
                        return "%s" % (ref)
        
        return "fail"
                
proj_name = getProjectName()
successmsg = bugzillaAPIRequest(proj_name)
        
if (successmsg is "fail"):
        fail("\nERROR - HTTP POST REQUEST")
                
successmsg = successmsg.decode('string_escape')
success(successmsg)

After the script has been installed, the issue window looks like the following display, with the BUG ID field showing the hyperlink to the issue's Bugzilla entry.

Image:bug_tracker_11.png

Example: Integrating with Rational Team Concert

The following example provides a walkthrough of the steps you need to do in order to integrate your Klocwork environment with Rational Team Concert.

How to navigate RTC xml documents

To create a work item in RTC you must first identify the relevant URL and project key by requesting a series of xml documents from the RTC server . The steps will be similar to:

  1. Fetch the xml root services document from the RTC REST API: http(s)://yourRTCserver:port/ccm/rootservices
  2. Extract the Services Catalog URL which is the "rdf:resource" attribute in "oslc_cm:cmServiceProviders"
            <oslc_cm:cmServiceProviders
                     xmlns:oslc_cm="http://open-services.net/xmlns/cm/1.0/"
                     rdf:resource="http(s):// yourRTCserver:port /ccm/oslc/workitems/catalog" 
            />
  3. Find the relevant project’s service provider URL (attribute "rdf:resource" of element "oslc_disc:services") in the Service Catalog by identifying the project’s title (element dc:title of element oslc_disc:ServiceProvider).
    The URL contains a unique project key (e.g. _Day3sOHaEeO1tdkD6QbZUQ).
  4. Extract the appropriate service factory (<dc:title>Location for creation of change requests</dc:title> of element “oslc_cm:factory” of element “oslc_cm:changeRequests oslc” ) URL ("oslc_cm:url") from the service provider URL
            <oslc_cm:changeRequests oslc_cm:version="1.0">
                            …
                            <oslc_cm:factory>
                                    >dc:title<Location for creation of change requests>/dc:title<
                                    >oslc_cm:url< http(s):// yourRTCserver:port /ccm/oslc/contexts/_Day3sOHaEeO1tdkD6QbZUQ/workitems</oslc_cm:url>
                            </oslc_cm:factory>
                            …
            </oslc_cm:changeRequests>
  5. Post the work item to the factory URL. For example a JSON encoded work item could be:
    {
                    "dc:title":"Klocwork ID 42: Suspicious dereference of pointer in function call before NULL check: cvs\\src\\checkin.c",
                    
                    "dc:description":"This issue was detected by Klocwork static code analysis.
                     \n
                     \t\t\nId: 42    URL: http(s)://yourKlocworkServer:port/review/kw-review.htm#issuedetails_goto:problemid=42,project=CVS,view_id=1
                     \nExported to RTC by: jchapman
                     \n
                     \nFile: cvs\\src\\checkin.c
                     \n
                     \nChecker: RNPD.CALL
                     \nType: Suspicious dereference of pointer in function call before NULL check
                     \nMessage: Suspicious dereference of pointer 'options' by passing argument 1 to function 'strcmp' at line 63 before NULL check at line 76
                     \nSeverity: Critical(1)
                     \nStatus: Analyze
                     \nState: Existing
                     \nOwner: azukich
                     \nLast Update: No Updates
                     \nHistory: \n",
                            
                            "dc:type": "task",
                            
                            "oslc_cm:priority": " http(s):// yourRTCserver:port /ccm/oslc/enumerations/_Day3sOHaEeO1tdkD6QbZUQ/priority/priority.literal.l4"
    }
  6. If successful, the URL to the work item will in “Location” within the response header and the work item ID will be in the “dc:identifier” element of the response.

How to handle authentication

By default the RTC server is setup to use forms based authentication so it is necessary to look for an authentication response request when posting anything to the RTC server. For example:

req = urllib2.Request(targetUrl, data,{'Content-Type': 'application/json', 'Accept' : "application/xml"})
                        try :
                        response = urllib2.urlopen(req)
                        if 'X-com-ibm-team-repository-web-auth-msg' in response.info() and response.info()['X-com-ibm-team-repository-web-auth-msg'] == 'authrequired' :
                        reqLogon = urllib2.Request(hostbase+"/j_security_check",urllib.urlencode({'j_username': str(rtc_username), 'j_password': str(rtc_password)}), {'Content-Type': 'application/x-www-form-urlencoded', 'Accept' : "application/json"})
                        response = urllib2.urlopen(reqLogon)
                        if 'X-com-ibm-team-repository-web-auth-msg' in response.info() and response.info()['X-com-ibm-team-repository-web-auth-msg'] == 'authfailed' :
                        fail("RTC logon failed")
                        else :
                        if data is not None:
                        # if we posted data then we need to repost it
                        response = urllib2.urlopen(req)
                        except HTTPError, e:
                        eData = str(e.read())
                        if hasattr(e, 'code'):
                        if e.code == 201 :# 201 indicates success with a RTC response
                        # process response
                        elif e.code == 400 : # 400 indicated RTC rejected the request
                        # process error message

How to handle field values

Field value enumerators (e.g. “oslc_cm:priority”) are defined on a per project basis and can be customized by the RTC administrator. To discover the configured values for a particular project, use your browser and the project’s unique project key to query the server. For example:

http(s):// yourRTCserver:port/ccm/oslc/enumerations/_Day3sOHaEeO1tdkD6QbZUQ/priority

Need help? Contact the Static Code Analysis Professional Services Team.

The Static Code Analysis Professional Services Team has experience creating basic scripts for Bugzilla, JIRA, and IBM Rational Team Concert. The scripts can be customized for your installation. Contact the Static Code Analysis Professional Services Team for help.

Customizing the 'Create a ticket' button

Placing the review_action.py script in the projects_root/config directory causes Static Code Analysis to display the 'Create a ticket' button on the issue details pages in Static Code Analysis for the project. (You may need to refresh the browser to see the link.) If you want to specify a different name for the button, add the following line to your script:

#ui.name:<my custom button>

For example:

#ui.name:Send to Bugzilla

After the script has been installed, the issue window shows the new button:

Image:bug_tracker_31.png

You can put Japanese characters in the button name by including UTF-8 encoding in the review_action.py script.

Including diagnostic messages

If the bug report is filed successfully when the 'Create a ticket' button is clicked, the 'Ticket created' message pops up on the Static Code Analysis window. If it fails, 'Bug reporting failed' appears. To provide custom diagnostic messages for success and failure, use these methods in the Python script:

  • success(custom_message)
  • fail(custom_message)

If you call the fail() method in the script, it will interrupt further script execution.

Placing the script in projects_root

When you've completed your review_action.py script, place it in the projects_root/config directory for the project.

Using predefined variables

For the review_action.py script, the following variables have been predefined:

variable.field Usage
username the name of the user who activated the script with the Create a ticket button
issue a Python object of class Issue containing information about the script in the following fields:
issue.id the identifier of the issue in Static Code Analysis
issue.groupId the identifier of the group that an issue belongs to in Static Code Analysis. A zero value indicates that group calculations are turned off and this variable should not be used.
issue.name the name of the issue from the Static Code Analysis issue details page
issue.message the checker message for the issue in Static Code Analysis
issue.file the file in which the issue occurs
issue.code the name of the checker that found that issue
issue.severity the severity of the issue in textual form (not numeric)
issue.severityCode the severity of the issue in numeric form
issue.state the state of the issue - Existing or Fixed
issue.status the status of the issue, such as Fix or Analyze
issue.lastUpdateDate the time of the last update in milliseconds
issue.owner the owner of the issue
issue.project the name of the Klocwork project
issue.url the URL of the issue in Static Code Analysis
issue.history an array with citing history events. Each event is an object of class StatusHistoryEvent with the following fields:
  • date - date of the event in milliseconds
  • userid - user name of the event creator
  • owner - new issue owner
  • status - new issue status
  • comment - comment created in the process of citing
issue.bugTrackerId the bug tracker ID of the issue in Static Code Analysis