~nhoad/dotfiles

7e4f569771476394ba523af55545cbfb022ca74e — Nathan Hoad 5 months ago a2908b6
Add a script for printing PR info from github.
1 files changed, 113 insertions(+), 0 deletions(-)

A bin/.bin/get-prs
A bin/.bin/get-prs => bin/.bin/get-prs +113 -0
@@ 0,0 1,113 @@
#!/bin/python3

import datetime
import enum
import os
import sys

import click
import requests

session = requests.Session()
session.headers = {
    "Authorization": open(os.path.expanduser("~/.secrets/github-token")).read().strip()
}

domain = open(os.path.expanduser("~/.secrets/github-domain")).read().strip()


class Status(enum.Enum):
    Pending = "pending"
    Accepted = "accepted"
    Denied = "denied"


def get_prs():
    resp = session.get(
        f"https://{domain}/api/v3/search/issues",
        params={"q": "involves:nhoad state:open"},
        timeout=10,
    )
    resp.raise_for_status()

    prs = list()
    for issue in resp.json()["items"]:
        repo = "/".join(issue["repository_url"].rsplit("/", 2)[1:])
        issue_id = issue["number"]
        creator = issue["user"]["login"]
        # handle assignees
        reviews = {assignee["login"]: Status.Pending for assignee in issue["assignees"]}
        # handle people who haven't put in reviews yet
        u = f"https://{domain}/api/v3/repos/{repo}/pulls/{issue_id}/requested_reviewers"
        resp = session.get(u, timeout=10)
        try:
            resp.raise_for_status()
        except requests.exceptions.HTTPError as e:
            if e.response.status_code == 404:
                continue
        reviewers = resp.json()
        for reviewer in reviewers["users"]:
            reviews[reviewer["login"]] = Status.Pending
        resp = session.get(
            issue["repository_url"] + "/pulls/{}/reviews".format(issue_id), timeout=10
        )
        resp.raise_for_status()

        for review in resp.json():
            username = review["user"]["login"]
            accepted = review["state"].upper() == "APPROVED"
            done = review["state"].upper() not in ("PENDING", "COMMENTED")

            if not done:
                status = Status.Pending
            elif accepted:
                status = Status.Accepted
            else:
                status = Status.Denied

            # if the submitter comments, don't show them as a reviewer for
            # their own thing
            if issue["user"]["login"] == username:
                continue
            reviews[username] = status

        # FIXME: don't do any formatting here or anything, leave that for the template
        # reviews = [f"{name[:2]}={status.value}" for (name, status) in sorted(reviews.items())]
        prs.append(
            {
                "org_repo": repo,
                "creator": creator,
                "number": issue_id,
                "reviews": sorted(reviews.items()),
            }
        )

    return prs


prs = get_prs()


def format_reviewer(name: str, status: Status) -> str:
    s = {"accepted": "green", "pending": "blue", "denied": "red"}[status.value]
    return click.style(name, fg=s)


print(datetime.datetime.now().strftime("%a, %b %d, %H:%M:%S"))

for pr in prs:
    org_repo = pr["org_repo"]
    number = pr["number"]
    creator = pr["creator"]
    reviews = pr["reviews"]

    if creator == "nhoad" and all(r[1].value == "accepted" for r in reviews):
        status = "merge"
    else:
        status = " ".join([format_reviewer(*r) for r in pr["reviews"]])
    print(
        f"{org_repo}#{number}",
        click.style(creator, fg="yellow"),
        status,
        f"https://{domain}/{org_repo}/pull/{number}",
    )