Skip to content

Loading…

Include Message field in posted Rally Changeset record #290

Merged
merged 1 commit into from

2 participants

@ghost

check for empty required data parms
add Message field to Changeset post
use repository value from data element for SCMRepository name if set, otherwise use GitHub repo name
pared back on all but two instance variables

@klehman-rally klehman-rally check for empty required data parms, add Message to Changeset post, o…
…btain SCM Repository as repository from data element, pared back on all but two instance variables
156bb2e
@technoweenie technoweenie merged commit 289c7d0 into github:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 17, 2012
  1. @klehman-rally

    check for empty required data parms, add Message to Changeset post, o…

    klehman-rally committed
    …btain SCM Repository as repository from data element, pared back on all but two instance variables
Showing with 67 additions and 61 deletions.
  1. +36 −32 services/rally.rb
  2. +31 −29 test/rally_test.rb
View
68 services/rally.rb
@@ -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
60 test/rally_test.rb
@@ -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,13 +32,13 @@ 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",
}
]
@@ -46,72 +46,74 @@ def test_push
[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
}
]
Something went wrong with that request. Please try again.