Python スクリプトの作成

バグ システムの統合のための Python スクリプトは、review_action.pyと呼ばれます。このスクリプトでは次のことを行う必要があります。

  • バグ追跡システムの特定
  • 統合のために行う必要があるアクションの定義
  • バグ トラッカーに送信する指摘情報の指定

オプションで、次のことを行うこともできます。

  • 指摘の詳細ページに表示する [Create a ticket] ボタンのテキストのカスタマイズを行う
  • バグ トラッカーからのコメントの表示に加え、バグ追跡システムのバグ エントリーへの指摘の詳細ページでハイパーリンクの表示を行う
  • スクリプトに診断メッセージを含める

例: Bugzilla への接続を確立する

要件: この例を完全に実行するには、JSON オブジェクトのシリアル化を解除してパースするために、外部 Python JSON ライブラリをインクルードする必要があります。ここで示す例で使用したライブラリの使用可能な実装例は、以下で確認できます。http://sourceforge.net/projects/json-py/ あるいは、別のサードパーティ Python JSON ライブラリを使用することもできます。

この例では、ユーザーが Static Code Analysis で [Send to Bugzilla] ボタンをクリックすると、Python スクリプトはオープンソースのバグ追跡システム Bugzilla への接続を指定します。review_action.py スクリプトでは一般的ですが、指摘 ID、指摘を見つけたチェッカー、チェッカー メッセージ、指摘の URL など、Bugzilla に送信する必要がある指摘データを定義します(スクリプトの定義済み変数のリストについては、[定義済み変数の使用] を参照してください)。

また、スクリプトには、デフォルト値 (Create a ticket) の代わりにボタンのカスタム名 Send to Bugzilla を定義する定義 #ui.nameも含まれます。set_bug_id メソッドは、指摘の対応する Bugzilla のバグへのハイパーリンクになる、Bugzilla へのリンクを指定します。また、success_msg メソッドは、診断メッセージを定義します。

current_path の以下の変数は、Python ライブラリのアンパック先に応じて異なります。

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)

スクリプトをインストールすると、指摘ウィンドウは次のように表示されます。BUG ID フィールドは指摘の Bugzilla のエントリーへのハイパーリンクを示しています。

Image:bug_tracker_11.png

例: Rational Team Concert との統合

以下の例は、お使いの Klocwork 環境を Rational Team Concert と統合するために必要なステップを詳細に示したものです。

RTC xml ドキュメントのナビゲート方法

RTC で業務詳細を作成するには、まず、RTC サーバーから一連の xml ドキュメントを要求することにより、関連 URL とプロジェクトキーを特定する必要があります。このステップは次のステップと似ています。

  1. RTC REST API から xml ルートサービスドキュメントをフェッチします: http(s)://yourRTCserver:port/ccm/rootservices
  2. "oslc_cm:cmServiceProviders" 内 "rdf:resource" 属性である Services Catalog URL を抽出します。
            <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. プロジェクトのタイトル (element dc:title of element oslc_disc:ServiceProvider) を特定することにより、Service Catalog の中から関連するプロジェクトのサービスプロバイダー URL (要素 "oslc_disc:services" の属性 "rdf:resource" of element) を探します。
    URL には一意のプロジェクトキー (_Day3sOHaEeO1tdkD6QbZUQ など) が含まれています。
  4. サービスプロバイダの URL から、適切なサービスファクトリーの URL ("oslc_cm:url") (要素 "oslc_cm:changeRequests oslc" の要素 "oslc_cm:factory" の<dc:title>Location for creation of change requests</dc:title>) を抽出します
            <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. 業務詳細をファクトリー URL にアップします。たとえば、JSON エンコードの業務詳細は次のようになります。
    {
                    "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. 動作が正常に行われた場合、業務詳細がアップされた URL は、レスポンスヘッダー内の "Location" に、業務詳細の ID はレスポンス要素 "dc:identifier"; に表示されます。

認証の取り扱い方法

初期設定では、RTC サーバーがフォームの記入による認証方法を採用するようにセットアップされています。そのため、RTC サーバーに何かをアップする際には、認証レスポンスリクエストを検索する必要があります。例:

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

フィールド値の取り扱い方法

フィールド値の列挙子 ("oslc_cm:priority" など) は、プロジェクトごとに定義され、RTC 管理者がカスタマイズすることができます。特定のプロジェクトに対して設定された値を発見するには、お使いのブラウザーとプロジェクトに一意のプロジェクトキーを使ってサーバーにクエリを出します。例:

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

ヘルプが必要ですか?静的コード解析プロフェッショナルサービスチームにお問い合わせください。

静的コード解析プロフェッショナルサービスチームは、Bugzilla、JIRA、および IBM Rational Team Concert 向けのベーシックスクリプトを作成してきた長い実績があります。スクリプトはご希望のインストールに合わせてカスタマイズすることができます。ヘルプが必要な場合は、静的コード解析プロフェッショナルサービスチームまでお問い合わせください。

[Create a ticket] ボタンのカスタマイズ

review_action.py スクリプトを projects_root/config ディレクトリに配置すると、Static Code Analysis により、プロジェクトの Static Code Analysis で、指摘の詳細ページに [Create a ticket] ボタンが表示されます。(リンクを表示するにはブラウザーの更新が必要になることがあります)ボタンに別の名前を指定する場合は、スクリプトに次の行を追加します。

#ui.name:<my custom button>

例:

#ui.name:Send to Bugzilla

スクリプトがインストールされると、指摘ウィンドウに新しいボタンが表示されます。

Image:bug_tracker_31.png

ボタン名に日本語を使用するには、review_action.py スクリプトに UTF-8 エンコーディングを含めます。

診断メッセージの組み込み

[Create a ticket] ボタンをクリックしたときにバグレポートが正常に保管されると、Static Code Analysis ウィンドウに、[Ticket created] メッセージが表示されます。失敗すると、[Bug reporting failed] と表示されます。成功時と失敗時のカスタム診断メッセージを指定するには、Python スクリプトで次のメソッドを使用します。

  • success(custom_message)
  • fail(custom_message)

スクリプトで fail() メソッドを呼び出すと、スクリプトの実行がさらに中断されます。

projects_root へのスクリプトの配置

review_action.pyスクリプトが完了したら、プロジェクトのprojects_root/configディレクトリに配置します。

定義済み変数の使用

review_action.py スクリプトの場合、次の変数があらかじめ定義されています。

variable.field 使用方法
username [Create a ticket] ボタンでスクリプトをアクティブにしたユーザーの名前
issue 次のフィールドのスクリプトに関する情報が含まれているクラス Issue の Python オブジェクト
issue.id Static Code Analysis での指摘の識別子
issue.groupId Static Code Analysis で指摘が属するグループの識別子
issue.name Static Code Analysis 指摘の詳細ページからの指摘の名前
issue.message Static Code Analysis での指摘のチェッカーメッセージ
issue.file 指摘が出現したファイル
issue.code 指摘を見つけたチェッカーの名前
issue.severity テキスト形式 (数値以外) の指摘の重要度
issue.severityCode 数値形式の指摘の重要度
issue.state 指摘のステート - 既存 (Existing) または修正済み (Fixed)
issue.status 要修正 (Fix) または解析 (Analyze) などの指摘のステータス
issue.lastUpdateDate 最終更新の時間 (ミリ秒単位)
issue.owner 指摘のオーナー
issue.project Klocwork プロジェクトの名前
issue.url Static Code Analysis での指摘の URL
issue.history 更新履歴イベントを持つ配列。各イベントは、次のフィールドがあるクラス StatusHistoryEvent のオブジェクトです。
  • date - イベントの日付 (ミリ秒単位)
  • userid - イベント作成者のユーザー名
  • owner - 新しい指摘のオーナー
  • status - 新しい指摘ステータス
  • comment - 更新プロセスで作成されたコメント
issue.bugTrackerId Static Code Analysis での指摘のバグトラッカー ID