66GITHUB_TOKEN = os .environ ['GITHUB_TOKEN' ]
77REPO = os .environ ['GITHUB_REPOSITORY' ]
88RELEASE_TAG = os .environ .get ('RELEASE_TAG' , 'Unreleased' )
9+ START_DATE_STR = os .environ .get ('START_DATE' ) # expected format: yyyy-mm-dd
10+ END_DATE_STR = os .environ .get ('END_DATE' ) # expected format: yyyy-mm-dd
11+
12+ START_DATE = datetime .fromisoformat (START_DATE_STR ) if START_DATE_STR else None
13+ END_DATE = datetime .fromisoformat (END_DATE_STR ) if END_DATE_STR else None
14+
915API_URL = f"https://api.github.com/repos/{ REPO } /commits"
1016HEADERS = {"Authorization" : f"token { GITHUB_TOKEN } " }
1117
1218def fetch_commits ():
1319 commits = []
1420 page = 1
21+ params = {
22+ "per_page" : 100 ,
23+ }
24+ if START_DATE_STR :
25+ params ["since" ] = START_DATE_STR + "T00:00:00Z"
26+ if END_DATE_STR :
27+ params ["until" ] = END_DATE_STR + "T23:59:59Z"
28+
1529 while True :
16- response = requests .get (API_URL , headers = HEADERS , params = {"per_page" : 100 , "page" : page })
30+ params ["page" ] = page
31+ response = requests .get (API_URL , headers = HEADERS , params = params )
1732 data = response .json ()
1833 if not data or 'message' in data :
1934 break
2035 commits .extend (data )
2136 page += 1
2237 return commits
2338
39+ def filter_commits_by_date (commits ):
40+ if not START_DATE and not END_DATE :
41+ return commits
42+ filtered = []
43+ for commit in commits :
44+ commit_date = datetime .fromisoformat (commit ['commit' ]['author' ]['date' ].replace ("Z" , "+00:00" ))
45+ if START_DATE and commit_date < START_DATE :
46+ continue
47+ if END_DATE and commit_date > END_DATE :
48+ continue
49+ filtered .append (commit )
50+ return filtered
51+
2452def categorize_commits (commits ):
2553 categories = {
2654 "Reliability" : [],
@@ -35,23 +63,28 @@ def categorize_commits(commits):
3563 url = commit ['html_url' ]
3664 entry = f"- { message .splitlines ()[0 ]} [{ sha [:7 ]} ]({ url } )"
3765 # Simple categorization based on keywords
38- if "fix" in message .lower ():
66+ msg_lower = message .lower ()
67+ if "fix" in msg_lower :
3968 categories ["Reliability" ].append (entry )
40- elif "feature" in message . lower () or "add" in message . lower () :
69+ elif "feature" in msg_lower or "add" in msg_lower :
4170 categories ["New Features" ].append (entry )
42- elif "break" in message . lower () or "remove" in message . lower () :
71+ elif "break" in msg_lower or "remove" in msg_lower :
4372 categories ["Breaking Changes" ].append (entry )
44- elif "arch" in message . lower () :
73+ elif "arch" in msg_lower :
4574 categories ["New Architecture-specific changes" ].append (entry )
4675 else :
4776 categories ["Other" ].append (entry )
4877 return categories
4978
5079def generate_release_notes (commits , categories ):
51- dates = [commit ['commit' ]['author' ]['date' ] for commit in commits ]
52- dates = sorted (dates )
53- start_date = datetime .fromisoformat (dates [0 ].replace ("Z" , "+00:00" )).strftime ("%m/%d/%Y" )
54- end_date = datetime .fromisoformat (dates [- 1 ].replace ("Z" , "+00:00" )).strftime ("%m/%d/%Y" )
80+ if commits :
81+ dates = [commit ['commit' ]['author' ]['date' ] for commit in commits ]
82+ dates = sorted (dates )
83+ start_date = datetime .fromisoformat (dates [0 ].replace ("Z" , "+00:00" )).strftime ("%m/%d/%Y" )
84+ end_date = datetime .fromisoformat (dates [- 1 ].replace ("Z" , "+00:00" )).strftime ("%m/%d/%Y" )
85+ else :
86+ start_date = END_DATE_STR or "N/A"
87+ end_date = END_DATE_STR or "N/A"
5588
5689 notes = []
5790 notes .append (f"{ RELEASE_TAG } Release Notes" )
@@ -70,6 +103,7 @@ def generate_release_notes(commits, categories):
70103
71104def main ():
72105 commits = fetch_commits ()
106+ commits = filter_commits_by_date (commits )
73107 categories = categorize_commits (commits )
74108 release_notes = generate_release_notes (commits , categories )
75109 with open ("release_notes.md" , "w" , encoding = "utf-8" ) as f :
0 commit comments