From 5283a543625947d54962c16d19e96c114ac0f054 Mon Sep 17 00:00:00 2001 From: Mariatta Date: Sat, 16 Sep 2017 11:42:54 -0700 Subject: [PATCH] Comment on backport PR when status checks are done. (GH-27) Leave a comment when status checks for the backport PR are done. Only leave the comment on backports made by @miss-islington. Mention the original PR author and the core dev who merged the original PR. Closes https://github.com/python/miss-islington/issues/26 --- backport/__main__.py | 6 +++- backport/backport_pr.py | 6 +++- backport/status_change.py | 61 +++++++++++++++++++++++++++++++++++++++ backport/tasks.py | 9 ++++-- backport/util.py | 13 +++++++-- 5 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 backport/status_change.py diff --git a/backport/__main__.py b/backport/__main__.py index dda02926..0281f91b 100644 --- a/backport/__main__.py +++ b/backport/__main__.py @@ -14,8 +14,12 @@ from . import tasks from . import backport_pr from . import delete_branch +from . import status_change + +router = routing.Router(backport_pr.router, + delete_branch.router, + status_change.router) -router = routing.Router(backport_pr.router, delete_branch.router) cache = cachetools.LRUCache(maxsize=500) diff --git a/backport/backport_pr.py b/backport/backport_pr.py index 418f9e80..2671302a 100644 --- a/backport/backport_pr.py +++ b/backport/backport_pr.py @@ -43,7 +43,11 @@ async def backport_pr(event, gh, *args, **kwargs): util.comment_on_pr(issue_number, message) - for branch in branches: + sorted_branches = sorted(branches, + reverse=True, + key=lambda v: tuple(map(int, v.split('.')))) + + for branch in sorted_branches: tasks.backport_task.delay(commit_hash, branch, issue_number=issue_number, diff --git a/backport/status_change.py b/backport/status_change.py new file mode 100644 index 00000000..cb06c712 --- /dev/null +++ b/backport/status_change.py @@ -0,0 +1,61 @@ +import requests +import os +import re + +from gidgethub import sansio, routing + +from . import util + +router = routing.Router() + +TITLE_RE = re.compile(r'\[(?P\d+\.\d+)\].+?(?P\d+)\)') + + + +@router.register("status") +async def check_status(event, gh, *args, **kwargs): + """ + Check the state change + """ + if event.data["commit"]["committer"]["login"] == "miss-islington": + sha = event.data["sha"] + status_url = f"https://api.github.com/repos/python/cpython/commits/{sha}/status" + request_headers = sansio.create_headers( + "miss-islington", + oauth_token=os.getenv('GH_AUTH')) + response = requests.get(status_url, + headers=request_headers) + result = response.json() + + if result["state"] != "pending": + url = "https://api.github.com/repos/miss-islington/cpython/git/refs/heads/" + response = requests.get(url, headers=request_headers) + for ref in response.json(): + print("ref obj") + print(ref) + if "backport-" in ref["ref"] and ref["object"]["sha"] == sha: + backport_branch_name = ref["ref"].split("/")[-1] + pr_url = f"https://api.github.com/repos/python/cpython/pulls?state=open&head=miss-islington:{backport_branch_name}" + pr_response = requests.get(pr_url, headers=request_headers).json() + print("pr respponse") + print(pr_response) + if pr_response: + pr_number = pr_response[0]["number"] + normalized_pr_title = util.normalize_title(pr_response[0]["title"], + pr_response[0]["body"]) + + title_match = TITLE_RE.match(normalized_pr_title) + if title_match: + original_pr_number = title_match.group('pr') + original_pr_url = f"https://api.github.com/repos/python/cpython/pulls/{original_pr_number}" + original_pr_result = requests.get(original_pr_url, + headers=request_headers).json() + pr_author = original_pr_result["user"]["login"] + committer = original_pr_result["merged_by"]["login"] + + participants = util.get_participants( + pr_author, committer) + emoji = "✅" if result['state'] == "success" else "❌" + util.comment_on_pr( + pr_number, + message=f"{participants}: Backport status check is done, and it's a {result['state']} {emoji} .") diff --git a/backport/tasks.py b/backport/tasks.py index 3cf9e60e..de8e1b65 100644 --- a/backport/tasks.py +++ b/backport/tasks.py @@ -30,8 +30,13 @@ 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 - - os.chdir('./cpython') + if "cpython" in os.listdir('.'): + os.chdir('./cpython') + else: + print(f"pwd: {os.pwd()}, 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.""") cp = cherry_picker.CherryPicker('origin', commit_hash, [branch]) try: cp.backport() diff --git a/backport/util.py b/backport/util.py index 3cefb956..a0bd72a0 100644 --- a/backport/util.py +++ b/backport/util.py @@ -20,7 +20,7 @@ def comment_on_pr(issue_number, message): headers=request_headers, json=data) if response.status_code == requests.codes.created: - print(f"Commented at {response.json()['html_url']}") + print(f"Commented at {response.json()['html_url']}, message: {message}") else: print(response.status_code) print(response.text) @@ -60,4 +60,13 @@ def delete_branch(branch_name): if response.status_code == 204: print(f"{branch_name} branch deleted.") else: - print(f"Couldn't delete the branch {branch_name}") \ No newline at end of file + print(f"Couldn't delete the branch {branch_name}") + + +def normalize_title(title, body): + """Normalize the title if it spills over into the PR's body.""" + if not (title.endswith('…') and body.startswith('…')): + return title + else: + # Being paranoid in case \r\n is used. + return title[:-1] + body[1:].partition('\r\n')[0]