1
- import requests
2
- import os
3
1
import re
4
2
5
- from gidgethub import sansio , routing
3
+ from gidgethub import routing
6
4
7
5
from . import util
8
6
11
9
TITLE_RE = re .compile (r'\[(?P<branch>\d+\.\d+)\].+?(?P<pr>\d+)\)' )
12
10
13
11
14
-
15
12
@router .register ("status" )
16
13
async def check_status (event , gh , * args , ** kwargs ):
17
14
"""
@@ -20,43 +17,86 @@ async def check_status(event, gh, *args, **kwargs):
20
17
if event .data ["commit" ].get ("committer" ) \
21
18
and event .data ["commit" ]["committer" ]["login" ] == "miss-islington" :
22
19
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 :
50
54
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 )
54
57
pr_author = original_pr_result ["user" ]["login" ]
55
58
committer = original_pr_result ["merged_by" ]["login" ]
56
59
57
60
participants = util .get_participants (
58
61
pr_author , committer )
59
62
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 ,
62
66
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