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