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

Run event loop in tasks and remove requests dependency. #186

Merged
merged 4 commits into from Dec 14, 2018
File filter...
Filter file types
Jump to file or symbol
Failed to load files and symbols.
+121 −109
Diff settings

Always

Just for now

Copy path View file
@@ -2,4 +2,3 @@
pytest==4.0.1
pytest-asyncio==0.9.0
pytest-aiohttp==0.3.0
requests-mock==1.5.2
Copy path View file
@@ -1,6 +1,11 @@
import celery
import asyncio
import os
import subprocess
import aiohttp
from gidgethub import aiohttp as gh_aiohttp

import cachetools

from celery import bootsteps

@@ -14,6 +19,8 @@
BROKER_URL=os.environ["REDIS_URL"], CELERY_RESULT_BACKEND=os.environ["REDIS_URL"]
)

cache = cachetools.LRUCache(maxsize=500)


@app.task()
def setup_cpython_repo():
@@ -39,52 +46,78 @@ def setup_cpython_repo():

@app.task()
def backport_task(commit_hash, branch, *, issue_number, created_by, merged_by):
"""Backport a commit into a branch."""
if not util.is_cpython_repo():
# cd to cpython if we're not already in it
if "cpython" in os.listdir("."):
os.chdir("./cpython")
else:
print(f"pwd: {os.getcwd()}, listdir: {os.listdir('.')}")
util.comment_on_pr(
issue_number,
f"""{util.get_participants(created_by, merged_by)}, Something is wrong... I can't backport for now.
Please backport using [cherry_picker](https://pypi.org/project/cherry-picker/) on command line.
```
cherry_picker {commit_hash} {branch}
```
""",
)
util.assign_pr_to_core_dev(issue_number, merged_by)
cp = cherry_picker.CherryPicker(
"origin", commit_hash, [branch], prefix_commit=False
loop = asyncio.get_event_loop()
loop.run_until_complete(
backport_task_asyncio(
commit_hash,
branch,
issue_number=issue_number,
created_by=created_by,
merged_by=merged_by,
)
)
try:
cp.backport()
except cherry_picker.BranchCheckoutException:
util.comment_on_pr(
issue_number,
f"""Sorry {util.get_participants(created_by, merged_by)}, I had trouble checking out the `{branch}` backport branch.
Please backport using [cherry_picker](https://pypi.org/project/cherry-picker/) on command line.
```
cherry_picker {commit_hash} {branch}
```
""",


async def backport_task_asyncio(
commit_hash, branch, *, issue_number, created_by, merged_by
):
"""Backport a commit into a branch."""

oauth_token = os.environ.get("GH_AUTH")
async with aiohttp.ClientSession() as session:
gh = gh_aiohttp.GitHubAPI(
session, "python/cpython", oauth_token=oauth_token, cache=cache
)
util.assign_pr_to_core_dev(issue_number, merged_by)
cp.abort_cherry_pick()
except cherry_picker.CherryPickException:
util.comment_on_pr(
issue_number,
f"""Sorry, {util.get_participants(created_by, merged_by)}, I could not cleanly backport this to `{branch}` due to a conflict.
Please backport using [cherry_picker](https://pypi.org/project/cherry-picker/) on command line.
```
cherry_picker {commit_hash} {branch}
```
""",

if not util.is_cpython_repo():
# cd to cpython if we're not already in it
if "cpython" in os.listdir("."):
os.chdir("./cpython")
else:
print(f"pwd: {os.getcwd()}, listdir: {os.listdir('.')}")

await util.comment_on_pr(
gh,
issue_number,
f"""{util.get_participants(created_by, merged_by)}, Something is wrong... I can't backport for now.
Please backport using [cherry_picker](https://pypi.org/project/cherry-picker/) on command line.
```
cherry_picker {commit_hash} {branch}
```
""",
)
await util.assign_pr_to_core_dev(gh, issue_number, merged_by)
cp = cherry_picker.CherryPicker(
"origin", commit_hash, [branch], prefix_commit=False
)
util.assign_pr_to_core_dev(issue_number, merged_by)
cp.abort_cherry_pick()
try:
cp.backport()
except cherry_picker.BranchCheckoutException:
await util.comment_on_pr(
gh,
issue_number,
f"""Sorry {util.get_participants(created_by, merged_by)}, I had trouble checking out the `{branch}` backport branch.
Please backport using [cherry_picker](https://pypi.org/project/cherry-picker/) on command line.
```
cherry_picker {commit_hash} {branch}
```
""",
)
await util.assign_pr_to_core_dev(gh, issue_number, merged_by)
cp.abort_cherry_pick()
except cherry_picker.CherryPickException:
await util.comment_on_pr(
gh,
issue_number,
f"""Sorry, {util.get_participants(created_by, merged_by)}, I could not cleanly backport this to `{branch}` due to a conflict.
Please backport using [cherry_picker](https://pypi.org/project/cherry-picker/) on command line.
```
cherry_picker {commit_hash} {branch}
```
""",
)
await util.assign_pr_to_core_dev(gh, issue_number, merged_by)
cp.abort_cherry_pick()


class InitRepoStep(bootsteps.StartStopStep):
Copy path View file
@@ -1,54 +1,31 @@
import requests
import os
import subprocess

import gidgethub

from gidgethub import sansio


AUTOMERGE_LABEL = ":robot: automerge"


def comment_on_pr(issue_number, message):
async def comment_on_pr(gh, issue_number, message):
"""
Leave a comment on a PR/Issue
"""
request_headers = sansio.create_headers(
"miss-islington", oauth_token=os.getenv("GH_AUTH")
)
issue_comment_url = (
f"https://api.github.com/repos/python/cpython/issues/{issue_number}/comments"
)
issue_comment_url = f"/repos/python/cpython/issues/{issue_number}/comments"
data = {"body": message}
response = requests.post(issue_comment_url, headers=request_headers, json=data)
if response.status_code == requests.codes.created:
print(f"Commented at {response.json()['html_url']}, message: {message}")
else:
print(response.status_code)
print(response.text)
response = await gh.post(issue_comment_url, data=data)
print(f"Commented at {response['html_url']}, message: {message}")
return response


def assign_pr_to_core_dev(issue_number, coredev_login):
async def assign_pr_to_core_dev(gh, issue_number, coredev_login):
"""
Assign the PR to a core dev. Should be done when miss-islington failed
to backport.
"""
request_headers = sansio.create_headers(
"miss-islington", oauth_token=os.getenv("GH_AUTH")
)
edit_issue_url = (
f"https://api.github.com/repos/python/cpython/issues/{issue_number}"
)

edit_issue_url = f"/repos/python/cpython/issues/{issue_number}"
data = {"assignees": [coredev_login]}
response = requests.patch(edit_issue_url, headers=request_headers, json=data)
if response.status_code == requests.codes.created:
print(f"Assigned PR {issue_number} to {coredev_login}")
else:
print(response.status_code)
print(response.text)
return response
await gh.patch(edit_issue_url, data=data)


async def leave_comment(gh, pr_number, message):
Copy path View file
@@ -2,6 +2,5 @@ cherry_picker==1.2.1
aiohttp==3.4.4
gidgethub==3.0.0
cachetools==3.0.0
requests==2.21.0
redis==2.10.6
celery==4.2.1
Copy path View file
@@ -9,12 +9,14 @@


class FakeGH:
def __init__(self, *, getiter=None, getitem=None, post=None):
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):
@@ -31,6 +33,21 @@ def __init__(self, *, getiter=None, getitem=None, post=None):
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
print(type(self._post_return))
if isinstance(self._post_return, Exception):
print("raising")
raise self._post_return
else:
return self._post_return


def test_title_normalization():
title = "abcd"
@@ -223,51 +240,38 @@ def test_pr_is_not_automerge():
assert util.pr_is_automerge(labels) is False


def test_comment_on_pr_success(requests_mock):
async def test_comment_on_pr_success():
issue_number = 100
message = "Thanks for the PR!"
post_url = (
f"https://api.github.com/repos/python/cpython/issues/{issue_number}/comments"
)
requests_mock.post(
post_url,
json={
"html_url": "https://github.com/python/cpython/pull/{issue_number}#issuecomment-401309376"
},
status_code=201,

gh = FakeGH(
post={
"html_url": f"https://github.com/python/cpython/pull/{issue_number}#issuecomment-401309376"
}
)
response = util.comment_on_pr(issue_number, message)
assert response.status_code == 201

await util.comment_on_pr(gh, issue_number, message)
assert gh.post_url == f"/repos/python/cpython/issues/{issue_number}/comments"
assert gh.post_data == {"body": message}


def test_comment_on_pr_failure(requests_mock):
async def test_comment_on_pr_failure():
issue_number = 100
message = "Thanks for the PR!"
post_url = (
f"https://api.github.com/repos/python/cpython/issues/{issue_number}/comments"
)
requests_mock.post(post_url, status_code=400)
response = util.comment_on_pr(issue_number, message)
assert response.status_code == 400

gh = FakeGH(post=gidgethub.BadRequest(status_code=http.HTTPStatus(400)))

def test_assign_pr_to_coredev_success(requests_mock):
with pytest.raises(gidgethub.BadRequest):
await util.comment_on_pr(gh, issue_number, message)

issue_number = 100
coredev_login = "Mariatta"
patch_url = f"https://api.github.com/repos/python/cpython/issues/{issue_number}"
requests_mock.patch(patch_url, status_code=201)
response = util.assign_pr_to_core_dev(issue_number, coredev_login)
assert response.status_code == 201

async def test_assign_pr_to_coredev():

def test_assign_pr_to_coredev_failed(requests_mock):
issue_number = 100
coredev_login = "Mariatta"
patch_url = f"https://api.github.com/repos/python/cpython/issues/{issue_number}"
requests_mock.patch(patch_url, status_code=400)
response = util.assign_pr_to_core_dev(issue_number, coredev_login)
assert response.status_code == 400
gh = FakeGH()

await util.assign_pr_to_core_dev(gh, issue_number, coredev_login)
assert gh.patch_url == f"/repos/python/cpython/issues/{issue_number}"


async def test_get_pr_for_commit():
ProTip! Use n and p to navigate between commits in a pull request.