xref: /openbmc/openbmc-test-automation/tools/github_issues_to_csv (revision 9fe1b12e8b0e29a2a745d3a8ff1031b956bd03b9)
1#!/usr/bin/env python
2
3r"""
4Exports issues from a list of repositories to individual CSV files.
5Uses basic authentication (GitHub username + password) to retrieve issues
6from a repository that username has access to. Supports GitHub API v3.
7"""
8import argparse
9import csv
10import getpass
11import requests
12
13auth = None
14states = 'all'
15
16
17def write_issues(response, csv_out):
18    r"""
19    Parses JSON response and writes to CSV.
20    """
21    print response
22    if response.status_code != 200:
23        raise Exception(response.status_code)
24    for issue in response.json():
25        if 'pull_request' not in issue:
26            labels = ', '.join([l['name'] for l in issue['labels']])
27            date = issue.get('created_at').split('T')[0]
28            # Below lines to overcome "TypeError: 'NoneType' object has
29            # no attribute '__getitem__'"
30
31            assignee_resp = issue.get('assignee', 'Not Assigned')
32            if assignee_resp:
33                assignee_resp = assignee_resp.get('login').encode('utf-8')
34            else:
35                assignee_resp = "Not Assigned"
36
37            # Change the following line to write out additional fields
38            csv_out.writerow([labels.encode('utf-8'),
39                             issue.get('title').encode('utf-8'),
40                             issue.get('state').encode('utf-8'),
41                             date.encode('utf-8'),
42                             issue.get('html_url').encode('utf-8'),
43                             issue.get('user').get('login').encode('utf-8'),
44                             assignee_resp])
45
46
47def get_issues_from_github_to_csv(name):
48    r"""
49    Requests issues from GitHub API and writes to CSV file.
50    """
51    print name
52    print states
53    l_url = 'https://api.github.com/repos/{}/issues?state={}'.format(name,
54                                                                     states)
55    print l_url
56    # 'https://api.github.com/repos/{}/issues?state={}'.format(name, state)
57    response = requests.get(l_url, auth=auth)
58
59    csvfilename = '{}-issues.csv'.format(name.replace('/', '-'))
60    with open(csvfilename, 'w') as csvfile:
61        csv_out = csv.writer(csvfile)
62        csv_out.writerow(['Labels', 'Title', 'State', 'Date', 'URL', 'Author',
63                         'Assignee'])
64        write_issues(response, csv_out)
65
66        # Multiple requests are required if response is paged
67        if 'link' in response.headers:
68            pages = {rel[6:-1]: url[url.index('<')+1:-1] for url, rel in
69                     (link.split(';') for link in
70                      response.headers['link'].split(','))}
71            while 'last' in pages and 'next' in pages:
72                pages = {rel[6:-1]: url[url.index('<')+1:-1] for url, rel in
73                         (link.split(';') for link in
74                          response.headers['link'].split(','))}
75                response = requests.get(pages['next'], auth=auth)
76                write_issues(response, csv_out)
77                if pages['next'] == pages['last']:
78                    break
79
80        csvfile.close()
81
82parser = argparse.ArgumentParser(description="Write GitHub repository issues "
83                                             "to CSV file.")
84
85parser.add_argument('username', nargs='+', help="GitHub user name, "
86                    "formatted as 'username'")
87
88parser.add_argument('repositories', nargs='+', help="Repository names, "
89                    "formatted as 'basereponame/repo'")
90
91parser.add_argument('--all', action='store_true', help="Returns both open "
92                    "and closed issues.")
93args = parser.parse_args()
94
95if args.all:
96    state = 'all'
97
98for argusername in args.username:
99    username = argusername
100
101password = getpass.getpass("Enter your GitHub Password:")
102
103auth = (username, password)
104
105for repository in args.repositories:
106    get_issues_from_github_to_csv(repository)
107