1- import requests
2- import os
31import re
42
5- from gidgethub import sansio , routing
3+ from gidgethub import routing
64
75from . import util
86
119TITLE_RE = re .compile (r'\[(?P<branch>\d+\.\d+)\].+?(?P<pr>\d+)\)' )
1210
1311
14-
1512@router .register ("status" )
1613async def check_status (event , gh , * args , ** kwargs ):
1714 """
@@ -20,43 +17,86 @@ async def check_status(event, gh, *args, **kwargs):
2017 if event .data ["commit" ].get ("committer" ) \
2118 and event .data ["commit" ]["committer" ]["login" ] == "miss-islington" :
2219 sha = event .data ["sha" ]
23- status_url = f"https://api.github.com/repos/python/cpython/commits/{ sha } /status"
24- request_headers = sansio .create_headers (
25- "miss-islington" ,
26- oauth_token = os .getenv ('GH_AUTH' ))
27- response = requests .get (status_url ,
28- headers = request_headers )
29- result = response .json ()
30- all_ci_status = [status ["state" ] for status in result ["statuses" ]]
31- all_ci_context = [status ["context" ] for status in result ["statuses" ]]
32- print (f"miss-islington's PR state changed: { all_ci_status } " )
33- print (f"miss-islington's PR CI: { all_ci_context } " )
34- if "pending" not in all_ci_status \
35- and "continuous-integration/travis-ci/pr" in all_ci_context :
36- url = "https://api.github.com/repos/miss-islington/cpython/git/refs/heads/"
37- response = requests .get (url , headers = request_headers )
38- for ref in response .json ():
39- if "backport-" in ref ["ref" ] and ref ["object" ]["sha" ] == sha :
40- backport_branch_name = ref ["ref" ].split ("/" )[- 1 ]
41- pr_url = f"https://api.github.com/repos/python/cpython/pulls?state=open&head=miss-islington:{ backport_branch_name } "
42- pr_response = requests .get (pr_url , headers = request_headers ).json ()
43- if pr_response :
44- pr_number = pr_response [0 ]["number" ]
45- normalized_pr_title = util .normalize_title (pr_response [0 ]["title" ],
46- pr_response [0 ]["body" ])
47-
48- title_match = TITLE_RE .match (normalized_pr_title )
49- if title_match :
20+ await check_ci_status_and_approval (gh , sha , leave_comment = True )
21+
22+
23+ @router .register ("pull_request_review" , action = "submitted" )
24+ async def pr_reviewed (event , gh , * args , ** kwargs ):
25+ if event .data ["pull_request" ]["user" ]["login" ] == "miss-islington" :
26+ reviewer = event .data ["review" ]["user" ]["login" ]
27+ approved = event .data ["review" ]["state" ] == "approved"
28+ if approved and await util .is_core_dev (gh , reviewer ):
29+ sha = event .data ["review" ]["commit_id" ]
30+ await check_ci_status_and_approval (gh , sha )
31+
32+
33+ async def check_ci_status_and_approval (gh , sha , leave_comment = False ):
34+
35+ result = await gh .getitem (f'/repos/python/cpython/commits/{ sha } /status' )
36+ all_ci_status = [status ["state" ] for status in result ["statuses" ]]
37+ all_ci_context = [status ["context" ] for status in result ["statuses" ]]
38+
39+ if "pending" not in all_ci_status \
40+ and "continuous-integration/travis-ci/pr" in all_ci_context :
41+ async for ref in gh .getiter ('/repos/miss-islington/cpython/git/refs/heads/' ):
42+ if "backport-" in ref ["ref" ] and ref ["object" ]["sha" ] == sha :
43+ backport_branch_name = ref ["ref" ].split ("/" )[- 1 ]
44+ async for pr_response in gh .getiter (f'/repos/python/cpython/pulls?state=open&head=miss-islington:{ backport_branch_name } ' ):
45+ pr_number = pr_response ["number" ]
46+ normalized_pr_title = util .normalize_title (
47+ pr_response ["title" ],
48+ pr_response ["body" ])
49+
50+ title_match = TITLE_RE .match (normalized_pr_title )
51+ if title_match :
52+
53+ if leave_comment :
5054 original_pr_number = title_match .group ('pr' )
51- original_pr_url = f"https://api.github.com/repos/python/cpython/pulls/{ original_pr_number } "
52- original_pr_result = requests .get (original_pr_url ,
53- headers = request_headers ).json ()
55+ original_pr_url = f"/repos/python/cpython/pulls/{ original_pr_number } "
56+ original_pr_result = await gh .getitem (original_pr_url )
5457 pr_author = original_pr_result ["user" ]["login" ]
5558 committer = original_pr_result ["merged_by" ]["login" ]
5659
5760 participants = util .get_participants (
5861 pr_author , committer )
5962 emoji = "✅" if result ['state' ] == "success" else "❌"
60- util .comment_on_pr (
61- pr_number ,
63+
64+ await comment_on_pr (gh ,
65+ pr_number = pr_number ,
6266 message = f"{ participants } : Backport status check is done, and it's a { result ['state' ]} { emoji } ." )
67+
68+ if result ['state' ] == "success" :
69+ async for review in gh .getiter (f"/repos/python/cpython/pulls/{ pr_number } /reviews" ):
70+ reviewer = review ["user" ]["login" ]
71+ approved = review ["state" ].lower () == "approved"
72+ if approved \
73+ and await util .is_core_dev (gh , reviewer ):
74+ await merge_pr (gh , pr_number , sha )
75+ break
76+
77+
78+ async def merge_pr (gh , pr_number , sha ):
79+ async for commit in gh .getiter (f"/repos/python/cpython/pulls/{ pr_number } /commits" ):
80+ if commit ["sha" ] == sha :
81+ pr_commit_msg = commit ["commit" ]["message" ].split ("\n " )
82+
83+ cleaned_up_title = f"{ pr_commit_msg [0 ]} (GH-{ pr_number } )"
84+ await gh .put (f"/repos/python/cpython/pulls/{ pr_number } /merge" ,
85+ data = {"commit_title" : cleaned_up_title ,
86+ "commit_message" : "\n " .join (pr_commit_msg [1 :]),
87+ "sha" : sha ,
88+ "merge_method" : "squash"
89+ }
90+ )
91+ break
92+
93+
94+ async def comment_on_pr (gh , pr_number , message ):
95+ """
96+ Leave a comment on a PR/Issue
97+ """
98+ issue_comment_url = f"/repos/python/cpython/issues/{ pr_number } /comments"
99+ data = {
100+ "body" : message ,
101+ }
102+ await gh .post (issue_comment_url , data = data )
0 commit comments