diff --git a/blurb_it/__main__.py b/blurb_it/__main__.py index 9587a5d..be780eb 100644 --- a/blurb_it/__main__.py +++ b/blurb_it/__main__.py @@ -159,28 +159,71 @@ async def handle_add_blurb_post(request): "path": path, "message": "📜🤖 Added by blurb_it.", } - try: - response = await gh.put( - f"/repos/{pr_repo_full_name}/contents/{path}", data=put_data - ) - except gidgethub.BadRequest as bac: - print("BadRequest") - print(int(bac.status_code)) - print(bac) - context[ - "pr_url" - ] = f"https://github.com/python/cpython/pull/{pr_number}" - context["pr_number"] = pr_number - context["status"] = "failure" + if pr["user"]["login"] != session_context["username"]: + async with aiohttp.ClientSession() as session: + mi_gh = GitHubAPI( + session, + "python/cpython", + oauth_token=os.getenv("MI_GH_AUTH"), + ) + is_core_dev = await util.is_core_dev( + mi_gh, session_context["username"] + ) + print(f"{session_context['username']} is core dev {is_core_dev} ") + if is_core_dev: + try: + # put_data["author"] = {"name": "Miss Islington (bot)", "email": "mariatta.wijaya+miss-islington@gmail.com"} + # put_data["committer"] = {"name": "Miss Islington (bot)", "email": "mariatta.wijaya+miss-islington@gmail.com"} + response = await mi_gh.put( + f"/repos/{pr_repo_full_name}/contents/{path}", + data=put_data, + ) + except gidgethub.BadRequest as bac: + print("BadRequest, error using miss-islington's oauth token") + print(int(bac.status_code)) + print(bac) + context[ + "pr_url" + ] = f"https://github.com/python/cpython/pull/{pr_number}" + context["pr_number"] = pr_number + context["status"] = "failure" + await mi_gh.post(f"/repos/python/cpython/issues/{pr_number}/comments", data={"body": "Ping!"}) + else: + print("response") + print(response) + commit_url = response["commit"]["html_url"] + context["commit_url"] = commit_url + context["path"] = response["content"]["path"] + context[ + "pr_url" + ] = f"https://github.com/python/cpython/pull/{pr_number}" + context["pr_number"] = pr_number + context["status"] = "success" else: - commit_url = response["commit"]["html_url"] - context["commit_url"] = commit_url - context["path"] = response["content"]["path"] - context[ - "pr_url" - ] = f"https://github.com/python/cpython/pull/{pr_number}" - context["pr_number"] = pr_number - context["status"] = "success" + try: + response = await gh.put( + f"/repos/{pr_repo_full_name}/contents/{path}", data=put_data + ) + except gidgethub.BadRequest as bac: + print("BadRequest, using blurb-it") + print(int(bac.status_code)) + print(bac) + context[ + "pr_url" + ] = f"https://github.com/python/cpython/pull/{pr_number}" + context["pr_number"] = pr_number + context["status"] = "failure" + else: + print("response") + print(response) + commit_url = response["commit"]["html_url"] + context["commit_url"] = commit_url + context["path"] = response["content"]["path"] + context[ + "pr_url" + ] = f"https://github.com/python/cpython/pull/{pr_number}" + context["pr_number"] = pr_number + context["status"] = "success" template = "add_blurb.html" response = aiohttp_jinja2.render_template(template, request, context=context) diff --git a/blurb_it/util.py b/blurb_it/util.py index 6d82959..8d259b4 100644 --- a/blurb_it/util.py +++ b/blurb_it/util.py @@ -3,6 +3,8 @@ import time import jwt +import gidgethub + from aiohttp_session import get_session from blurb_it import error @@ -80,3 +82,26 @@ async def get_installation_access_token(gh, jwt, installation_id): # } return response + + +async def is_core_dev(gh, username): + """Check if the user is a CPython core developer.""" + org_teams = "/orgs/python/teams" + team_name = "python core" + async for team in gh.getiter(org_teams): + if team["name"].lower() == team_name: + break + else: + raise ValueError(f"{team_name!r} not found at {org_teams!r}") + # The 'teams' object only provides a URL to a deprecated endpoint, + # so manually construct the URL to the non-deprecated team membership + # endpoint. + membership_url = f"/teams/{team['id']}/memberships/{username}" + try: + await gh.getitem(membership_url) + except gidgethub.BadRequest as exc: + if exc.status_code == 404: + return False + raise + else: + return True diff --git a/tests/test_util.py b/tests/test_util.py index 95a52cb..04f11e5 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -1,8 +1,61 @@ +import http +import pytest +import gidgethub + + from blurb_it import util +class FakeGH: + def __init__(self, *, getiter=None, getitem=None, post=None, patch=None): + self._getitem_return = getitem + self._getiter_return = getiter + self._post_return = post + self._patch_return = patch + self.getitem_url = None + self.getiter_url = None + self.patch_url = self.patch_data = None + self.post_url = self.post_data = None + + async def getitem(self, url): + self.getitem_url = url + to_return = self._getitem_return[self.getitem_url] + if isinstance(to_return, Exception): + raise to_return + else: + return to_return + + async def getiter(self, url): + self.getiter_url = url + to_iterate = self._getiter_return[url] + for item in to_iterate: + yield item + + async def patch(self, url, *, data): + self.patch_url = url + self.patch_data = data + return self._patch_return + + async def post(self, url, *, data): + self.post_url = url + self.post_data = data + if isinstance(self._post_return, Exception): + raise self._post_return + else: + return self._post_return + + async def test_nonceify(): - body = "Lorem ipsum dolor amet flannel squid normcore tbh raclette enim" "pabst tumblr wolf farm-to-table bitters. Bitters keffiyeh next" "level proident normcore, et all of +1 90's in blue bottle" "chillwave lorem. Id keffiyeh microdosing cupidatat pour-over" "paleo farm-to-table tumeric sriracha +1. Raclette in poutine," "bushwick kitsch id pariatur hexagon. Thundercats shaman beard," "nulla swag echo park organic microdosing. Hot chicken tbh pop-up" "tacos, asymmetrical tilde veniam bespoke reprehenderit ut do." + body = ( + "Lorem ipsum dolor amet flannel squid normcore tbh raclette enim" + "pabst tumblr wolf farm-to-table bitters. Bitters keffiyeh next" + "level proident normcore, et all of +1 90's in blue bottle" + "chillwave lorem. Id keffiyeh microdosing cupidatat pour-over" + "paleo farm-to-table tumeric sriracha +1. Raclette in poutine," + "bushwick kitsch id pariatur hexagon. Thundercats shaman beard," + "nulla swag echo park organic microdosing. Hot chicken tbh pop-up" + "tacos, asymmetrical tilde veniam bespoke reprehenderit ut do." + ) nonce = await util.nonceify(body) assert nonce == "Ps4kgC" @@ -24,3 +77,35 @@ async def test_get_misc_news_filename(): assert path.startswith("Misc/NEWS.d/next/Library/") assert path.endswith(".bpo-123.Ps4kgC.rst") + + +async def test_is_core_dev(): + teams = [{"name": "not Python core"}] + gh = FakeGH(getiter={"/orgs/python/teams": teams}) + with pytest.raises(ValueError): + await util.is_core_dev(gh, "mariatta") + + teams = [{"name": "python core", "id": 42}] + getitem = {"/teams/42/memberships/mariatta": True} + gh = FakeGH(getiter={"/orgs/python/teams": teams}, getitem=getitem) + assert await util.is_core_dev(gh, "mariatta") + assert gh.getiter_url == "/orgs/python/teams" + + teams = [{"name": "python core", "id": 42}] + getitem = { + "/teams/42/memberships/miss-islington": gidgethub.BadRequest( + status_code=http.HTTPStatus(404) + ) + } + gh = FakeGH(getiter={"/orgs/python/teams": teams}, getitem=getitem) + assert not await util.is_core_dev(gh, "miss-islington") + + teams = [{"name": "python core", "id": 42}] + getitem = { + "/teams/42/memberships/miss-islington": gidgethub.BadRequest( + status_code=http.HTTPStatus(400) + ) + } + gh = FakeGH(getiter={"/orgs/python/teams": teams}, getitem=getitem) + with pytest.raises(gidgethub.BadRequest): + await util.is_core_dev(gh, "miss-islington")