import json, re, sys d = json.load(open(sys.argv[1])) KW = re.compile(r"(supersed|in favou?r of|duplicate of|already (been )?(fixed|merged|resolved)|fixed (by|in|with) #|resolved (by|in) #|closed by #|done in #|addressed (in|by) #)", re.I) def merged_refs(n, created): out = [] for e in n["timelineItems"]["nodes"]: s = e.get("source") or e.get("subject") if s and s.get("__typename") == "PullRequest" and s.get("merged") and s["number"] != n["number"]: out.append({"pr": s["number"], "title": s["title"], "mergedAt": s["mergedAt"], "closes": bool(e.get("willCloseTarget")) or e["__typename"] == "ConnectedEvent", "base": s.get("baseRefName")}) c = e.get("canonical") if c: out.append({"dup": c["number"], "state": c["state"]}) return out def hints(n): return [{"by": c["author"]["login"] if c["author"] else None, "at": c["createdAt"], "text": c["body"][:400]} for c in n["comments"]["nodes"] if KW.search(c["body"])] cands = [] for kind in ("issues", "prs"): for n in d[kind]: refs, h = merged_refs(n, n["createdAt"]), hints(n) sup = [] if kind == "prs": for iss in n["closingIssuesReferences"]["nodes"]: for p in iss["closedByPullRequestsReferences"]["nodes"]: if p["merged"] and p["number"] != n["number"]: sup.append({"issue": iss["number"], "issue_state": iss["state"], "merged_pr": p["number"]}) if refs or h or sup: score = 3 if (any(r.get("closes") for r in refs) or sup) else 2 if h else 1 cands.append({"kind": kind[:-1].replace("pr", "pr"), "number": n["number"], "title": n["title"], "author": (n["author"] or {}).get("login"), "created": n["createdAt"], "updated": n["updatedAt"], "draft": n.get("isDraft"), "merged_refs": refs, "hint_comments": h, "sibling_merged": sup, "score": score}) cands.sort(key=lambda c: -c["score"]) json.dump(cands, open(sys.argv[2], "w"), indent=1) from collections import Counter print(Counter((c["kind"], c["score"]) for c in cands))