Unfuddle Project template


/ Published in: Ruby
Save to your folder(s)

Written by Joshua W. Frappier


Copy this code and paste it in your HTML
  1. #!/usr/bin/env ruby
  2. # Trac2Unfuddle: The Unfuddle Trac import tool
  3. # Copyright © 2007-2009, Unfuddle LLC. All rights reserved.
  4. # Author: Joshua W. Frappier
  5. # Version: 0.7
  6. #
  7. # No portion of this code may be duplicated or reproduced
  8. # without the express written consent of Unfuddle LLC.
  9. # For more information, contact [email protected].
  10. #
  11. # NOTE: For this script to work, the following gems must be installed:
  12. # sqlite3-ruby, xml-simple
  13. #
  14. # NOTE: You MUST change the values in the section below before
  15. # running the script. Once changed, you can simply run the script
  16. # without any additional parameters:
  17. #
  18. # ruby project.rb
  19. # this importer is based on the Trac2Unfuddle import tool of Joshua W. Frappier
  20. # Author Gianni Metitieri, Swisstimex
  21. # Version: 1.0
  22.  
  23. ########################################################################
  24. # CHANGE THE VALUES IN THIS SECTION
  25. ########################################################################
  26.  
  27. # change these to your own settings
  28. # be sure that the user is an account administrator
  29. UNFUDDLE_SETTINGS = {
  30. :subdomain => 'insert subdomain here',
  31. :username => 'insert username here',
  32. :password => 'insert password here',
  33. :ssl => true # ssl true or false
  34. }
  35.  
  36. # values for the newly created Unfuddle project
  37. # NOTE: this project must not currently exist within the specified account
  38. PROJECT_TITLE = "Imported Project Template"
  39. PROJECT_SHORT_NAME = "template"
  40. PROJECT_DESCRIPTION = "insert project description here!"
  41. THEME = "blue" #[blue, green, grey, orange, purple, red, teal]
  42.  
  43. # Define Component
  44. component = ['User Story', 'Documentation', 'Test Case', 'Project Management','Environment','GUI','Database', 'Functionality', 'Performance','Middleware', 'Look & Feel']
  45.  
  46. # Define Milestones
  47. milestone = ['Backlog', 'Sprint 1', 'Sprint 2', 'Sprint 3']
  48.  
  49. # Define Milestone Due on
  50. due_on = ['02/28/2010', '11/30/2009', '12/31/2009', '01/31/2010']
  51.  
  52. # Define Milestone Status
  53. status = [0, 0, 0, 0]
  54.  
  55. # Define Severity
  56. severity = ['1-Urgent Fix', '2-Must Fix', '3-Should Fix', '4-Could Fix']
  57.  
  58. # Define Version
  59. version = ['Major.Minor.Patch.Build']
  60.  
  61. # Define Category
  62. category = ['General','News', 'Project', 'Team', 'Blog']
  63.  
  64. # Define Customer Field 1
  65. type1 = 'list' # is a list or text
  66. title1 = 'Type' # insert customer title here
  67.  
  68. if type1 == 'list'
  69. customer_1 = ['BUG', 'REQ', 'TASK', 'TECH']
  70. else
  71. end
  72.  
  73. # Define Customer Field 2
  74. type2 = 'text' # is a list or text
  75. title2 = 'Effort' # insert customer title here
  76.  
  77. if type2 == 'list'
  78. customer_2 = ['item1', 'item2', 'item3', 'item4']
  79. else
  80. end
  81.  
  82. # Define Customer Field 1
  83. type3 = 'text' #is a list or text
  84. title3 = 'Value' # insert customer title here
  85.  
  86. if type3 == 'list'
  87. customer_3 = ['item1', 'item2', 'item3', 'item4']
  88. else
  89. end
  90.  
  91. # Define Notebook
  92. title = 'Project Wiki'
  93.  
  94. ########################################################################
  95. # NO NEED TO CHANGE BELOW THIS LINE
  96. ########################################################################
  97. require 'rubygems'
  98. require 'date'
  99. require 'net/https'
  100. require 'xmlsimple'
  101.  
  102. # an adequate hash to xml conversion method
  103. class Hash
  104. def to_xml(options={})
  105. xml = ''
  106. xml += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" unless options[:skip_instruct]
  107. xml += "<#{options[:root]}>" if options[:root]
  108. self.each { |key,val|
  109. key_formatted = key.to_s.gsub('_','-')
  110. case val
  111. when Date:
  112. val_formatted = val.strftime("%Y-%m-%d")
  113. when DateTime, Time:
  114. val_formatted = val.strftime("%Y-%m-%d %H:%M:%S")
  115. when Hash:
  116. val_formatted = val.to_xml(:skip_instruct => true)
  117. else
  118. val_formatted = val.to_s.gsub('&', '&amp;').gsub('>', '&gt;').gsub('<', '&lt;')
  119. end
  120. xml += "<#{key_formatted}>"
  121. xml += val_formatted.to_s
  122. xml += "</#{key_formatted}>"
  123. }
  124. xml += "</#{options[:root]}>" if options[:root]
  125. xml
  126. end
  127. end
  128.  
  129. # convenience method to get a date
  130. class Time
  131. def to_date
  132. ::Date.new(year, month, day)
  133. end
  134. end
  135.  
  136. # get a resource
  137. # returns a hash of the resource
  138. def api_get_hash(short_url)
  139. request = Net::HTTP::Get.new("/api/v1/#{short_url}.xml", {'Accept' => 'application/xml'})
  140. request.basic_auth UNFUDDLE_SETTINGS[:username], UNFUDDLE_SETTINGS[:password]
  141. response = @http.request(request)
  142. if response.code == "200"
  143. XmlSimple.xml_in(response.body, { 'ForceArray' => false })
  144. else
  145. {}
  146. end
  147. end
  148.  
  149. # create a resource via the unfuddle api and return the
  150. # new id of the resource on success
  151. def api_create(resource_type, short_url, attributes)
  152. request = Net::HTTP::Post.new("/api/v1/#{short_url}", {'Accept' => 'application/xml', 'Content-type' => 'application/xml'})
  153. request.basic_auth UNFUDDLE_SETTINGS[:username], UNFUDDLE_SETTINGS[:password]
  154. request.body = attributes.to_xml(:root => resource_type)
  155. response = @http.request(request)
  156. if response.code == "201"
  157. response['Location'].split('/').last.to_i
  158. else
  159. puts "ERROR (#{response.code}):\n" + response.body
  160. 0
  161. end
  162. end
  163.  
  164. # update a resource via the unfuddle api
  165. def api_update(resource_type, short_url, attributes)
  166. request = Net::HTTP::Put.new("/api/v1/#{short_url}", {'Accept' => 'application/xml', 'Content-type' => 'application/xml'})
  167. request.basic_auth UNFUDDLE_SETTINGS[:username], UNFUDDLE_SETTINGS[:password]
  168. request.body = attributes.to_xml(:root => resource_type)
  169. response = @http.request(request)
  170. if response.code == "200"
  171. true
  172. else
  173. puts "ERROR (#{response.code}):\n" + response.body
  174. false
  175. end
  176. end
  177.  
  178. # upload a file to the unfuddle api
  179. # returns the upload key of the file
  180. def api_upload(short_url, path)
  181. request = Net::HTTP::Post.new("/api/v1/#{short_url}.xml", {'Accept' => 'application/xml', 'Content-type' => 'application/octet-stream'})
  182. request.basic_auth UNFUDDLE_SETTINGS[:username], UNFUDDLE_SETTINGS[:password]
  183. path = path.gsub(/[^a-zA-Z0-9_\.\-]/n) {|s| sprintf('%%%02x', s[0]) } unless File.exists?(path)
  184. request.body = File.read(path)
  185. response = @http.request(request)
  186. if response.code == "200"
  187. XmlSimple.xml_in(response.body, { 'ForceArray' => false })['key']
  188. else
  189. nil
  190. end
  191. end
  192.  
  193. # setup the http object for later use
  194. @http = Net::HTTP.new("#{UNFUDDLE_SETTINGS[:subdomain]}.unfuddle.com", UNFUDDLE_SETTINGS[:ssl] ? 443 : 80)
  195. @http.use_ssl = true if UNFUDDLE_SETTINGS[:ssl]
  196. @http.verify_mode = OpenSSL::SSL::VERIFY_NONE if UNFUDDLE_SETTINGS[:ssl]
  197.  
  198.  
  199. # create the project
  200. print "Creating Project..."
  201. project_id = api_create(:project, 'projects', {:title => PROJECT_TITLE, :short_name => PROJECT_SHORT_NAME, :description => PROJECT_DESCRIPTION, :assignee_on_resolve => 'reporter',:close_ticket_simultaneously_default => 0, :enable_time_tracking => 1, :theme => THEME,
  202. :ticket_field1_active => 1, :ticket_field1_title => title1, :ticket_field1_disposition => type1,
  203. :ticket_field2_active => 1, :ticket_field2_title => title2, :ticket_field2_disposition => type2,
  204. :ticket_field3_active => 1, :ticket_field3_title => title3, :ticket_field3_disposition => type3})
  205. print "#{project_id}...done\n"
  206.  
  207. # create the components
  208. index = 0
  209. while index < component.length
  210. print "Creating Component #{component[index]}..."
  211. component_id = api_create(:component, "projects/#{project_id}/components", {:name => component[index]})
  212. print "#{component_id}...done\n"
  213. index += 1
  214. end
  215.  
  216. # create milestones
  217. index = 0
  218. while index < milestone.length
  219. print "Creating Milestone #{milestone[index]}..."
  220. milestone_id = api_create(:milestone, "projects/#{project_id}/milestones", {:title => milestone[index], :due_on => Date.parse(due_on[index]).to_s, :completed => status[index]})
  221. print "#{milestone_id}...done\n"
  222. index += 1
  223. end
  224.  
  225.  
  226. # create severities
  227. index = 0
  228. while index < severity.length
  229. print "Creating Severities #{severity[index]}..."
  230. severity_id = api_create(:severity, "projects/#{project_id}/severities", {:name => severity[index]})
  231. print "#{severity_id}...done\n"
  232. index += 1
  233. end
  234.  
  235. # create versions
  236. index = 0
  237. while index < version.length
  238. print "Creating Versions #{version[index]}..."
  239. version_id = api_create(:version, "projects/#{project_id}/versions", {:name => version[index]})
  240. print "#{version_id}...done\n"
  241. index += 1
  242. end
  243.  
  244. # create customer field 1
  245. if type1 == 'list'
  246. index = 0
  247. while index < customer_1.length
  248. print "Creating Customer Field 1 #{customer_1[index]}..."
  249. customer_1_id = api_create(:custom_field_value, "projects/#{project_id}/custom_field_values", {:value => customer_1[index], :field_number => 1})
  250. print "#{customer_1_id}...done\n"
  251. index += 1
  252. end
  253. else
  254. end
  255.  
  256. # create customer field 2
  257. if type2 == 'list'
  258. index = 0
  259. while index < customer_2.length
  260. print "Creating Customer Field 2 #{customer_2[index]}..."
  261. customer_2_id = api_create(:custom_field_value, "projects/#{project_id}/custom_field_values", {:value => customer_2[index], :field_number => 2})
  262. print "#{customer_2_id}...done\n"
  263. index += 1
  264. end
  265. else
  266. end
  267.  
  268. # create customer field 3
  269. if type3 == 'list'
  270. index = 0
  271. while index < customer_3.length
  272. print "Creating Customer Field 3 #{customer_3[index]}..."
  273. customer_3_id = api_create(:custom_field_value, "projects/#{project_id}/custom_field_values", {:value => customer_3[index], :field_number => 3})
  274. print "#{customer_3_id}...done\n"
  275. index += 1
  276. end
  277. else
  278. end
  279.  
  280. # create category
  281. index = 0
  282. while index < category.length
  283. print "Creating category #{category[index]}..."
  284. category_id = api_create(:category, "projects/#{project_id}/categories", {:name => category[index]})
  285. print "#{category_id}...done\n"
  286. index += 1
  287. end
  288.  
  289.  
  290. # create notebook
  291. print "Creating Notebook..."
  292. notebook_id = api_create(:notebook, "projects/#{project_id}/notebooks", {:title => title})
  293. print "#{notebook_id}...done\n"

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.