Skip to content

Instantly share code, notes, and snippets.

@erussell
Created September 1, 2011 20:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erussell/1187119 to your computer and use it in GitHub Desktop.
Save erussell/1187119 to your computer and use it in GitHub Desktop.
Import Trac tickets into GitHub issues, using v3 of the GitHub API. Based on https://github.com/adamcik/github-trac-ticket-import
#!/usr/bin/env python
import base64
import csv
import json
import urllib
import urllib2
import string
# Dictionary mapping Trac usernames to GitHub usernames
USERS = {
'erussell' : 'erussell',
}
# Username of your GitHub account
USERNAME = ''
# Password of your GitHub account
PASSWORD = ''
# Organization that owns repository (or empty string if no organization)
ORGNAME = ''
# Repository name
REPOSITORY = ''
# Path to Trac issues (CSV version of report 1)
TRAC_TICKETS = ''
if (ORGNAME == ''):
ORGNAME = USERNAME
github_url = 'https://api.github.com/repos/%s/%s/' % (ORGNAME, REPOSITORY)
authorization = 'Basic %s' % base64.b64encode("%s:%s" % (USERNAME, PASSWORD))
csv_data = open(TRAC_TICKETS)
reader = csv.DictReader(csv_data)
tickets = []
url = github_url + 'issues?per_page=100'
response = urllib2.urlopen(url)
content = response.read()
issues = json.loads(content)
url = github_url + 'milestones'
response = urllib2.urlopen(url)
content = response.read()
milestones = dict([ (milestone['title'], milestone) for milestone in json.loads(content) ])
create_milestones = set()
url = github_url + 'labels'
response = urllib2.urlopen(url)
content = response.read()
labels = [ label['name'] for label in json.loads(content) ]
create_labels = set()
for row in reader:
for key, value in row.items():
row[key] = row[key].decode('utf-8')
if filter(lambda i: i['title'] == row['summary'], issues):
continue
if 'milestone' in row and not row['milestone'] in milestones:
create_milestones.add(row['milestone'])
if not row['type'] in labels:
create_labels.add(row['type'])
if not row['component'] in labels:
create_labels.add(row['component'])
tickets.append({
'title': row['summary'],
'description': row['_description'],
'owner' : row['owner'],
'tags': [row['type'], row['component']],
'milestone' : row['milestone'] if 'milestone' in row else None,
})
url = github_url + 'milestones'
for milestone in create_milestones:
data = json.dumps({'title' : milestone})
request = urllib2.Request(url, data, {'Content-Type': 'application/json'})
request.add_header('Authorization', authorization)
response = urllib2.urlopen(request)
content = response.read()
try:
milestones[milestone] = json.loads(content)
except KeyError:
raise Exception(content)
response.close()
url = github_url + 'labels'
for label in create_labels:
data = json.dumps({'name' : label})
request = urllib2.Request(url, data, {'Content-Type': 'application/json'})
request.add_header('Authorization', authorization)
response = urllib2.urlopen(request)
content = response.read()
response.close()
url = github_url + 'issues'
for ticket in tickets:
owner = ticket['owner']
body = ticket['description']
body = string.replace(body, '[[BR]]', '\n\n')
body = string.replace(body, "'''", '**')
body = string.replace(body, "''", '*')
data = json.dumps({
'title' : ticket['title'],
'body' : body,
'assignee' : USERS[owner] if owner in USERS else None,
'milestone' : milestones[ticket['milestone']]['number'],
'labels' : ticket['tags']})
request = urllib2.Request(url, data, {'Content-Type': 'application/json'})
request.add_header('Authorization', authorization)
response = urllib2.urlopen(request)
content = response.read()
try:
issue = json.loads(content)
except KeyError:
raise Exception(content)
response.close()
@brucellino
Copy link

Very useful (potentially) piece of code. I tried running it against by repo, but the authorisation is failing (see below). I wonder if the basic authorization with token would work ?

Traceback (most recent call last):
  File "github-trac-ticket-import.py", line 82, in <module>
    response = urllib2.urlopen(request)
  File "/usr/lib/python2.7/urllib2.py", line 127, in urlopen
    return _opener.open(url, data, timeout)
  File "/usr/lib/python2.7/urllib2.py", line 410, in open
    response = meth(req, response)
  File "/usr/lib/python2.7/urllib2.py", line 523, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/lib/python2.7/urllib2.py", line 448, in error
    return self._call_chain(*args)
  File "/usr/lib/python2.7/urllib2.py", line 382, in _call_chain
    result = func(*args)
  File "/usr/lib/python2.7/urllib2.py", line 531, in http_error_default
    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 422: Unprocessable Entity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment