Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow adding blurb for anyone, if logged in user is core-dev. #11

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
85 changes: 64 additions & 21 deletions blurb_it/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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": "[email protected]"}
# put_data["committer"] = {"name": "Miss Islington (bot)", "email": "[email protected]"}
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)
Expand Down
25 changes: 25 additions & 0 deletions blurb_it/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import time

import jwt
import gidgethub

from aiohttp_session import get_session

from blurb_it import error
Expand Down Expand Up @@ -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
87 changes: 86 additions & 1 deletion tests/test_util.py
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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")