def print_issue_overview(*insights): closed_issues = sum([x["closed_issues"] for x in insights]) issue_closers = set().union(*[x["issue_closers"] for x in insights]) new_issues = sum([x["new_issues"] for x in insights]) issue_authors = set().union(*[x["issue_authors"] for x in insights]) output_handler( "* {} closed issues by {} people, {} opened by {} people".format( closed_issues, len(issue_closers), new_issues, len(issue_authors))) # print Hacktoberfest labels changes if its Hacktober in_season, season_action = hacktober.is_hacktober_season() if in_season: hacktober_changes = "" if season_action == "add": hacktober_changes = "* Assigned Hacktoberfest label to {} issues.".format( sum([x["hacktober_assigned"] for x in insights])) elif season_action == "remove": hacktober_changes += "* Removed Hacktoberfest label from {} issues.".format( sum([x["hacktober_removed"] for x in insights])) output_handler(hacktober_changes)
def gather_insights(self, repo, insights, since, show_closed_metric=False): """Gather analytics about a repository like open and merged pull requests. This expects a dictionary with GitHub API repository state (like from the list_repos function) and will fill in the provided insights dictionary with analytics it computes for the repository. """ if repo["owner"]["login"] != "adafruit": return [] params = {"sort": "updated", "state": "all", "since": since.strftime("%Y-%m-%dT%H:%M:%SZ")} response = github.get("/repos/" + repo["full_name"] + "/issues", params=params) if not response.ok: # replace 'output_handler' with ERROR_OUTPUT_HANDLER self.output_file_data.append("Insights request failed: {}".format(repo["full_name"])) return [ERROR_OUTPUT_HANDLER] issues = response.json() for issue in issues: created = datetime.datetime.strptime(issue["created_at"], "%Y-%m-%dT%H:%M:%SZ") if "pull_request" in issue: pr_info = github.get(issue["pull_request"]["url"]) pr_info = pr_info.json() if issue["state"] == "open": if created > since: insights["new_prs"] += 1 insights["pr_authors"].add(pr_info["user"]["login"]) insights["active_prs"] += 1 else: if pr_info["merged"]: merged_info = "" if show_closed_metric: created = datetime.datetime.strptime( issue["created_at"], "%Y-%m-%dT%H:%M:%SZ" ) merged = datetime.datetime.strptime( issue["closed_at"], "%Y-%m-%dT%H:%M:%SZ" ) days_open = merged - created if days_open.days < 0: # opened earlier today days_open += datetime.timedelta( days=(days_open.days * -1) ) elif days_open.days == 0: days_open += datetime.timedelta( days=(1) ) merged_info = " (Days open: {})".format(days_open.days) pr_link = "{0}{1}".format( issue["pull_request"]["html_url"], merged_info ) insights["merged_prs"].append(pr_link) pr_author = pr_info["user"]["login"] if pr_author == "weblate": pr_commits = github.get(str(pr_info["url"]) + "/commits") if pr_commits.ok: for commit in pr_commits.json(): author = commit.get("author") if author: insights["pr_merged_authors"].add(author["login"]) else: insights["pr_merged_authors"].add(pr_info["user"]["login"]) insights["pr_reviewers"].add(pr_info["merged_by"]["login"]) pr_reviews = github.get(str(pr_info["url"]) + "/reviews") if pr_reviews.ok: for review in pr_reviews.json(): if review["state"].lower() == "approved": insights["pr_reviewers"].add(review["user"]["login"]) else: insights["closed_prs"] += 1 else: issue_info = github.get(issue["url"]) issue_info = issue_info.json() if issue["state"] == "open": if created > since: insights["new_issues"] += 1 insights["issue_authors"].add(issue_info["user"]["login"]) insights["active_issues"] += 1 else: insights["closed_issues"] += 1 insights["issue_closers"].add(issue_info["closed_by"]["login"]) issues = [] params = {"state": "open", "per_page": 100} response = github.get("/repos/" + repo["full_name"] + "/issues", params=params) if not response.ok: # replace 'output_handler' with ERROR_OUTPUT_HANDLER self.output_file_data.append("Issues request failed: {}".format(repo["full_name"])) return [ERROR_OUTPUT_HANDLER] while response.ok: issues.extend(response.json()) try: links = response.headers["Link"] except KeyError: break if links: next_url = None for link in links.split(","): link, rel = link.split(";") link = link.strip(" <>") rel = rel.strip() if rel == "rel=\"next\"": next_url = link break if not next_url: break response = requests.get(link, timeout=30) for issue in issues: created = datetime.datetime.strptime(issue["created_at"], "%Y-%m-%dT%H:%M:%SZ") days_open = datetime.datetime.today() - created if days_open.days < 0: # opened earlier today days_open += datetime.timedelta(days=(days_open.days * -1)) if "pull_request" in issue: pr_link = "{0} (Open {1} days)".format(issue["pull_request"]["html_url"], days_open.days) insights["open_prs"].append(pr_link) else: issue_link = "{0} (Open {1} days)".format(issue["html_url"], days_open.days) insights["open_issues"].append(issue_link) if "labels" in issue: for i in issue["labels"]: if i["name"] == 'good first issue': insights["good_first_issues"] += 1 # process Hacktoberfest labels if it is Hacktoberfest season in_season, season_action = hacktober.is_hacktober_season() if in_season: hacktober_issues = [ issue for issue in issues if "pull_request" not in issue ] if season_action == "add": insights["hacktober_assigned"] += ( hacktober.assign_hacktoberfest(repo, issues=hacktober_issues) ) elif season_action == "remove": insights["hacktober_removed"] += ( hacktober.assign_hacktoberfest(repo, issues=hacktober_issues, remove_labels=True) ) # get milestones for core repo if repo["name"] == "circuitpython": params = {"state": "open"} response = github.get("/repos/adafruit/circuitpython/milestones", params=params) if not response.ok: # replace 'output_handler' with ERROR_OUTPUT_HANDLER self.output_file_data.append("Failed to get core milestone insights.") return [ERROR_OUTPUT_HANDLER] else: milestones = response.json() for milestone in milestones: #print(milestone) insights["milestones"][milestone["title"]] = milestone["open_issues"] return []