1
|
# updated feb-09
|
2
|
# bmishkin@sagebit.com
|
3
|
#
|
4
|
# to install up-to-date lighthouse api gem:
|
5
|
# gem install Caged-lighthouse-api --source=http://gems.github.com
|
6
|
#
|
7
|
# to import a project, create identically named redmine project
|
8
|
# to enable issue state -> ticket status, you need to create identically-named statuses in redmine before starting
|
9
|
|
10
|
require 'lighthouse-api'
|
11
|
namespace :import do
|
12
|
task :lighthouse => :environment do
|
13
|
|
14
|
Lighthouse.account = ENV["LH_ACCOUNT"]
|
15
|
Lighthouse.token = ENV["LH_TOKEN"]
|
16
|
|
17
|
users = User.find(:all)
|
18
|
find_user = lambda do |lh_user|
|
19
|
names = lh_user.name.split(/\s/)
|
20
|
names[1] = "Unknown" if !names[1] || names[1].strip.blank?
|
21
|
result = User.find(:all).detect {|u|
|
22
|
"#{u.firstname} #{u.lastname}" == names.join(' ')
|
23
|
}
|
24
|
unless result
|
25
|
result = User.find_by_admin(1) unless ENV['CREATE_USERS']
|
26
|
end
|
27
|
unless result
|
28
|
begin
|
29
|
login = names.first.downcase.gsub(/[^\w]/, '') +
|
30
|
(rand * 1000 + 100).to_s.first(3)
|
31
|
|
32
|
result = User.new(
|
33
|
:firstname => names.shift,
|
34
|
:lastname => names.join(' '),
|
35
|
:mail => "#{login}@fixme.com"
|
36
|
)
|
37
|
result.login = login
|
38
|
result.password = result.password_confirmation = login
|
39
|
result.save!
|
40
|
puts "Created a user: " +
|
41
|
"#{result.firstname} #{result.lastname} (#{result.login})"
|
42
|
rescue => e
|
43
|
raise "Failed creating user from: #{lh_user.inspect} -- #{e.inspect}"
|
44
|
end
|
45
|
end
|
46
|
result
|
47
|
end
|
48
|
|
49
|
cat_for_tag = lambda do |project, tag|
|
50
|
project.issue_categories.find_by_name(tag) ||
|
51
|
project.issue_categories.create(:name => tag)
|
52
|
end
|
53
|
|
54
|
# TODO: attempt to match priorities somehow?
|
55
|
priority = Enumeration.find_by_opt_and_name('IPRI', 'Normal')
|
56
|
|
57
|
puts "Identifying matching projects..."
|
58
|
projects = Lighthouse::Project.find(:all).collect do |lh_project|
|
59
|
rm_project = Project.find_by_name(lh_project.name)
|
60
|
puts "#{lh_project.name} => #{rm_project || '???'}"
|
61
|
|
62
|
# NOTE: disabled because creating projects involves a number of decisions
|
63
|
# about trackers, issue statuses, workflows, users, modules, etc that we
|
64
|
# don't want to get into.
|
65
|
#
|
66
|
#if rm_project
|
67
|
# puts "#{lh_project.name} => #{rm_project}"
|
68
|
#else
|
69
|
# rm_project = Project.create!(
|
70
|
# :name => lh_project.name,
|
71
|
# :identifier => lh_project.name.downcase.gsub(/[^\w]/, '-').first(20),
|
72
|
# :created_on => lh_project.created_at,
|
73
|
# :updated_on => lh_project.updated_at,
|
74
|
# :is_public => lh_project.public
|
75
|
# )
|
76
|
# puts "#{lh_project.name} => #{rm_project} [CREATED]"
|
77
|
#end
|
78
|
|
79
|
{lh_project => rm_project}
|
80
|
end
|
81
|
|
82
|
project_pairs = projects.inject({}) {|acc, hash| acc.update(hash)}
|
83
|
|
84
|
project_pairs.each_pair do |lh_project, rm_project|
|
85
|
next unless rm_project
|
86
|
|
87
|
if rm_project.trackers.empty?
|
88
|
raise "No trackers found for #{project.name!}. Cannot create an issue."
|
89
|
end
|
90
|
|
91
|
lh_project.milestones.each do |milestone|
|
92
|
next if rm_project.versions.find_by_name(milestone.title)
|
93
|
v = rm_project.versions.create!(
|
94
|
:name => milestone.title,
|
95
|
:description => milestone.goals,
|
96
|
:effective_date => milestone.due_on ? milestone.due_on.to_date : nil,
|
97
|
:created_on => milestone.created_at,
|
98
|
:updated_on => milestone.updated_at
|
99
|
)
|
100
|
puts "Created new target version for #{rm_project.name}: #{v.name}"
|
101
|
end
|
102
|
|
103
|
pg = 0
|
104
|
while (tix = lh_project.tickets(:page => (pg += 1), :q => 'sort:number status:any')).length > 0
|
105
|
puts "Chewing tickets on page #{pg}"
|
106
|
tix.each do |ticket_lite|
|
107
|
ticket = Lighthouse::Ticket.find(
|
108
|
ticket_lite.to_param,
|
109
|
:params => ticket_lite.instance_variable_get(:@prefix_options)
|
110
|
)
|
111
|
next if Issue.find_by_subject(ticket.title)
|
112
|
first_version = ticket.versions.shift
|
113
|
|
114
|
ticket_creator = Lighthouse::User.find(ticket.user_id) unless ticket.user_id.blank?
|
115
|
ticket_assignee = Lighthouse::User.find(ticket.assigned_user_id) unless ticket.assigned_user_id.blank?
|
116
|
issue = Issue.new
|
117
|
issue.project = rm_project
|
118
|
issue.tracker = rm_project.trackers.first
|
119
|
issue.author = find_user.call(ticket_creator) unless ticket_creator.blank?
|
120
|
issue.assigned_to = find_user.call(ticket_assignee) unless ticket_assignee.blank?
|
121
|
issue.priority = priority
|
122
|
issue.status = IssueStatus.find(
|
123
|
:first,
|
124
|
:conditions => ["UCASE(name) = ?", ticket.state.upcase]
|
125
|
) || IssueStatus.default
|
126
|
issue.fixed_version = rm_project.versions.find_by_name(
|
127
|
lh_project.milestones.detect {|ms| ms.id == ticket.milestone_id}.title
|
128
|
) unless ticket.milestone_id.blank?
|
129
|
issue.attributes = {
|
130
|
:subject => ticket.title,
|
131
|
:description => first_version.body || "[No description]",
|
132
|
:done_ratio => 0,
|
133
|
:created_on => ticket.created_at,
|
134
|
:updated_on => ticket.updated_at
|
135
|
}
|
136
|
|
137
|
if ticket.tags && ticket.tags.any?
|
138
|
issue.category = cat_for_tag.call(rm_project, ticket.tags.first)
|
139
|
end
|
140
|
|
141
|
if issue.save
|
142
|
puts "Added ticket [##{ticket.number}] to #{rm_project.name}: '#{issue.subject}' : #{ticket.state.upcase}"
|
143
|
else
|
144
|
puts "Failed to add issue: #{issue.inspect} - " +
|
145
|
issue.errors.full_messages.join(', ')
|
146
|
end
|
147
|
|
148
|
ticket.versions.each do |version|
|
149
|
next if version.body.blank?
|
150
|
|
151
|
version_author = Lighthouse::User.find(version.user_id)
|
152
|
issue.instance_variable_set(:@current_journal, nil)
|
153
|
issue.init_journal(find_user.call(version_author), version.body)
|
154
|
cj = issue.instance_variable_get(:@current_journal)
|
155
|
cj.created_on = version.created_at
|
156
|
issue.save!
|
157
|
end
|
158
|
end
|
159
|
end
|
160
|
end
|
161
|
|
162
|
end
|
163
|
end
|