Include Message field in posted Rally Changeset record #290

Merged
merged 1 commit into from Apr 18, 2012
View
@@ -4,51 +4,47 @@ class Service::Rally < Service
string :server, :username, :workspace, :repository
password :password
- attr_accessor :wksp_ref, :repo_ref, :user_cache, :chgset_uri
- attr_reader :art_type, :branch, :artifact_detector
+ attr_accessor :wksp_ref, :user_cache
def receive_push
server = data['server']
username = data['username']
password = data['password']
workspace = data['workspace']
- @branch = payload['ref'].split('/')[-1] # most of the time it'll be refs/heads/master ==> master
+ scm_repository = data['repository']
+ raise_config_error("No Server value specified") if server.nil? or server.strip.length == 0
+ raise_config_error("No UserName value specified") if username.nil? or username.strip.length == 0
+ raise_config_error("No Password value specified") if password.nil? or password.strip.length == 0
+ raise_config_error("No Workspace value specified") if workspace.nil? or workspace.strip.length == 0
+ branch = payload['ref'].split('/')[-1] # most of the time it'll be refs/heads/master ==> master
repo = payload['repository']['name']
repo_owner = payload['repository']['owner']['name']
- @chgset_uri = 'https://github.com/%s/%s' % [repo_owner, repo]
+ chgset_uri = 'https://github.com/%s/%s' % [repo_owner, repo]
http.ssl[:verify] = false
if server =~ /^https?:\/\// # if they have http:// or https://, leave server value unchanged
- http.url_prefix = "#{server}/slm/webservice/1.29"
+ http.url_prefix = "#{server}/slm/webservice/1.30"
else
server = "#{server}.rallydev.com" if server !~ /\./ # leave unchanged if '.' in server
- http.url_prefix = "https://#{server}/slm/webservice/1.29"
+ http.url_prefix = "https://#{server}/slm/webservice/1.30"
end
http.basic_auth(username, password)
http.headers['Content-Type'] = 'application/json'
http.headers['X-RallyIntegrationVendor'] = 'Rally'
http.headers['X-RallyIntegrationName'] = 'GitHub-Service'
- http.headers['X-RallyIntegrationVersion'] = '1.0'
+ http.headers['X-RallyIntegrationVersion'] = '1.1'
+ # create the repo in Rally if it doesn't already exist
@wksp_ref = validateWorkspace(workspace)
- @repo_ref = getOrCreateRepo(repo, repo_owner)
-
- @art_type = { 'D' => 'defect', 'DE' => 'defect', 'DS' => 'defectsuite',
- 'TA' => 'task', 'TC' => 'testcase',
- 'S' => 'hierarchicalrequirement',
- 'US' => 'hierarchicalrequirement'
- }
- formatted_id_pattern = '^(%s)\d+[\.:;]?$' % @art_type.keys.join('|') # '^(D|DE|DS|TA|TC|S|US)\d+[\.:;]?$'
- @artifact_detector = Regexp.compile(formatted_id_pattern)
-
+ repo_ref = getOrCreateRepo(scm_repository, repo, repo_owner)
@user_cache = {}
payload['commits'].each do |commit|
artifact_refs = snarfArtifacts(commit['message'])
- addChangeset(commit, artifact_refs)
+ addChangeset(commit, repo_ref, artifact_refs, chgset_uri, branch)
end
end
- def addChangeset(commit, artifact_refs)
+ def addChangeset(commit, repo_ref, artifact_refs, chgset_uri, branch)
author = commit['author']['email']
if !@user_cache.has_key?(author)
user = rallyQuery('User', 'Name,UserName', 'UserName = "%s"' % [author])
@@ -57,13 +53,13 @@ def addChangeset(commit, artifact_refs)
@user_cache[author] = user_ref
end
user_ref = @user_cache[author]
- message = commit['message']
- message = message[0..3999] unless message.size <= 4000
- changeset = { 'SCMRepository' => @repo_ref,
+ message = commit['message'][0..3999] # message max size is 4000 characters
+ changeset = { 'SCMRepository' => repo_ref,
'Revision' => commit['id'],
- 'Author' => user_ref,
'CommitTimestamp' => Time.iso8601(commit['timestamp']).strftime("%FT%H:%M:%S.00Z"),
- 'Uri' => @chgset_uri,
+ 'Author' => user_ref,
+ 'Message' => message,
+ 'Uri' => chgset_uri,
'Artifacts' => artifact_refs # [{'_ref' => 'defect/1324.js'}, {}...]
}
changeset.delete('Author') if user_ref == ""
@@ -84,7 +80,7 @@ def addChangeset(commit, artifact_refs)
commit['removed'].each { |rem| changes << {'Action' => 'R', 'PathAndFilename' => rem } }
changes.each do |change|
change['Changeset'] = chgset_ref
- change['Uri'] = '%s/blob/%s/%s' % [@chgset_uri, @branch, change['PathAndFilename']]
+ change['Uri'] = '%s/blob/%s/%s' % [chgset_uri, branch, change['PathAndFilename']]
chg_item = rallyCreate('Change', change)
end
end
@@ -99,10 +95,11 @@ def validateWorkspace(workspace)
return itemRef(target_workspace[0])
end
- def getOrCreateRepo(repo, repo_owner)
- repo_item = rallyQuery('SCMRepository', 'Name', 'Name = "%s"' % repo)
+ def getOrCreateRepo(scm_repository, repo, repo_owner)
+ scm_repository = scm_repository == nil ? repo : scm_repository
+ repo_item = rallyQuery('SCMRepository', 'Name', 'Name = "%s"' % scm_repository)
return itemRef(repo_item) unless repo_item.nil?
- repo_info = { 'Workspace' => @wksp_ref, 'Name' => repo, 'SCMType' => 'GitHub',
+ repo_info = { 'Workspace' => @wksp_ref, 'Name' => scm_repository, 'SCMType' => 'GitHub',
'Description' => 'GitHub-Service push changesets',
'Uri' => 'http://github.com/%s/%s' % [repo_owner, repo]
}
@@ -114,7 +111,8 @@ def itemRef(item) ref = item['_ref'].split('/')[-2..-1].join('/')[0..-4] end
def rallyWorkspaces()
response = @http.get('Subscription.js?fetch=Name,Workspaces,Workspace&pretty=true')
- raise_config_error('config error') unless response.success?
+ raise_config_error('Config error: credentials not valid for Rally endpoint') if response.status == 401
+ raise_config_error('Config error: Unable to obtain your Rally subscription info') unless response.success?
qr = JSON.parse(response.body)
begin
workspaces = qr['Subscription']['Workspaces']
@@ -146,14 +144,20 @@ def rallyCreate(entity, data)
end
def snarfArtifacts(message)
+ art_type = { 'D' => 'defect', 'DE' => 'defect', 'DS' => 'defectsuite',
+ 'TA' => 'task', 'TC' => 'testcase',
+ 'S' => 'hierarchicalrequirement',
+ 'US' => 'hierarchicalrequirement'
+ }
+ formatted_id_pattern = '^(%s)\d+[\.:;]?$' % art_type.keys.join('|') # '^(D|DE|DS|TA|TC|S|US)\d+[\.:;]?$'
+ artifact_detector = Regexp.compile(formatted_id_pattern)
words = message.gsub(',', ' ').gsub('\r\n', '\n').gsub('\n', ' ').gsub('\t', ' ').split(' ')
- #rally_formatted_ids = words.select { |word| word =~ /^(D|DE|DS|TA|TC|S|US)\d+[\.:;]?$/ }
- rally_formatted_ids = words.select { |word| @artifact_detector.match(word) }
+ rally_formatted_ids = words.select { |word| artifact_detector.match(word) }
artifacts = [] # actually, just the refs
rally_formatted_ids.uniq.each do |fmtid|
next unless fmtid =~ /^(([A-Z]{1,2})\d+)[\.:;]?$/
fmtid, prefix = $1, $2
- entity = @art_type[prefix]
+ entity = art_type[prefix]
artifact = rallyQuery(entity, 'Name', 'FormattedID = "%s"' % fmtid)
next if artifact.nil?
art_ref = itemRef(artifact)
View
@@ -22,7 +22,7 @@ def setup
end
# For now, test is totally happy-path.
- # In future should test for empty data values (server, username, password, workspace)
+ # In future should test for empty data values (server, username, password, workspace, repository)
# raise_config_error on bad form values(server, username, password, workspace)
# graceful failure on inability to create scmrepository, changeset, change based on Rally credentials
# test for no payload
@@ -32,86 +32,88 @@ def setup
def test_push
- @stubs.get '/slm/webservice/1.29/Subscription.js?fetch=Name,Workspaces,Workspace&pretty=true' do |env|
+ @stubs.get '/slm/webservice/1.30/Subscription.js?fetch=Name,Workspaces,Workspace&pretty=true' do |env|
assert_equal 'crubble.rallydev.com', env[:url].host
subs = { 'Name' => "Omicron Bacan Fluffies",
'Errors' => [],
'Warnings' => [],
'Workspaces' => [ {"Name" => "Chloroformer",
- "_ref" => "https://crubble.rallydev.com/slm/webservice/1.29/workspace/662372755.js",
+ "_ref" => "https://crubble.rallydev.com/slm/webservice/1.30/workspace/662372755.js",
"_refObjectName" => "Chlorformer",
}
]
}
[200, {}, JSON.generate({"Subscription" => subs})]
end
- @stubs.get '/slm/webservice/1.29/scmrepository.js' do |env|
+ @stubs.get '/slm/webservice/1.30/scmrepository.js' do |env|
repo = {"Errors" => [],
"Warnings" => [],
"TotalResultCount" => 1, "StartIndex" => 1, "PageSize" => 20,
"Results" => [
- {
- "Name" => "Reservoir Dogs",
- "_type" => "SCMRepository",
- "_ref" => "https://trial.rallydev.com/slm/webservice/1.29/scmrepository/11432875342.js"
- }
- ]
+ {
+ "Name" => "Reservoir Dogs",
+ "_type" => "SCMRepository",
+ "_ref" => "https://trial.rallydev.com/slm/webservice/1.30/scmrepository/11432875342.js"
+ }
+ ]
}
[200, {}, JSON.generate({"QueryResult" => repo})]
end
- @stubs.get '/slm/webservice/1.29/hierarchicalrequirement.js' do |env|
+ @stubs.get '/slm/webservice/1.30/hierarchicalrequirement.js' do |env|
result = artifact_query_response(env[:url])
[200, {}, result]
end
- @stubs.get '/slm/webservice/1.29/defect.js' do |env|
+ @stubs.get '/slm/webservice/1.30/defect.js' do |env|
result = artifact_query_response(env[:url])
[200, {}, result]
end
- @stubs.get '/slm/webservice/1.29/task.js' do |env|
+ @stubs.get '/slm/webservice/1.30/task.js' do |env|
result = artifact_query_response(env[:url])
[200, {}, result]
end
- @stubs.get '/slm/webservice/1.29/testcase.js' do |env|
+ @stubs.get '/slm/webservice/1.30/testcase.js' do |env|
result = artifact_query_response(env[:url])
[200, {}, result]
end
- @stubs.get '/slm/webservice/1.29/user.js' do |env|
+ @stubs.get '/slm/webservice/1.30/user.js' do |env|
assert_equal 'crubble.rallydev.com', env[:url].host
assert_equal 'https', env[:url].scheme
user_item = { "Name" => "Romeo",
"UserName" => "romeo_must_die",
- "_ref" => "https://crubble.rallydev.com/slm/webservice/1.29/user/919235435.js"
+ "_ref" => "https://crubble.rallydev.com/slm/webservice/1.30/user/919235435.js"
}
user_result = {"Errors" => [], "Warnings" => [], "TotalResultCount" => 1, 'Results' => [user_item]}
[200, {}, JSON.generate({'QueryResult' => user_result})]
end
- @stubs.post '/slm/webservice/1.29/scmrepository/create.js' do |env|
- repo_result = {'Object' => {"" => 'http://x.y.z/foo/scmrepository/4433556.js'}}
+ @stubs.post '/slm/webservice/1.30/scmrepository/create.js' do |env|
+ repo_result = {'Object' => {"_ref" => 'http://x.y.z/foo/scmrepository/4433556.js'}}
[200, {}, JSON.generate({'CreateResult' => repo_result})]
end
- @stubs.post '/slm/webservice/1.29/Changeset/create.js' do |env|
+ @stubs.post '/slm/webservice/1.30/Changeset/create.js' do |env|
chgset_result = {"Object" => {"_ref" => 'http://x.y.z/foo/changeset/639214.js'}}
[200, {}, JSON.generate({'CreateResult' => chgset_result})]
end
- @stubs.post '/slm/webservice/1.29/Change/create.js' do |env|
+ @stubs.post '/slm/webservice/1.30/Change/create.js' do |env|
chg_result = {"Object" => {"_ref" => 'http://x.y.z/foo/change/7366456.js'}}
[200, {}, JSON.generate({'CreateResult' => chg_result})]
end
- data = { 'server' => 'crubble',
- 'username' => 'romeo_must_die',
- 'password' => 'Plantrachette',
- 'workspace' => 'Chloroformer'}
+ data = { 'server' => 'crubble',
+ 'username' => 'romeo_must_die',
+ 'password' => 'Plantrachette',
+ 'workspace' => 'Chloroformer',
+ 'repository' => 'Reservoir Dogs'
+ }
payload = rally_test_payload()
svc = service(data, payload)
@@ -133,14 +135,14 @@ def rally_test_payload()
{ "after" => "a47fd41f3aa4610ea527dcc1669dfdb9c15c5425",
"ref" => "refs/heads/master",
"before" => "4c8124ffcf4039d292442eeccabdeca5af5c5017",
- "compare" => "http://github.com/kipster-t/powalla/compare/4c8124ffcf4039d292442eeccabdeca5af5c5017...a47fd41f3aa4610ea527dcc1669dfdb9c15c5425",
+ "compare" => "https://github.com/kipster-t/powalla/compare/4c8124ffcf4039d292442eeccabdeca5af5c5017...a47fd41f3aa4610ea527dcc1669dfdb9c15c5425",
"forced" => false,
"created" => false,
"deleted" => false,
"repository" => {
"name" => "powalla",
- "url" => "http://github.com/kipster-t/powalla",
+ "url" => "https://github.com/kipster-t/powalla",
"owner" => { "name" => "kipster-t", "email" => "klehman@rallydev.com" }
},
@@ -157,7 +159,7 @@ def rally_test_payload()
"added" => ["bus/pricing-model.txt"],
"modified" => ["lib/grit/grit.rb", "test/helper.rb", "test/test_grit.rb"],
"removed" => [],
- "url" => "http://github.com/kipster-t/powalla/commit/06f63b43050935962f84fe54473a7c5de7977325",
+ "url" => "https://github.com/kipster-t/powalla/commit/06f63b43050935962f84fe54473a7c5de7977325",
"distinct" => true
},
{
@@ -168,7 +170,7 @@ def rally_test_payload()
"added" => [],
"modified" => ["test/test_grit.rb"],
"removed" => ["test/test_grotty.rb", "test/test_joobbar.rb"],
- "url" => "http://github.com/kipster-t/powalla/commit/5057e76a11abd02e83b7d3d3171c4b68d9c88480",
+ "url" => "https://github.com/kipster-t/powalla/commit/5057e76a11abd02e83b7d3d3171c4b68d9c88480",
"distinct" => true
},
{
@@ -179,7 +181,7 @@ def rally_test_payload()
"added" => ["docs/messieurs.pdf"],
"modified" => ["README", "lib/grit/commiteur.rb"],
"removed" => ["too_gritty.rb"],
- "url" => "http://github.com/kipster-t/powalla/commit/a47fd41f3aa4610ea527dcc1669dfdb9c15c5425",
+ "url" => "https://github.com/kipster-t/powalla/commit/a47fd41f3aa4610ea527dcc1669dfdb9c15c5425",
"distinct" => true
}
]