88import sys
99
1010import requests
11+ import time
12+
1113
1214
1315def main ():
@@ -19,9 +21,7 @@ def main():
1921 "X-GitHub-Api-Version" : "2022-11-28" ,
2022 }
2123 )
22- NUMBER , head_ref = int (sys .argv [1 ]), sys .argv [2 ]
23- EV = json .loads (sys .stdin .read ())
24- REPO = EV ["repository" ]
24+ NUMBER , head_ref , REPO = int (sys .argv [1 ]), sys .argv [2 ], sys .argv [3 ]
2525
2626 def must (cond , msg ):
2727 if not cond :
@@ -60,44 +60,58 @@ def must(cond, msg):
6060 pr_numbers = list (map (int , pr_numbers ))
6161 print (pr_numbers )
6262 must (pr_numbers and pr_numbers [0 ] == NUMBER , "Extracted PR numbers not seems right!" )
63-
63+
6464 for n in pr_numbers :
6565 print (f":: Checking PR status #{ n } ... " , end = "" )
66- resp = gh .get (f"https://api.github.com/repos/{ REPO } /pulls/{ n } " )
67- must (resp .ok , "Error Getting PR Object!" )
66+
67+ # Get PR object with mergeable state
68+ resp = gh .get (
69+ f"https://api.github.com/repos/{ REPO } /pulls/{ n } " ,
70+ headers = {"Accept" : "application/vnd.github.v3+json" }
71+ )
72+ must (resp .ok , f"Error getting PR #{ n } !" )
6873 pr_obj = resp .json ()
69-
70- resp = gh .get (f"https://api.github.com/repos/{ REPO } /pulls/{ NUMBER } /reviews" )
71- must (resp .ok , "Error Getting PR Reviews!" )
72- reviews = resp .json ()
73- idmap = {}
74- approved = True # TODO: REMOVE
75- for r in reviews :
76- s = r ["state" ]
77- if s not in ("COMMENTED" ,):
78- idmap [r ["user" ]["login" ]] = r ["state" ]
79-
80- for u , cc in idmap .items ():
81- approved = approved or cc == "APPROVED"
82- must (
83- cc in ("APPROVED" , "DISMISSED" ),
84- f"@{ u } has stamped PR #{ n } `{ cc } `, please resolve it first!" ,
85- )
86-
87- must (approved , f"PR #{ n } is not approved yet!" )
88-
89- resp = gh .get (f'https://api.github.com/repos/{ REPO } /commits/{ pr_obj ["head" ]["sha" ]} /check-runs' )
90- must (resp .ok , "Error getting check runs status!" )
91- checkruns = resp .json ()
92- for cr in checkruns ["check_runs" ]:
93- status = cr .get ("conclusion" , cr ["status" ])
94- name = cr ["name" ]
95- if name == "Copilot for PRs" :
96- continue
97- must (
98- status in ("success" , "neutral" ),
99- f"PR #{ n } check-run `{ name } `'s status `{ status } ` is not success!" ,
74+
75+ # Check if GitHub is still calculating the mergeable state
76+ mergeable_state = pr_obj .get ("mergeable_state" , "unknown" )
77+ if mergeable_state == "unknown" :
78+ # Wait and try again - GitHub is still calculating
79+ time .sleep (2 )
80+ resp = gh .get (
81+ f"https://api.github.com/repos/{ REPO } /pulls/{ n } " ,
82+ headers = {"Accept" : "application/vnd.github.v3+json" }
10083 )
84+ must (resp .ok , f"Error getting PR #{ n } on retry!" )
85+ pr_obj = resp .json ()
86+ mergeable_state = pr_obj .get ("mergeable_state" , "unknown" )
87+
88+ # Check mergeable state
89+ must (
90+ mergeable_state != "blocked" ,
91+ f"PR #{ n } is blocked from merging (possibly failing status checks)!"
92+ )
93+ must (
94+ mergeable_state != "dirty" ,
95+ f"PR #{ n } has merge conflicts that need to be resolved!"
96+ )
97+ must (
98+ mergeable_state != "unstable" ,
99+ f"PR #{ n } has failing or pending required status checks!"
100+ )
101+ must (
102+ mergeable_state == "clean" ,
103+ f"PR #{ n } is not ready to merge (state: { mergeable_state } )!"
104+ )
105+
106+ # If you still want to verify approval status specifically
107+ resp = gh .get (f"https://api.github.com/repos/{ REPO } /pulls/{ n } /reviews" )
108+ must (resp .ok , f"Error getting reviews for PR #{ n } !" )
109+ reviews = resp .json ()
110+
111+ # Check if at least one approval exists
112+ has_approval = any (review ["state" ] == "APPROVED" for review in reviews )
113+ must (has_approval , f"PR #{ n } has no approvals!" )
114+
101115 print ("SUCCESS!" )
102116
103117 print (":: All PRs are ready to be landed!" )
0 commit comments