Skip to content

Commit 33ecfbf

Browse files
committed
Updated ghstack perm check
1 parent 9c7d124 commit 33ecfbf

File tree

2 files changed

+52
-39
lines changed

2 files changed

+52
-39
lines changed

.github/workflows/issue_comment.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ jobs:
6969
run: |
7070
pip install requests ghstack
7171
echo ${{ github.event.issue.number }}
72-
.github/workflows/scripts/ghstack-perm-check.py ${{ github.event.issue.number }} ${{steps.get-pr.outputs.pr_branch}} <<'EOF'
73-
${{ toJson(github) }}
72+
.github/workflows/scripts/ghstack-perm-check.py ${{ github.event.issue.number }} ${{steps.get-pr.outputs.pr_branch}} ${{ github.repository }}
7473
EOF
7574
env:
7675
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}

.github/workflows/scripts/ghstack-perm-check.py

Lines changed: 51 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import sys
99

1010
import requests
11+
import time
12+
1113

1214

1315
def 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

Comments
 (0)