Permalink
Browse files

First version of the Rational Team Concert github plugin

  • Loading branch information...
1 parent c82b5da commit a42dbf25664cc06b9df82dd980980765bfdf3208 Filip Wieladek committed Aug 19, 2012
Showing with 131 additions and 0 deletions.
  1. +24 −0 docs/rational_team_concert
  2. +107 −0 services/rational_team_concert.rb
View
24 docs/rational_team_concert
@@ -0,0 +1,24 @@
+This service integrates github with Rational Team Concert (http://www.jazz.net). The service automatically adds comments into work item specified by the commit message. Additionally, this hook allows you to create new work items from commits.
+
+Use the pattern "[#<workItemNumber>] Commit text" to add a comment to the work item with the number specified in the commit message. E.g.
+ "[#32] Fix an annoying bug."
+
+Note that the '#' is optional.
+
+Use the pattern "[workItemType] Fix an annoying bug" to create a new work item for type workItemType. Note, that you have to enter the workItemType id instead of the name. E.g.
+ "[defect] Fox an annoying bug"
+
+This implementation supports both form based and basic authentication.
+
+Install Notes
+-------------
+
+A user with the correct licenses to add comments and create work items needs to be created.
+
+Configuring the github hook:
+
+1. Server Url - This is your server url (including the jazz application suffix). A valid example would be https://yourdomain:port/jazz or https://yourdomain:port/ccm.
+2. Username - This is the username of the user used to access your Rational Team Concert instance.
+3. Password - This is the password of the user used to access your Rational Team Concert instance.
+4. Project Area UUID - This is the uuid of your project area. It is needed to create new work items. You can find out the uuid by accessing your projet using the web ui (using the admin panel). The uuid will be after the itemId parameter in the url. E.g. itemId=_VZsIQOehEeGMALe74yZ8ZQ. Enter just the itemId, which in this example is _VZsIQOehEeGMALe74yZ8ZQ
+5. Basic Authentication - Check this option if you have configured your server to use basic authentication instead of form authentication.
View
107 services/rational_team_concert.rb
@@ -0,0 +1,107 @@
+class Service::RationalTeamConcert < Service
+ string :server_url, :username, :project_area_uuid
+ password :password
+ boolean :basic_authentication
+ white_list :server_url, :username, :basic_authentication
+
+ def receive_push
+ checkSettings
+ prepare
+ authenticate
+ commit_changes
+ end
+
+ def checkSettings
+ raise_config_error "Server Url url not set" if data['server_url'].blank?
+ raise_config_error "username not set" if data['username'].blank?
+ raise_config_error "password not set" if data['password'].blank?
+ raise_config_error "Project Area UUID is not set" if data['project_area_uuid'].blank?
+ end
+
+ def prepare
+ http.headers['X-com-ibm-team-userid']= data['username']
+ end
+
+ def authenticate
+ if data['basic_authentication']
+ http.basic_auth data['username'], data['password']
+ else
+ form_based_authentification
+ end
+ end
+
+ def form_based_authentification
+ res= http_get '%s/authenticated/identity' % data['server_url']
+ if not 'authrequired'.eql? res.headers['X-com-ibm-team-repository-web-auth-msg']
+ raise_config_error "Invalid authentication url. The response did not include a X-com-ibm-team-repository-web-auth-msg header"
+ end
+ http.headers['Cookie']= res.headers['set-cookie']
+ http.headers['Content-Type']= 'application/x-www-form-urlencoded'
+
+ res= http_post '%s/authenticated/j_security_check' % data['server_url'],
+ Faraday::Utils.build_nested_query(http.params.merge(:j_username => data['username'], :j_password => data['password']))
+
+ if 'authrequired'.eql? res.headers['X-com-ibm-team-repository-web-auth-msg']
+ raise_config_error "Invalid Username or Password"
+ end
+
+ http.headers['Content-Type']= ''
+ res= http_get '%s/authenticated/identity' % data['server_url']
+ http.headers['Cookie']= res.headers['set-cookie']
+ end
+
+ def commit_changes
+ http.headers['Content-Type']= 'application/json'
+ http.headers['oslc-core-version']= '2.0'
+ http.headers['accept']= 'application/json'
+
+ payload['commits'].each do |commit|
+ next if commit['message'] =~ /^x /
+ commit['message'].match(/\[(#?(\d+)|[a-zA-Z0-9]+)[^\]]*\]/)
+ next unless $1
+
+ comment_body= generate_comment_body commit
+ work_item= $2 ? get_work_item($2) : new_work_item(commit, $1)
+ post_comment work_item, comment_body
+ end
+ end
+
+ def generate_comment_body (commit)
+
+ comment_body= "[Message] #{commit['message']}<br/>" +
+ "[Author] #{commit['author']['name']}(#{commit['author']['email']})<br/>" +
+ "[Url] #{commit['url']}<br/>"
+
+ comment_body= comment_body + "[Modified]<br/>#{commit['modified'].join('<br/>')}<br/>" if commit['modified'].length > 0
+ comment_body= comment_body + "[Added]<br/>#{commit['added'].join('<br/>')}<br/>" if commit['added'].length > 0
+ comment_body= comment_body + "[Removed]<br/>#{commit['removed'].join('<br/>')}<br/>" if commit['removed'].length > 0
+ return comment_body
+ end
+
+ def get_work_item (work_item_number)
+ res= http_get "%s/resource/itemName/com.ibm.team.workitem.WorkItem/%s?oslc.properties=oslc:discussedBy" % [ data['server_url'], work_item_number ]
+ return res.body
+ end
+
+ def new_work_item (commit, work_item_type)
+ url= "%s/oslc/contexts/%s/workitems/%s" % [data['server_url'], data['project_area_uuid'], work_item_type]
+ work_item= { 'dcterms:title' => commit['message']}
+ res= http_post url, work_item.to_json
+ raise_config_error "Work item was not created. Make sure that its possible to create work items with no additional required fields" unless res.status == 201
+ return res.body
+ end
+
+ def post_comment(work_item, comment_body)
+ comment_url= get_comment_url work_item
+ comment= { 'dcterms:description' => comment_body }
+ res= http_post comment_url, comment.to_json
+ raise_config_error "Not possible to add comments with the current setup" unless res.status == 201
+ end
+
+ def get_comment_url (work_item)
+ answer= JSON.parse(work_item)
+ discussedBy= answer['oslc:discussedBy']
+ raise_config_error "Invalid OSLC response. Expected to receive oslc:discussedBy in the response" unless discussedBy
+ return "#{discussedBy['rdf:resource']}/oslc:comment"
+ end
+end

0 comments on commit a42dbf2

Please sign in to comment.