1
1
from os import getenv
2
+ from typing import Optional
2
3
3
4
import requests
4
5
5
6
6
7
def get_github_prs (token : str , owner : str , repo : str , label : str = "" , state : str = "all" ) -> list [dict ]:
7
8
"""
8
- Fetches pull requests from a GitHub repository that match a given milestone and label .
9
+ Fetches pull requests from a GitHub repository that match a given label and state .
9
10
10
11
Args:
11
12
token (str): GitHub token.
@@ -23,39 +24,10 @@ def get_github_prs(token: str, owner: str, repo: str, label: str = "", state: st
23
24
"Accept" : "application/vnd.github.v3+json" ,
24
25
}
25
26
26
- milestone_id = None
27
- milestone_url = f"https://api.github.com/repos/{ owner } /{ repo } /milestones"
28
- params = {"state" : "open" }
29
-
30
- try :
31
- response = requests .get (milestone_url , headers = headers , params = params )
32
- response .raise_for_status ()
33
- milestones = response .json ()
34
-
35
- if len (milestones ) > 2 :
36
- print ("More than two milestones found, unable to determine the milestone required." )
37
- exit (1 )
38
-
39
- # milestones.pop()
40
- for ms in milestones :
41
- if ms ["title" ] != "Future" :
42
- milestone_id = ms ["number" ]
43
- print (f"Gathering PRs with milestone { ms ['title' ]} ..." )
44
- break
45
-
46
- if not milestone_id :
47
- print (f"No suitable milestone found in repository '{ owner } /{ repo } '." )
48
- exit (1 )
49
-
50
- except requests .exceptions .RequestException as e :
51
- print (f"Error fetching milestones: { e } " )
52
- exit (1 )
53
-
54
- # This endpoint allows filtering by milestone and label. A PR in GH's perspective is a type of issue.
27
+ # This endpoint allows filtering by label(and milestone). A PR in GH's perspective is a type of issue.
55
28
prs_url = f"https://api.github.com/repos/{ owner } /{ repo } /issues"
56
29
params = {
57
30
"state" : state ,
58
- "milestone" : milestone_id ,
59
31
"labels" : label ,
60
32
"per_page" : 100 ,
61
33
}
@@ -83,14 +55,15 @@ def get_github_prs(token: str, owner: str, repo: str, label: str = "", state: st
83
55
return all_prs
84
56
85
57
86
- def get_prs (pull_request_items : list [dict ], label : str = "" , state : str = "all" ) -> list [dict ]:
58
+ def get_prs (pull_request_items : list [dict ], label : str = "" , state : str = "all" , milestone_number : Optional [ int ] = None ) -> list [dict ]:
87
59
"""
88
60
Returns a list of pull requests after applying the label and state filters.
89
61
90
62
Args:
91
63
pull_request_items (list[dict]): List of PR items.
92
64
label (str): The label name. Filter is not applied when empty string.
93
65
state (str): State of PR, e.g. open, closed, all
66
+ milestone_number (Optional[int]): The milestone number to filter by. If None, no milestone filtering is applied.
94
67
95
68
Returns:
96
69
list: A list of dictionaries, where each dictionary represents a pull request.
@@ -99,11 +72,20 @@ def get_prs(pull_request_items: list[dict], label: str = "", state: str = "all")
99
72
pr_list = []
100
73
count = 0
101
74
for pr in pull_request_items :
102
- if state in [pr ["state" ], "all" ] and (not label or [item for item in pr ["labels" ] if item ["name" ] == label ]):
103
- pr_list .append (pr )
104
- count += 1
75
+ if state not in [pr ["state" ], "all" ]:
76
+ continue
77
+
78
+ if label and not [item for item in pr ["labels" ] if item ["name" ] == label ]:
79
+ continue
80
+
81
+ if milestone_number :
82
+ if not pr .get ("milestone" ) or pr ["milestone" ]["number" ] != milestone_number :
83
+ continue
84
+
85
+ pr_list .append (pr )
86
+ count += 1
105
87
106
- print (f"Found { count } PRs with { label if label else 'no filter on' } label and state as { state } " )
88
+ print (f"Found { count } PRs with { label if label else 'no filter on' } label, state as { state } , and milestone { pr . get ( "milestone" ,{}). get ( "number" , "None" ) } " )
107
89
108
90
return pr_list
109
91
@@ -204,24 +186,33 @@ def update_pull_request_description(token: str, owner: str, repo: str, pr_number
204
186
205
187
print (f"Fetching { state } PRs for { repository_owner } /{ repository_name } ..." )
206
188
207
- pull_requests = get_github_prs (github_token , repository_owner , repository_name )
189
+ # First, get all PRs to find the release PR and determine the milestone
190
+ all_pull_requests = get_github_prs (github_token , repository_owner , repository_name )
208
191
209
- if not pull_requests :
210
- print ("No matching pull requests found" )
192
+ if not all_pull_requests :
193
+ print ("No pull requests found" )
211
194
exit (1 )
212
195
213
- print (f"\n Found total of { len (pull_requests )} pull requests" )
196
+ print (f"\n Found total of { len (all_pull_requests )} pull requests" )
214
197
215
- release_pr = get_prs (pull_requests , "release" , "open" )
198
+ release_pr = get_prs (all_pull_requests , "release" , "open" )
216
199
217
200
if len (release_pr ) != 1 :
218
201
print (f"Unable to find the exact release PR. Returned result: { release_pr } " )
219
202
exit (1 )
220
203
221
204
print (f"Found release PR: { release_pr [0 ]['title' ]} " )
222
205
223
- enhancement_prs = get_prs (pull_requests , "enhancement" , "closed" )
224
- bug_fix_prs = get_prs (pull_requests , "bug" , "closed" )
206
+ release_milestone_number = release_pr [0 ].get ("milestone" ,{}).get ("number" ,None )
207
+
208
+ if not release_milestone_number :
209
+ print ("Release PR does not have a milestone assigned." )
210
+ exit (1 )
211
+
212
+ print (f"Using milestone number: { release_milestone_number } " )
213
+
214
+ enhancement_prs = get_prs (all_pull_requests , "enhancement" , "closed" , release_milestone_number )
215
+ bug_fix_prs = get_prs (all_pull_requests , "bug" , "closed" , release_milestone_number )
225
216
226
217
description_content = "# Release notes\n "
227
218
description_content += f"## Features\n { get_pr_descriptions (enhancement_prs )} " if enhancement_prs else ""
0 commit comments