Skip to content

Commit 049bcaa

Browse files
Create pr_review_handler.py
1 parent a336bfd commit 049bcaa

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed

scripts/pr_review_handler.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import os
2+
import json
3+
from github import Github, GithubException
4+
5+
def sanitize_username(username):
6+
"""Sanitize GitHub username to prevent injection attacks"""
7+
return ''.join(c for c in username if c.isalnum() or c in ['-', '_'])
8+
9+
def handle_approval(g, repo, pr, author):
10+
"""Handle approved review scenario"""
11+
try:
12+
# Get all requested reviewers
13+
pr_obj = repo.get_pull(pr.number)
14+
requested_reviewers = [r.login for r in pr_obj.get_review_requests()[0]]
15+
16+
# Get all approvals
17+
reviews = pr_obj.get_reviews()
18+
approvals = {review.user.login for review in reviews if review.state == 'APPROVED'}
19+
20+
# Check pending reviewers
21+
pending_reviewers = [r for r in requested_reviewers if r not in approvals]
22+
23+
if not pending_reviewers:
24+
# Add LGTM label
25+
pr.add_to_labels('LGTM')
26+
27+
# Assign author
28+
pr.add_to_assignees(author)
29+
print(f"Assigned {author} to PR #{pr.number}")
30+
else:
31+
# Re-request reviews
32+
pr.create_review_request(reviewers=pending_reviewers)
33+
print(f"Re-requested reviews from {', '.join(pending_reviewers)}")
34+
35+
except GithubException as e:
36+
print(f"Error handling approval: {e}")
37+
raise
38+
39+
def handle_changes_requested(repo, pr, author, reviewer):
40+
"""Handle changes requested scenario"""
41+
try:
42+
# Remove LGTM label if exists
43+
try:
44+
pr.remove_from_labels('LGTM')
45+
except GithubException as e:
46+
if e.status != 404:
47+
raise
48+
49+
# Unassign reviewer
50+
pr.remove_from_assignees(reviewer)
51+
52+
# Assign author
53+
pr.add_to_assignees(author)
54+
print(f"Unassigned {reviewer} and assigned {author} to PR #{pr.number}")
55+
56+
except GithubException as e:
57+
print(f"Error handling changes requested: {e}")
58+
raise
59+
60+
def main():
61+
# Get inputs
62+
token = os.getenv('GITHUB_TOKEN')
63+
event_path = os.getenv('GITHUB_EVENT_PATH')
64+
65+
with open(event_path) as f:
66+
event_data = json.load(f)
67+
68+
review = event_data['review']
69+
pr_data = event_data['pull_request']
70+
repo_name = os.getenv('GITHUB_REPOSITORY')
71+
72+
# Sanitize inputs
73+
author = sanitize_username(pr_data['user']['login'])
74+
reviewer = sanitize_username(review['user']['login'])
75+
review_state = review['state'].lower()
76+
77+
# Initialize GitHub objects
78+
g = Github(token)
79+
repo = g.get_repo(repo_name)
80+
pr = repo.get_pull(pr_data['number'])
81+
82+
if review_state == 'approved':
83+
handle_approval(g, repo, pr, author)
84+
elif review_state == 'changes_requested':
85+
handle_changes_requested(repo, pr, author, reviewer)
86+
else:
87+
print(f"Ignoring review state: {review_state}")
88+
89+
if __name__ == "__main__":
90+
main()

0 commit comments

Comments
 (0)