1
|
require 'rexml/document'
|
2
|
require 'active_record'
|
3
|
require 'yaml'
|
4
|
require 'config/environment'
|
5
|
|
6
|
|
7
|
|
8
|
module JiraMigration
|
9
|
include REXML
|
10
|
|
11
|
file = File.new('backup_jira.xml')
|
12
|
doc = Document.new file
|
13
|
$doc = doc
|
14
|
|
15
|
CONF_FILE = "map_jira_to_redmine.yml"
|
16
|
|
17
|
$MIGRATED_USERS_BY_NAME = {} # Maps the Jira username to the Redmine Rails User object
|
18
|
$MIGRATED_ISSUE_TYPES = {}
|
19
|
$MIGRATED_ISSUE_STATUS = {}
|
20
|
$MIGRATED_ISSUE_PRIORITIES = {}
|
21
|
|
22
|
$MIGRATED_ISSUE_TYPES_BY_ID = {}
|
23
|
$MIGRATED_ISSUE_STATUS_BY_ID = {}
|
24
|
$MIGRATED_ISSUE_PRIORITIES_BY_ID = {}
|
25
|
|
26
|
def self.get_all_options()
|
27
|
# return all options
|
28
|
# Issue Type, Issue Status, Issue Priority
|
29
|
ret = {}
|
30
|
ret["types"] = self.get_jira_issue_types()
|
31
|
ret["status"] = self.get_jira_status()
|
32
|
ret["priorities"] = self.get_jira_priorities()
|
33
|
|
34
|
return ret
|
35
|
end
|
36
|
def self.get_list_from_tag(xpath_query)
|
37
|
# Get a tag node and get all attributes as a hash
|
38
|
ret = []
|
39
|
$doc.elements.each(xpath_query) {|node| ret.push(node.attributes.rehash)}
|
40
|
|
41
|
return ret
|
42
|
end
|
43
|
|
44
|
class BaseJira
|
45
|
attr_reader :tag
|
46
|
attr_accessor :new_record
|
47
|
MAP = {}
|
48
|
|
49
|
def map
|
50
|
self.class::MAP
|
51
|
end
|
52
|
|
53
|
def initialize(node)
|
54
|
@tag = node
|
55
|
end
|
56
|
|
57
|
def method_missing(key, *args)
|
58
|
if key.to_s.start_with?("jira_")
|
59
|
attr = key.to_s.sub("jira_", "")
|
60
|
return @tag.attributes[attr]
|
61
|
end
|
62
|
puts "Method missing: #{key}"
|
63
|
raise NoMethodError key
|
64
|
end
|
65
|
|
66
|
def run_all_redmine_fields
|
67
|
ret = {}
|
68
|
self.methods.each do |method_name|
|
69
|
m = method_name.to_s
|
70
|
if m.start_with?("red_")
|
71
|
mm = m.to_s.sub("red_", "")
|
72
|
ret[mm] = self.send(m)
|
73
|
end
|
74
|
end
|
75
|
return ret
|
76
|
end
|
77
|
def migrate
|
78
|
all_fields = self.run_all_redmine_fields()
|
79
|
pp("Saving:", all_fields)
|
80
|
record = self.retrieve
|
81
|
if record
|
82
|
record.update_attributes(all_fields)
|
83
|
else
|
84
|
record = self.class::DEST_MODEL.new all_fields
|
85
|
end
|
86
|
if self.respond_to?("before_save")
|
87
|
self.before_save(record)
|
88
|
end
|
89
|
record.save!
|
90
|
record.reload
|
91
|
self.map[self.jira_id] = record
|
92
|
self.new_record = record
|
93
|
if self.respond_to?("post_migrate")
|
94
|
self.post_migrate(record)
|
95
|
end
|
96
|
return record
|
97
|
end
|
98
|
def retrieve
|
99
|
self.class::DEST_MODEL.find_by_name(self.jira_id)
|
100
|
end
|
101
|
end
|
102
|
|
103
|
class JiraProject < BaseJira
|
104
|
DEST_MODEL = Project
|
105
|
MAP = {}
|
106
|
|
107
|
def retrieve
|
108
|
self.class::DEST_MODEL.find_by_identifier(self.red_identifier)
|
109
|
end
|
110
|
def post_migrate(new_record)
|
111
|
if !new_record.module_enabled?('issue_tracking')
|
112
|
new_record.enabled_modules << EnabledModule.new(:name => 'issue_tracking')
|
113
|
end
|
114
|
$MIGRATED_ISSUE_TYPES.values.uniq.each do |issue_type|
|
115
|
if !new_record.trackers.include?(issue_type)
|
116
|
new_record.trackers << issue_type
|
117
|
end
|
118
|
end
|
119
|
end
|
120
|
|
121
|
# here is the tranformation of Jira attributes in Redmine attribues
|
122
|
def red_name
|
123
|
self.jira_name
|
124
|
end
|
125
|
def red_description
|
126
|
self.jira_name
|
127
|
end
|
128
|
def red_identifier
|
129
|
ret = self.jira_key.downcase
|
130
|
return ret
|
131
|
end
|
132
|
end
|
133
|
|
134
|
class JiraUser < BaseJira
|
135
|
DEST_MODEL = User
|
136
|
MAP = {}
|
137
|
def retrieve
|
138
|
user = self.class::DEST_MODEL.find_by_login(self.red_login)
|
139
|
if !user
|
140
|
user = self.class::DEST_MODEL.find_by_mail(self.jira_emailAddress)
|
141
|
end
|
142
|
|
143
|
return user
|
144
|
end
|
145
|
def migrate
|
146
|
super
|
147
|
$MIGRATED_USERS_BY_NAME[self.jira_userName] = self.new_record
|
148
|
end
|
149
|
|
150
|
# First Name, Last Name, E-mail, Password
|
151
|
# here is the tranformation of Jira attributes in Redmine attribues
|
152
|
def red_firstname()
|
153
|
self.jira_firstName
|
154
|
end
|
155
|
def red_lastname
|
156
|
self.jira_lastName
|
157
|
end
|
158
|
def red_mail
|
159
|
self.jira_emailAddress
|
160
|
end
|
161
|
def red_password
|
162
|
self.jira_userName
|
163
|
end
|
164
|
def red_login
|
165
|
self.jira_userName
|
166
|
end
|
167
|
def before_save(new_record)
|
168
|
new_record.login = red_login
|
169
|
end
|
170
|
#def red_username
|
171
|
# self.jira_name
|
172
|
#end
|
173
|
end
|
174
|
|
175
|
class JiraComment < BaseJira
|
176
|
DEST_MODEL = Journal
|
177
|
MAP = {}
|
178
|
|
179
|
def initialize(node)
|
180
|
super
|
181
|
# get a body from a comment
|
182
|
# comment can have the comment body as a attribute or as a child tag
|
183
|
@jira_body = @tag.attributes["body"] || @tag.elements["body"].text
|
184
|
end
|
185
|
|
186
|
def jira_marker
|
187
|
return "FROM JIRA: #{self.jira_id}\n"
|
188
|
end
|
189
|
def retrieve
|
190
|
Journal.first(:conditions => "notes LIKE '#{self.jira_marker}%'")
|
191
|
end
|
192
|
|
193
|
# here is the tranformation of Jira attributes in Redmine attribues
|
194
|
def red_notes
|
195
|
self.jira_marker + "\n" + @jira_body
|
196
|
end
|
197
|
def red_created_on
|
198
|
DateTime.parse(self.jira_created)
|
199
|
end
|
200
|
def red_user
|
201
|
# retrieving the Rails object
|
202
|
$MIGRATED_USERS_BY_NAME[self.jira_author]
|
203
|
end
|
204
|
def red_journalized
|
205
|
# retrieving the Rails object
|
206
|
JiraIssue::MAP[self.jira_issue]
|
207
|
end
|
208
|
end
|
209
|
|
210
|
class JiraIssue < BaseJira
|
211
|
DEST_MODEL = Issue
|
212
|
MAP = {}
|
213
|
#attr_reader :jira_id, :jira_key, :jira_project, :jira_reporter,
|
214
|
# :jira_type, :jira_summary, :jira_assignee, :jira_priority
|
215
|
# :jira_resolution, :jira_status, :jira_created, :jira_resolutiondate
|
216
|
attr_reader :jira_description
|
217
|
|
218
|
|
219
|
def initialize(node_tag)
|
220
|
super
|
221
|
@jira_description = @tag.elements["description"].text if @tag.elements["description"]
|
222
|
end
|
223
|
def jira_marker
|
224
|
return "FROM JIRA: #{self.jira_key}\n"
|
225
|
end
|
226
|
def retrieve
|
227
|
Issue.first(:conditions => "description LIKE '#{self.jira_marker}%'")
|
228
|
end
|
229
|
|
230
|
def red_project
|
231
|
# needs to return the Rails Project object
|
232
|
proj = self.jira_project
|
233
|
JiraProject::MAP[proj]
|
234
|
end
|
235
|
def red_subject
|
236
|
#:subject => encode(issue.title[0, limit_for(Issue, 'subject')]),
|
237
|
self.jira_summary
|
238
|
end
|
239
|
def red_description
|
240
|
dsc = self.jira_marker + "\n"
|
241
|
if @jira_description
|
242
|
dsc += @jira_description
|
243
|
else
|
244
|
dsc += self.red_subject
|
245
|
end
|
246
|
return dsc
|
247
|
end
|
248
|
def red_priority
|
249
|
name = $MIGRATED_ISSUE_PRIORITIES_BY_ID[self.jira_priority]
|
250
|
return $MIGRATED_ISSUE_PRIORITIES[name]
|
251
|
end
|
252
|
def red_created_on
|
253
|
Time.parse(self.jira_created)
|
254
|
end
|
255
|
def red_updated_on
|
256
|
Time.parse(self.jira_updated)
|
257
|
end
|
258
|
def red_status
|
259
|
name = $MIGRATED_ISSUE_STATUS_BY_ID[self.jira_status]
|
260
|
return $MIGRATED_ISSUE_STATUS[name]
|
261
|
end
|
262
|
def red_tracker
|
263
|
type_name = $MIGRATED_ISSUE_TYPES_BY_ID[self.jira_type]
|
264
|
return $MIGRATED_ISSUE_TYPES[type_name]
|
265
|
end
|
266
|
def red_author
|
267
|
$MIGRATED_USERS_BY_NAME[self.jira_reporter]
|
268
|
end
|
269
|
def red_assigned_to
|
270
|
$MIGRATED_USERS_BY_NAME[self.jira_assignee]
|
271
|
end
|
272
|
|
273
|
end
|
274
|
|
275
|
class JiraAttachment < BaseJira
|
276
|
DEST_MODEL = Attachment
|
277
|
MAP = {}
|
278
|
|
279
|
def retrieve
|
280
|
self.class::DEST_MODEL.find_by_disk_filename(self.red_filename)
|
281
|
end
|
282
|
def before_save(new_record)
|
283
|
new_record.container = self.red_container
|
284
|
pp(new_record)
|
285
|
end
|
286
|
|
287
|
# here is the tranformation of Jira attributes in Redmine attribues
|
288
|
#<FileAttachment id="10084" issue="10255" mimetype="image/jpeg" filename="Landing_Template.jpg"
|
289
|
# created="2011-05-05 15:54:59.411" filesize="236515" author="emiliano"/>
|
290
|
def red_filename
|
291
|
self.jira_filename.gsub(/[^\w\.\-]/,'_') # stole from Redmine: app/model/attachment (methods sanitize_filenanme)
|
292
|
end
|
293
|
def red_disk_filename
|
294
|
Attachment.disk_filename(self.jira_issue+self.jira_filename)
|
295
|
end
|
296
|
def red_content_type
|
297
|
self.jira_mimetype.to_s.chomp
|
298
|
end
|
299
|
def red_filesize
|
300
|
self.jira_filesize
|
301
|
end
|
302
|
|
303
|
def red_created_on
|
304
|
DateTime.parse(self.jira_created)
|
305
|
end
|
306
|
def red_author
|
307
|
$MIGRATED_USERS_BY_NAME[self.jira_author]
|
308
|
end
|
309
|
def red_container
|
310
|
JiraIssue::MAP[self.jira_issue]
|
311
|
end
|
312
|
end
|
313
|
|
314
|
|
315
|
def self.parse_projects()
|
316
|
# PROJECTS:
|
317
|
# for project we need (identifies, name and description)
|
318
|
# in exported data we have name and key, in Redmine name and descr. will be equal
|
319
|
# the key will be the identifier
|
320
|
projs = []
|
321
|
$doc.elements.each('/*/Project') do |node|
|
322
|
proj = JiraProject.new(node)
|
323
|
projs.push(proj)
|
324
|
end
|
325
|
|
326
|
migrated_projects = {}
|
327
|
projs.each do |p|
|
328
|
#puts "Name and descr.: #{p.red_name} and #{p.red_description}"
|
329
|
#puts "identifier: #{p.red_identifier}"
|
330
|
migrated_projects[p.jira_id] = p
|
331
|
end
|
332
|
#puts migrated_projects
|
333
|
return projs
|
334
|
end
|
335
|
|
336
|
def self.parse_users()
|
337
|
users = []
|
338
|
#users = self.get_list_from_tag('/*/OSUser')
|
339
|
# For users in Redmine we need:
|
340
|
# First Name, Last Name, E-mail, Password
|
341
|
# In Jira, the fullname and email are property (a little more hard to get)
|
342
|
|
343
|
$doc.elements.each('/entity-engine-xml/User') do |node|
|
344
|
user = JiraUser.new(node)
|
345
|
users.push(user)
|
346
|
end
|
347
|
|
348
|
return users
|
349
|
end
|
350
|
|
351
|
ISSUE_TYPE_MARKER = "(choose a Redmine Tracker)"
|
352
|
DEFAULT_ISSUE_TYPE_MAP = {
|
353
|
# Default map from Jira (key) to Redmine (value)
|
354
|
# the comments on right side are Jira definitions - http://confluence.atlassian.com/display/JIRA/What+is+an+Issue#
|
355
|
"Bug" => "Bug", # A problem which impairs or prevents the functions of the product.
|
356
|
"Improvement" => "Feature", # An enhancement to an existing feature.
|
357
|
"New Feature" => "Feature", # A new feature of the product.
|
358
|
"Task" => "Task", # A task that needs to be done.
|
359
|
"Custom Issue" => "Support", # A custom issue type, as defined by your organisation if required.
|
360
|
}
|
361
|
def self.get_jira_issue_types()
|
362
|
# Issue Type
|
363
|
issue_types = self.get_list_from_tag('/*/IssueType')
|
364
|
#migrated_issue_types = {"jira_type" => "redmine tracker"}
|
365
|
migrated_issue_types = {}
|
366
|
issue_types.each do |issue|
|
367
|
migrated_issue_types[issue["name"]] = DEFAULT_ISSUE_TYPE_MAP.fetch(issue["name"], ISSUE_TYPE_MARKER)
|
368
|
$MIGRATED_ISSUE_TYPES_BY_ID[issue["id"]] = issue["name"]
|
369
|
end
|
370
|
return migrated_issue_types
|
371
|
end
|
372
|
|
373
|
ISSUE_STATUS_MARKER = "(choose a Redmine Issue Status)"
|
374
|
DEFAULT_ISSUE_STATUS_MAP = {
|
375
|
# Default map from Jira (key) to Redmine (value)
|
376
|
# the comments on right side are Jira definitions - http://confluence.atlassian.com/display/JIRA/What+is+an+Issue#
|
377
|
"Open" => "New", # This issue is in the initial 'Open' state, ready for the assignee to start work on it.
|
378
|
"In Progress" => "In Progress", # This issue is being actively worked on at the moment by the assignee.
|
379
|
"Resolved" => "Resolved", # A Resolution has been identified or implemented, and this issue is awaiting verification by the reporter. From here, issues are either 'Reopened' or are 'Closed'.
|
380
|
"Reopened" => "Assigned", # This issue was once 'Resolved' or 'Closed', but is now being re-examined. (For example, an issue with a Resolution of 'Cannot Reproduce' is Reopened when more information becomes available and the issue becomes reproducible). From here, issues are either marked In Progress, Resolved or Closed.
|
381
|
"Closed" => "Closed", # This issue is complete. ## Be careful to choose one which a "issue closed" attribute marked :-)
|
382
|
}
|
383
|
def self.get_jira_status()
|
384
|
# Issue Status
|
385
|
issue_status = self.get_list_from_tag('/*/Status')
|
386
|
migrated_issue_status = {}
|
387
|
issue_status.each do |issue|
|
388
|
migrated_issue_status[issue["name"]] = DEFAULT_ISSUE_STATUS_MAP.fetch(issue["name"], ISSUE_STATUS_MARKER)
|
389
|
$MIGRATED_ISSUE_STATUS_BY_ID[issue["id"]] = issue["name"]
|
390
|
end
|
391
|
return migrated_issue_status
|
392
|
end
|
393
|
|
394
|
ISSUE_PRIORITY_MARKER = "(choose a Redmine Enumeration Issue Priority)"
|
395
|
DEFAULT_ISSUE_PRIORITY_MAP = {
|
396
|
# Default map from Jira (key) to Redmine (value)
|
397
|
# the comments on right side are Jira definitions - http://confluence.atlassian.com/display/JIRA/What+is+an+Issue#
|
398
|
"Blocker" => "Immediate", # Highest priority. Indicates that this issue takes precedence over all others.
|
399
|
"Critical" => "Urgent", # Indicates that this issue is causing a problem and requires urgent attention.
|
400
|
"Major" => "High", # Indicates that this issue has a significant impact.
|
401
|
"Minor" => "Normal", # Indicates that this issue has a relatively minor impact.
|
402
|
"Trivial" => "Low", # Lowest priority.
|
403
|
}
|
404
|
def self.get_jira_priorities()
|
405
|
# Issue Priority
|
406
|
issue_priority = self.get_list_from_tag('/*/Priority')
|
407
|
migrated_issue_priority = {}
|
408
|
issue_priority.each do |issue|
|
409
|
migrated_issue_priority[issue["name"]] = DEFAULT_ISSUE_PRIORITY_MAP.fetch(issue["name"], ISSUE_PRIORITY_MARKER)
|
410
|
$MIGRATED_ISSUE_PRIORITIES_BY_ID[issue["id"]] = issue["name"]
|
411
|
end
|
412
|
return migrated_issue_priority
|
413
|
end
|
414
|
|
415
|
def self.parse_comments()
|
416
|
ret = []
|
417
|
$doc.elements.each('/*/Action[@type="comment"]') do |node|
|
418
|
comment = JiraComment.new(node)
|
419
|
ret.push(comment)
|
420
|
end
|
421
|
return ret
|
422
|
end
|
423
|
|
424
|
def self.parse_issues()
|
425
|
ret = []
|
426
|
$doc.elements.each('/*/Issue') do |node|
|
427
|
issue = JiraIssue.new(node)
|
428
|
ret.push(issue)
|
429
|
end
|
430
|
return ret
|
431
|
end
|
432
|
|
433
|
def self.parse_attachments()
|
434
|
attachs = []
|
435
|
$doc.elements.each('/*/FileAttachment') do |node|
|
436
|
attach = JiraAttachment.new(node)
|
437
|
attachs.push(attach)
|
438
|
end
|
439
|
|
440
|
return attachs
|
441
|
end
|
442
|
end
|
443
|
|
444
|
|
445
|
|
446
|
|
447
|
namespace :jira_migration do
|
448
|
|
449
|
desc "Generates the configuration for the map things from Jira to Redmine"
|
450
|
task :generate_conf => :environment do
|
451
|
conf_file = JiraMigration::CONF_FILE
|
452
|
conf_exists = File.exists?(conf_file)
|
453
|
if conf_exists
|
454
|
puts "You already have a conf file"
|
455
|
print "You want overwrite it ? [y/N] "
|
456
|
overwrite = STDIN.gets.match(/^y$/i)
|
457
|
end
|
458
|
|
459
|
if !conf_exists or overwrite
|
460
|
# Let's give the user all options to fill out
|
461
|
options = JiraMigration.get_all_options()
|
462
|
|
463
|
File.open(conf_file, "w"){ |f| f.write(options.to_yaml) }
|
464
|
|
465
|
puts "This migration script needs the migration table to continue "
|
466
|
puts "Please... fill the map table on the file: '#{conf_file}' and run again the script"
|
467
|
puts "To start the options again, just remove the file '#{conf_file} and run again the script"
|
468
|
exit(0)
|
469
|
end
|
470
|
end
|
471
|
|
472
|
desc "Gets the configuration from YAML"
|
473
|
task :pre_conf => :environment do
|
474
|
conf_file = JiraMigration::CONF_FILE
|
475
|
conf_exists = File.exists?(conf_file)
|
476
|
|
477
|
if !conf_exists
|
478
|
Rake::Task['jira_migration:generate_conf'].invoke
|
479
|
end
|
480
|
$confs = YAML.load_file(conf_file)
|
481
|
end
|
482
|
|
483
|
desc "Tests all parsers!"
|
484
|
task :test_all_migrations => [:environment, :pre_conf,
|
485
|
:test_parse_projects,
|
486
|
:test_parse_users,
|
487
|
:test_parse_comments,
|
488
|
:test_parse_issues,
|
489
|
] do
|
490
|
puts "All parsers was run! :-)"
|
491
|
end
|
492
|
|
493
|
desc "Tests all parsers!"
|
494
|
task :do_all_migrations => [:environment, :pre_conf,
|
495
|
:migrate_issue_types,
|
496
|
:migrate_issue_status,
|
497
|
:migrate_issue_priorities,
|
498
|
:migrate_projects,
|
499
|
:migrate_users,
|
500
|
:migrate_issues,
|
501
|
:migrate_comments,
|
502
|
:migrate_attachments,
|
503
|
] do
|
504
|
puts "All migrations done! :-)"
|
505
|
end
|
506
|
|
507
|
|
508
|
desc "Migrates Jira Issue Types to Redmine Trackes"
|
509
|
task :migrate_issue_types => [:environment, :pre_conf] do
|
510
|
|
511
|
JiraMigration.get_jira_issue_types()
|
512
|
types = $confs["types"]
|
513
|
types.each do |key, value|
|
514
|
t = Tracker.find_or_create_by_name(value)
|
515
|
t.save!
|
516
|
t.reload
|
517
|
$MIGRATED_ISSUE_TYPES[key] = t
|
518
|
end
|
519
|
puts "Migrated issue types"
|
520
|
end
|
521
|
|
522
|
desc "Migrates Jira Issue Status to Redmine Status"
|
523
|
task :migrate_issue_status => [:environment, :pre_conf] do
|
524
|
JiraMigration.get_jira_status()
|
525
|
status = $confs["status"]
|
526
|
status.each do |key, value|
|
527
|
s = IssueStatus.find_or_create_by_name(value)
|
528
|
s.save!
|
529
|
s.reload
|
530
|
$MIGRATED_ISSUE_STATUS[key] = s
|
531
|
end
|
532
|
puts "Migrated issue status"
|
533
|
end
|
534
|
|
535
|
desc "Migrates Jira Issue Priorities to Redmine Priorities"
|
536
|
task :migrate_issue_priorities => [:environment, :pre_conf] do
|
537
|
JiraMigration.get_jira_priorities()
|
538
|
priorities = $confs["priorities"]
|
539
|
|
540
|
priorities.each do |key, value|
|
541
|
p = IssuePriority.find_or_create_by_name(value)
|
542
|
p.save!
|
543
|
p.reload
|
544
|
$MIGRATED_ISSUE_PRIORITIES[key] = p
|
545
|
end
|
546
|
puts "Migrated issue priorities"
|
547
|
end
|
548
|
|
549
|
desc "Migrates Jira Projects to Redmine Projects"
|
550
|
task :migrate_projects => :environment do
|
551
|
projects = JiraMigration.parse_projects()
|
552
|
projects.each do |p|
|
553
|
#pp(p)
|
554
|
p.migrate
|
555
|
end
|
556
|
end
|
557
|
|
558
|
desc "Migrates Jira Users to Redmine Users"
|
559
|
task :migrate_users => :environment do
|
560
|
users = JiraMigration.parse_users()
|
561
|
users.each do |u|
|
562
|
#pp(u)
|
563
|
u.migrate
|
564
|
end
|
565
|
end
|
566
|
|
567
|
desc "Migrates Jira Issues to Redmine Issues"
|
568
|
task :migrate_issues => :environment do
|
569
|
issues = JiraMigration.parse_issues()
|
570
|
issues.each do |i|
|
571
|
#pp(i)
|
572
|
i.migrate
|
573
|
end
|
574
|
end
|
575
|
|
576
|
desc "Migrates Jira Issues Comments to Redmine Issues Journals (Notes)"
|
577
|
task :migrate_comments => :environment do
|
578
|
comments = JiraMigration.parse_comments()
|
579
|
comments.each do |c|
|
580
|
#pp(c)
|
581
|
c.migrate
|
582
|
end
|
583
|
end
|
584
|
|
585
|
desc "Migrates Jira Issues Attachments to Redmine Attachments"
|
586
|
task :migrate_attachments => :environment do
|
587
|
attachs = JiraMigration.parse_attachments()
|
588
|
attachs.each do |a|
|
589
|
#pp(c)
|
590
|
a.migrate
|
591
|
end
|
592
|
end
|
593
|
|
594
|
# Tests.....
|
595
|
desc "Just pretty print Jira Projects on screen"
|
596
|
task :test_parse_projects => :environment do
|
597
|
projects = JiraMigration.parse_projects()
|
598
|
projects.each {|p| pp(p.run_all_redmine_fields) }
|
599
|
end
|
600
|
|
601
|
desc "Just pretty print Jira Users on screen"
|
602
|
task :test_parse_users => :environment do
|
603
|
users = JiraMigration.parse_users()
|
604
|
users.each {|u| pp( u.run_all_redmine_fields) }
|
605
|
end
|
606
|
|
607
|
desc "Just pretty print Jira Comments on screen"
|
608
|
task :test_parse_comments => :environment do
|
609
|
comments = JiraMigration.parse_comments()
|
610
|
comments.each {|c| pp( c.run_all_redmine_fields) }
|
611
|
end
|
612
|
|
613
|
desc "Just pretty print Jira Issues on screen"
|
614
|
task :test_parse_issues => :environment do
|
615
|
issues = JiraMigration.parse_issues()
|
616
|
issues.each {|i| pp( i.run_all_redmine_fields) }
|
617
|
end
|
618
|
end
|