""" Taken from https://gist.github.com/patrickfuller/e2ea8a94badc5b6967ef3ca0a9452a43 and modified. Currently writes all issues that have some Weight. """ import argparse import csv import requests import os.path token = None path = os.path.dirname(os.path.realpath(__file__)) filename = path + "/github_issues_to_csv.ignore" if os.path.exists(filename): with open(filename, "r") as config: content = config.read() if len(content) == 40: token = content else: raise ValueError("Invalid config file") PRIORITIES = ("P1", "P2", "P3", "P4") SEVERITIES = ("S1", "S2", "S3", "S4") WEIGHTS = ("W0", "W1/2", "W1", "W2", "W3", "W5", "W8", "W13", "W20", "W40", "W100") def write_issues(r, csvout): """Parses JSON response and writes to CSV.""" if r.status_code != 200: raise Exception(r.status_code) for issue in r.json(): if "pull_request" not in issue: priority = "" severity = "" weight = "" labels = [] for l in issue["labels"]: if l["name"][:2] in PRIORITIES: priority = l["name"] elif l["name"][:2] in SEVERITIES: severity = l["name"] elif l["name"] in WEIGHTS: weight = l["name"][1:] if weight == "1/2": weight = "0.5" else: labels.append(l["name"]) if not weight: continue labels = ", ".join(labels) date = issue["created_at"].split("T")[0] milestone = issue["milestone"]["title"] if issue["milestone"] else "" assignee = issue["assignee"]["login"] if issue["assignee"] else "" csvout.writerow( [ issue["title"], issue["number"], issue["html_url"], issue["state"], assignee, milestone, priority, severity, weight, labels, ] ) def get_issues(name): """Requests issues from GitHub API and writes to CSV file.""" url = f"https://api.github.com/repos/{name}/issues?state=all" if token is not None: headers = {"Authorization": "token " + token} else: headers = None r = requests.get(url, headers=headers) csvfilename = f"{name.replace('/', '-')}-issues.csv" with open(csvfilename, "w", newline="") as csvfile: csvout = csv.writer(csvfile) csvout.writerow( [ "Title", "Number", "URL", "State", "Assignee", "Milestone", "Priority", "Severity", "Weight", "Labels", ] ) write_issues(r, csvout) # Multiple requests are required if response is paged if "link" in r.headers: pages = { 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 = { 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"], headers=headers) write_issues(r, csvout) if pages["next"] == pages["last"]: break parser = argparse.ArgumentParser( description="Write GitHub repository issues " "to CSV file." ) parser.add_argument( "repositories", nargs="+", help="Repository names, " "formatted as 'username/repo'" ) parser.add_argument( "--all", action="store_true", help="Returns both open " "and closed issues." ) args = parser.parse_args() for repository in args.repositories: get_issues(repository)