-
Notifications
You must be signed in to change notification settings - Fork 3
/
issue_exporter.py
190 lines (156 loc) · 6.17 KB
/
issue_exporter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#!/usr/bin/python
#
# Copyright 2011 James Purser, Christian Ohler, Michael MacFadden
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
""" This script imports issues from Code.Google and builds a csv file.
The intent is to imported the csv file into JIRA.
In order to run the script you will need the following library:
GData: http://code.google.com/p/gdata-python-client/"""
import gdata.projecthosting.client
import os
""" Configuration Values """
project_name = "wave-protocol"
export_file_name = "exported_issues.csv"
"""Mappings between Google Code Values and Jira Values"""
types = {}
types["Defect"] = "Bug"
types["Enhancement"] = "Improvemnet"
types["Patch"] = "Bug"
types["Review"] = "Bug"
types["Task"] = "Task"
priorities = {}
priorities["Critical"] = "Critical"
priorities["High"] = "Major"
priorities["Medium"] = "Minor"
priorities["Low"] = "Trivial"
statuses = {}
statuses["New"] = "Open"
statuses["Accepted"] = "Open"
statuses["Started"] = "In Progress"
statuses["Fixed"] = "Closed"
statuses["Invalid"] = "Closed"
statuses["Duplicate"] = "Closed"
statuses["WontFix"] = "Closed"
resolutions = {}
resolutions["New"] = ""
resolutions["Accepted"] = ""
resolutions["Started"] = ""
resolutions["Fixed"] = "Fixed"
resolutions["Invalid"] = "Invalid"
resolutions["Duplicate"] = "Duplicate"
resolutions["WontFix"] = "Won't Fix"
""" Helper Functions """
def get_comments(issue_id):
comments = []
while True:
comments_query = gdata.projecthosting.client.Query(start_index=len(comments) + 1)
comments_feed = hosting_client.get_comments(project_name, issue_id, query=comments_query)
if not comments_feed.entry:
break
comments.extend(comments_feed.entry)
comments_text = ""
if len(comments) > 0:
for comment in comments:
if len(comments_text) > 0:
comments_text += "---\n"
comments_text += "%s:\n%s\n\n" % (comment.title.text, comment.content.text)
updates = comment.updates
if updates:
if updates.summary:
comments_text += "Summary: %s\n\n" % updates.summary.text
if updates.status:
comments_text += "Status: %s\n\n" % updates.status.text
if updates.ownerUpdate:
comments_text += "OwnerUpdate: %s\n\n" % updates.ownerUpdate.text
for label in updates.label:
comments_text += "Label: %s\n\n" % label.text
for ccUpdate in updates.ccUpdate:
comments_text += "CcUpdate: %s\n\n" % ccUpdate.text
return comments_text
def escape(s):
return '"' + s.encode('utf-8').replace('"', '""') + '"'
def get_id(issue):
return issue.get_id().split('/')[-1]
def get_link(issue):
return "http://code.google.com/p/%s/issues/detail?id=%s" % (project_name, get_id(issue))
def get_description(issue):
# TODO: The content seems to be HTML, I'm not sure if that's what JIRA expects.
description = issue.content.text
description += "\n\n---\nIssue imported from %s\n\n" % issue_link
if issue.owner:
description += "Owner: %s\n" % issue.owner.username.text
for cc in issue.cc:
description += "Cc: %s\n" % cc.username.text
for label in issue.label:
description += "Label: %s\n" % label.text
if issue.stars:
description += "Stars: %s\n" % issue.stars.text
if issue.state:
description += "State: %s\n" % issue.state.text
if issue.status:
description += "Status: %s\n" % issue.status.text
return description
def convert_value(list,value):
if len(value) > 0:
return list[value]
else:
return ""
""" Export Process """
hosting_client = gdata.projecthosting.client.ProjectHostingClient()
export_file = open(export_file_name, "w")
# First row with column titles
export_file.write("Id,Summary,Issue Type,Priority,Status,Resolution,Description,Comment Body\n")
print "Exporting issues to: " + os.path.abspath(export_file_name)
issues_total = 0
while True:
issues_query = gdata.projecthosting.client.Query(start_index=issues_total + 1)
issues_feed = hosting_client.get_issues(project_name, query=issues_query)
if not issues_feed.entry:
break
for issue in issues_feed.entry:
issue_id = get_id(issue)
issue_link = get_link(issue)
print "Exporting Issue %s: %s" % (issue_id, issue_link)
# Append one row per issue
# Id, e.g. http://code.google.com/feeds/issues/p/wave-protocol/issues/full/1
row = escape(issue_id) + ","
# Title
row += escape(issue.title.text) + ","
# Fetch the type and priority from the labels
# There are any number of labels, but we are only interested in two. Namely
# Type-* and Priority-*
type = "";
priority = "";
for label in issue.label:
if label.text.startswith("Type-"):
type = label.text[5:]
elif label.text.startswith("Priority-"):
priority = label.text[9:]
row += escape(convert_value(types,type)) + ","
row += escape(convert_value(priorities,priority)) + ","
# Google Code only has the concept of status, while Jira has status and resolution.
# Status, e.g. Open or Closed
row += escape(convert_value(statuses,issue.status.text)) + ","
# Status, e.g. Fixed, Invalid, etc
row += escape(convert_value(resolutions,issue.status.text)) + ","
# Fetch the description text
description = get_description(issue)
row += escape(description) + ","
# Fetch all the comments and put them in a single column
comments = get_comments(issue_id)
row += escape(comments)
export_file.write(row + "\n")
issues_total += len(issues_feed.entry)
export_file.close()
print "\n%s issues exported" % issues_total