Skip to content

Instantly share code, notes, and snippets.

@pgavlin
Created October 19, 2016 16:10
Show Gist options
  • Save pgavlin/b766ac9e16fe2abdbed32a1d6044690a to your computer and use it in GitHub Desktop.
Save pgavlin/b766ac9e16fe2abdbed32a1d6044690a to your computer and use it in GitHub Desktop.
Query GitHub issues
#!/usr/bin/env python
from __future__ import print_function
import argparse, csv, itertools, json, os, requests, sys, urllib
from datetime import datetime
def write_csv(writer, milestone):
for i in milestone['issues']:
row = { 'Issue Number': i['number'], 'Description': i['title'], 'Assigned To': i['assignees_list'], 'Link': i['url'], 'Milestone': milestone['title'] }
writer.writerow(row)
def write_html(milestone):
assigned = [i for i in milestone['issues'] if len(i['assignees']) != 0]
unassigned = [i for i in milestone['issues'] if len(i['assignees']) == 0]
for i in itertools.chain(assigned, unassigned):
print('<tr><td><a href="{0}">{1}</a></td><td>{2}</td><td>{3}</td><td>{4}</td></tr>'.format(i['url'], i['number'], i['title'], i['assignees_list'], milestone['title']))
def write_md(milestone, is_first):
if not is_first:
print('')
print('# ' + milestone['title'])
assigned = [i for i in milestone['issues'] if len(i['assignees']) != 0]
unassigned = [i for i in milestone['issues'] if len(i['assignees']) == 0]
if len(assigned) != 0:
print('## In progress')
for i in assigned:
print('- {0}: {1} => {2} ([link]({3}))'.format(i['number'], i['title'], i['assignees_list'], i['url']))
if len(unassigned) != 0:
if len(assigned) != 0:
print('')
print('## Backlog')
for i in unassigned:
print('- {0}: {1} ([link]({2}))'.format(i['number'], i['title'], i['url']))
def main(args):
parser = argparse.ArgumentParser(prog = 'ghquery', description = 'Query the issues for a GitHub repository.')
parser.add_argument('-f', '--format', dest = 'fmt', type = str, help = 'the output format', choices = ['csv', 'html', 'md'], default = 'md')
parser.add_argument('query', metavar = 'QUERY', type = str, help = 'the path to the query description')
args = parser.parse_args(args)
query = None
with open(args.query, 'r') as query_file:
query = json.load(query_file)
base_path = 'https://api.github.com/repos/' + urllib.pathname2url(query['owner']) + '/' + urllib.pathname2url(query['repo'])
# Fetch the issues according to the query and build the milestones
params = { 'state': 'open', 'labels' : ','.join(query['labels']) }
milestones = {}
for i in requests.get(base_path + '/issues', params = params).json():
if 'pull_request' in i:
continue
milestone = i['milestone']
if milestone is None:
milestone = { 'number': -1, 'title': 'No milestone', 'due_on': None }
milestone_number = milestone['number']
if milestone_number not in milestones:
due_on = milestone['due_on']
due_on = datetime.max if due_on is None else datetime.strptime(due_on, '%Y-%m-%dT%H:%M:%SZ')
milestones[milestone_number] = { 'title': milestone['title'], 'due_on': due_on, 'issues': [] }
i['assignees_list'] = ', '.join([u['login'] for u in i['assignees']])
milestones[milestone_number]['issues'].append(i)
write_func = None
if args.fmt == 'csv':
writer = csv.DictWriter(sys.stdout, ['Issue Number', 'Description', 'Assigned To', 'Link', 'Milestone'])
writer.writeheader()
write_func = lambda m, f: write_csv(writer, m)
elif args.fmt == 'html':
print('<html><body><table><tr><th>Issue Number</th><th>Description</th><th>Assigned To</th><th>Milestone</th></tr>')
write_func = lambda m, f: write_html(m)
else:
assert args.fmt == 'md'
write_func = write_md
is_first = True
for k, v in sorted(milestones.iteritems(), key = lambda (k, v): v['due_on']):
write_func(v, is_first)
is_first = False
if args.fmt == 'html':
print('</table></body></html>')
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment