Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DavidMCook/b31a6721c06c184ed1f2e898ec4e3561 to your computer and use it in GitHub Desktop.
Save DavidMCook/b31a6721c06c184ed1f2e898ec4e3561 to your computer and use it in GitHub Desktop.
Export Issues from Github repo to CSV (API v3 and ZenHub API)
#!/usr/bin/env python
import csv
import json
import requests
"""
Exports Issues from a list of repositories to individual CSV files
Uses basic authentication (Github API Token and Zenhub API Token)
to retrieve Issues from a repository that token has access to.
Supports Github API v3 and ZenHubs current working API.
Derived from https://gist.github.com/Kebiled/7b035d7518fdfd50d07e2a285aff3977
Updated for Python3
"""
def write_issues(r, csvout, repo_name, repo_ID):
if not r.status_code == 200:
raise Exception(r.status_code)
r_json = r.json()
for issue in r_json:
print(repo_name + ' issue Number: ' + str(issue['number']))
zenhub_issue_url = 'https://api.zenhub.io/p1/repositories/' + \
str(repo_ID) + '/issues/' + str(issue['number']) + ACCESS_TOKEN
zen_r = requests.get(zenhub_issue_url).json()
global Payload
if 'pull_request' not in issue:
global ISSUES
ISSUES += 1
sAssigneeList = ''
sTag = ''
sCategory = ''
sPriority = ''
for i in issue['assignees'] if issue['assignees'] else []:
sAssigneeList += i['login'] + ','
for x in issue['labels'] if issue['labels'] else []:
if "Category" in x['name']:
sCategory = x['name']
if "Tag" in x['name']:
sTag = x['name']
if "Priority" in x['name']:
sPriority = x['name']
lEstimateValue = zen_r.get('estimate', dict()).get('value', "")
sPipeline = zen_r.get('pipeline', dict()).get('name', "")
#fnames = ['Repository', 'Issue Number', 'Issue Title', 'Category', 'Tag', 'Priority', 'Pipeline', 'Issue Author', 'Created At', 'Milestone', 'Assigned To', 'Issue Content', 'Estimate Value']
csvout.writerow({'Repository': repo_name,
'Issue Number': issue['number'],
'Issue Title': issue['title'].encode('utf-8'),
'Category': sCategory,
'Tag': sTag,
'Priority': sPriority,
'Pipeline': sPipeline,
'Issue Author': issue['user']['login'],
'Created At': issue['created_at'],
'Milestone': issue['milestone']['title'] if issue['milestone'] else "",
'Assigned To': sAssigneeList[:-1],
'Issue Content': issue['body'].encode('utf-8'),
'Estimate Value': lEstimateValue})
else:
print('You have skipped %s Pull Requests' % ISSUES)
def get_issues(REPO_ID, REPO_NAME):
repo_name = REPO_NAME
repo_ID = REPO_ID
issues_for_repo_url = 'https://api.github.com/repos/%s/issues' % repo_name
r = requests.get(issues_for_repo_url, auth=AUTH)
write_issues(r, FILEOUTPUT, repo_name, repo_ID)
# more pages? examine the 'link' header returned
if 'link' in r.headers:
pages = dict(
[(rel[6:-1], url[url.index('<') + 1:-1]) for url, rel in
[link.split(';') for link in
r.headers['link'].split(',')]])
while 'last' in pages and 'next' in pages:
pages = dict(
[(rel[6:-1], url[url.index('<') + 1:-1]) for url, rel in
[link.split(';') for link in
r.headers['link'].split(',')]])
r = requests.get(pages['next'], auth=AUTH)
write_issues(r, FILEOUTPUT, repo_name, repo_ID)
if pages['next'] == pages['last']:
break
FILEOUTPUT.writerow(['Total', ISSUES])
PAYLOAD = ""
REPO_NAME = '*REPO/NAME'
REPO_ID = '*REPO_ID*'
AUTH = ('token', '*PERSONAL_GIT_AUTHENTICATION_TOKEN*')
ACCESS_TOKEN = '*PERSONAL_ZENHUB_ACCESS_TOKEN*'
TXTOUT = open('data.json', 'w')
ISSUES = 0
FILENAME = './zenhub_tickets_export.csv'
OPENFILE = open(FILENAME, 'w')
fnames = ['Repository', 'Issue Number', 'Issue Title', 'Category', 'Tag', 'Priority', 'Pipeline', 'Issue Author', 'Created At', 'Milestone', 'Assigned To', 'Issue Content', 'Estimate Value']
FILEOUTPUT = csv.DictWriter(OPENFILE, fieldnames=fnames)
FILEOUTPUT.writeheader()
get_issues(REPO_ID, REPO_NAME)
json.dump(PAYLOAD, open('data.json', 'w'), indent=4)
TXTOUT.close()
OPENFILE.close()
@bmunkholm
Copy link

Line 26 needs to be:
str(repo_ID) + '/issues/' + str(issue['number']) + '?access_token=' + ACCESS_TOKEN

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