-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlambda_pr_webhook.py
More file actions
131 lines (112 loc) · 4.85 KB
/
lambda_pr_webhook.py
File metadata and controls
131 lines (112 loc) · 4.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import json
import logging
from utils import github, openai_utils
from pydantic import BaseModel
import boto3
from datetime import datetime
import os
class PRAnalysis(BaseModel):
title: str
summary: str # ✅ fixed (was int before)
changes: list[str]
impact: str
action_required: str
labels: list[str]
logger = logging.getLogger()
logger.setLevel(logging.INFO)
table_name = os.getenv("DYNAMODB_TABLE", "PRSummaries")
dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table(table_name)
def handler(event, context):
body = event.get("body")
if not body:
return {"statusCode": 400, "body": "No payload provided"}
payload = body if isinstance(body, dict) else json.loads(body)
action = payload.get("action")
pr = payload.get("pull_request", {})
repo = payload.get("repository", {}).get("full_name")
pr_number = pr.get("number")
diff_url = pr.get("diff_url")
commit_url = pr.get("commits_url")
pr_id = f"{pr.get('id')}-{pr_number}"
author = pr.get("user", {}).get("login")
reviewers = [r.get("login") for r in pr.get("requested_reviewers", [])]
pr_created_at = pr.get("created_at") # GitHub PR creation timestamp
pr_updated_at = pr.get("updated_at") # GitHub PR last update timestamp
logger.info(f"Processing PR {pr_number} in {repo}, {diff_url}")
logger.info(f"Action received: {action}")
try:
commit_messages = github.get_pr_commits(commit_url)
# Only analyze PR if opened, updated, or reopened
if action not in ["opened", "synchronize", "reopened"]:
if action == "closed" and pr.get("merged") is True:
table.update_item(
Key={"pr_id": pr_id, "repo": repo}, # ✅ ensure table schema only uses pr_id as key
UpdateExpression=(
"SET updated_at = :updated_at, #s = :status"
),
ExpressionAttributeNames={"#s": "status"},
ExpressionAttributeValues={
":updated_at": pr_updated_at,
":status": "merged",
},
)
logger.info("PR was merged, skipping analysis")
print("PR was merged, skipping analysis")
return {"statusCode": 200, "body": json.dumps({"status": "merged"})}
logger.info("Skipping analysis for action: {action}, {pr_id}")
table.update_item(
Key={"pr_id": pr_id, "repo": repo}, # ✅ ensure table schema only uses pr_id as key
UpdateExpression=(
"SET updated_at = :updated_at, #s = :status, reviewers = :reviewers, commit_messages = :commit_messages"
),
ExpressionAttributeNames={"#s": "status"},
ExpressionAttributeValues={
":updated_at": pr_updated_at,
":status": action,
":reviewers": json.dumps(reviewers),
":commit_messages": json.dumps(commit_messages),
},
)
logger.info("Exiting early with ignored status")
print("Exiting early with ignored status")
return {"statusCode": 200, "body": json.dumps({"status": "ignored"})}
logger.info("Continuing with PR analysis")
# Otherwise run analysis
diff_text = github.get_pr_diff(diff_url)
analysis: PRAnalysis = openai_utils.summarize_diff(diff_text, commit_messages)
changes_formatted = "\n- ".join(analysis.changes)
full_summary = f"""### {analysis.title}
**Summary:** {analysis.summary}
**Changes:**
- {changes_formatted}
**Impact:** {analysis.impact}
**Action Required:** {analysis.action_required}"""
# Update GitHub
github.update_pr_description(repo, pr_number, full_summary)
github.add_pr_labels(repo, pr_number, analysis.labels)
# Save in DynamoDB
table.put_item(
Item={
"pr_id": pr_id,
"repo": repo,
"pr_number": pr_number,
"title": analysis.title,
"summary": analysis.summary,
"changes": json.dumps(analysis.changes),
"impact": analysis.impact,
"action_required": analysis.action_required,
"labels": json.dumps(analysis.labels),
"commit_messages": json.dumps(commit_messages),
"created_at": pr_created_at,
"updated_at": pr_updated_at,
"status": action,
"author": author,
"reviewers": json.dumps(reviewers),
}
)
except Exception as e:
logger.error(f"Error processing PR: {e}", exc_info=True)
return {"statusCode": 500, "body": str(e)}
print("Exiting normally with ok status")
return {"statusCode": 200, "body": json.dumps({"status": "ok"})}