@@ -69,14 +69,14 @@ def get_file_info_by_sha(sha: str) -> Tuple[str, str]:
6969 try :
7070 with open (TARGET_FILE , 'r' , encoding = 'utf-8' ) as f :
7171 data = json .load (f )
72-
72+
7373 for ext_name , versions in data ["extensions" ].items ():
7474 for version in versions :
7575 if version ["sha256Digest" ] == sha :
7676 return version ["filename" ], version ["downloadUrl" ]
77-
77+
7878 return None , None
79-
79+
8080 except FileNotFoundError :
8181 print (f"Error: { TARGET_FILE } not found" )
8282 raise
@@ -120,7 +120,7 @@ def update_release_body(release_id: int, commit_sha: str, old_body: str, sha: st
120120 response = requests .patch (ref_url , headers = headers , json = data )
121121 response .raise_for_status ()
122122 print (f"Successfully updated tag { tag_name } " )
123-
123+
124124 sha_pattern = r'[a-fA-F0-9]{64}'
125125 new_body = old_body
126126
@@ -150,12 +150,37 @@ def update_release_body(release_id: int, commit_sha: str, old_body: str, sha: st
150150 return False
151151
152152
153+ def upload_wheel_file (wheel_url : str , upload_url : str ) -> None :
154+ """
155+ Download and upload a wheel file to GitHub release.
156+ Args:
157+ wheel_url: URL to download the wheel file from
158+ upload_url: GitHub API upload URL
159+ Raises:
160+ requests.RequestException: If download or upload fails
161+ """
162+ print (f"Downloading wheel from { wheel_url } " )
163+ wheel_response = requests .get (wheel_url )
164+ wheel_response .raise_for_status ()
165+
166+ upload_url = upload_url .replace ("{?name,label}" , "" )
167+ params = {"name" : os .path .basename (wheel_url )}
168+
169+ print (f"Uploading wheel to { upload_url } " )
170+ upload_headers = headers .copy ()
171+ upload_headers ["Content-Type" ] = "application/octet-stream"
172+ upload_response = requests .post (
173+ upload_url ,
174+ headers = upload_headers ,
175+ params = params ,
176+ data = wheel_response .content
177+ )
178+ upload_response .raise_for_status ()
179+ print ("Successfully uploaded wheel file" )
180+
181+
153182def update_release_asset (wheel_url : str , asset_id : int , release_id : int ) -> bool :
154183 try :
155- print (f"Downloading wheel from { wheel_url } " )
156- wheel_response = requests .get (wheel_url )
157- wheel_response .raise_for_status ()
158-
159184 if asset_id is not None :
160185 delete_url = f"{ base_url } /releases/assets/{ asset_id } "
161186 delete_response = requests .delete (delete_url , headers = headers )
@@ -166,21 +191,8 @@ def update_release_asset(wheel_url: str, asset_id: int, release_id: int) -> bool
166191 response = requests .get (release_url , headers = headers )
167192 response .raise_for_status ()
168193 release_info = response .json ()
169- upload_url = release_info ["upload_url" ].replace ("{?name,label}" , "" )
170-
171- upload_headers = headers .copy ()
172- upload_headers ["Content-Type" ] = "application/octet-stream"
173- params = {"name" : os .path .basename (wheel_url )}
174-
175- print (f"Uploading new wheel to { upload_url } " )
176- upload_response = requests .post (
177- upload_url ,
178- headers = upload_headers ,
179- params = params ,
180- data = wheel_response .content
181- )
182- upload_response .raise_for_status ()
183- print ("Successfully updated wheel file" )
194+
195+ upload_wheel_file (wheel_url , release_info ["upload_url" ])
184196 return True
185197
186198 except requests .RequestException as e :
@@ -239,7 +251,6 @@ def check_tag_exists(tag_name: str) -> bool:
239251def create_release (release_data : Dict [str , str ], wheel_url : str = None ) -> None :
240252 try :
241253 url = f"{ base_url } /releases"
242- # Create release
243254 response = requests .post (
244255 url ,
245256 json = release_data ,
@@ -251,24 +262,7 @@ def create_release(release_data: Dict[str, str], wheel_url: str = None) -> None:
251262
252263 # Upload wheel file if URL is provided
253264 if wheel_url :
254- print (f"Downloading wheel from { wheel_url } " )
255- wheel_response = requests .get (wheel_url )
256- wheel_response .raise_for_status ()
257-
258- upload_url = release_info ["upload_url" ].replace ("{?name,label}" , "" )
259- params = {"name" : os .path .basename (wheel_url )}
260-
261- print (f"Uploading wheel to { upload_url } " )
262- upload_headers = headers .copy ()
263- upload_headers ["Content-Type" ] = "application/octet-stream"
264- upload_response = requests .post (
265- upload_url ,
266- headers = upload_headers ,
267- params = params ,
268- data = wheel_response .content
269- )
270- upload_response .raise_for_status ()
271- print ("Successfully uploaded wheel file" )
265+ upload_wheel_file (wheel_url , release_info ["upload_url" ])
272266
273267 except requests .exceptions .RequestException as e :
274268 print (f"\n Error creating release for { release_data ['tag_name' ]} " )
@@ -285,62 +279,57 @@ def generate_release_body(history_note: str, sha256_digest: str, filename: str)
285279 return f"{ history_note } \n \n SHA256 hashes of the release artifacts:\n ```\n { sha256_digest } { filename } \n ```\n "
286280
287281
288- def get_history_note (wheel_url : str , version : str ) -> str :
289- """Download wheel package and extract HISTORY.rst to find version notes"""
290- try :
291- # Download wheel file
292- response = requests .get (wheel_url )
293- response .raise_for_status ()
294-
295- with tempfile .TemporaryFile () as temp_file :
296- temp_file .write (response .content )
297- temp_file .seek (0 )
298-
299- # Open wheel as zip
300- with zipfile .ZipFile (temp_file , 'r' ) as wheel :
301- # Find DESCRIPTION.rst file
302- history_files = [f for f in wheel .namelist () if f .endswith ('DESCRIPTION.rst' )]
303- if not history_files :
304- return "No history notes found"
305-
306- history_content = wheel .read (history_files [0 ]).decode ('utf-8' )
307-
308- # Match any line starting with the version number
309- version_pattern = rf"^{ re .escape (version )} .*?\n(?:[-=+~]+\n)?(.*?)(?=^[\d.]+[a-z0-9].*?(?:\n[-=+~]+)?|\Z)"
310- match = re .search (version_pattern , history_content , re .DOTALL | re .MULTILINE )
311-
312- if match :
313- return match .group (1 ).strip ()
314-
315- return "No history notes found for this version"
316-
317- except Exception as e :
318- print (f"Error getting history notes: { e } " )
319- return "No history notes found for this version"
282+ def get_history_note (version : str , extension_name : str , wheel_url : str = None ) -> str :
283+ """
284+ Get history notes for a version, first trying from source code then from wheel package.
320285
286+ Args:
287+ version: Version string to search for
288+ extension_name: Name of the extension
289+ wheel_url: Optional URL to download wheel package if source check fails
321290
322- def get_history_note_from_source (version : str , extension_name : str ) -> str :
323- """Get history notes from source code HISTORY.rst"""
291+ Returns:
292+ str: History notes for the version or default message if none found
293+ """
294+ version_pattern = rf"^{ re .escape (version )} .*?\n(?:[-=+~]+\n)?(.*?)(?=^[\d.]+[a-z0-9].*?(?:\n[-=+~]+)?|\Z)"
295+ # First try to get history from source code
324296 try :
325297 history_path = f"src/{ extension_name } /HISTORY.rst"
326- if not os .path .exists (history_path ):
327- return "No history notes found"
298+ if os .path .exists (history_path ):
299+ with open (history_path , 'r' , encoding = 'utf-8' ) as f :
300+ history_content = f .read ()
301+
302+ # Match any line starting with the version number
303+ match = re .search (version_pattern , history_content , re .DOTALL | re .MULTILINE )
304+ if match :
305+ return match .group (1 ).strip ()
306+ except Exception as e :
307+ print (f"Error reading history from source: { e } " )
328308
329- with open (history_path , 'r' , encoding = 'utf-8' ) as f :
330- history_content = f .read ()
309+ # If source check failed and wheel_url is provided, try wheel package
310+ if wheel_url :
311+ try :
312+ response = requests .get (wheel_url )
313+ response .raise_for_status ()
331314
332- # Match any line starting with the version number
333- version_pattern = rf"^ { re . escape ( version ) } .*?\n(?:[-=+~]+\n)?(.*?)(?=^[\d.]+[a-z0-9].*?(?:\n[-=+~]+)?|\Z)"
334- match = re . search ( version_pattern , history_content , re . DOTALL | re . MULTILINE )
315+ with tempfile . TemporaryFile () as temp_file :
316+ temp_file . write ( response . content )
317+ temp_file . seek ( 0 )
335318
336- if match :
337- return match .group (1 ).strip ()
319+ with zipfile .ZipFile (temp_file , 'r' ) as wheel :
320+ history_files = [f for f in wheel .namelist () if f .endswith ('DESCRIPTION.rst' )]
321+ if history_files :
322+ history_content = wheel .read (history_files [0 ]).decode ('utf-8' )
338323
339- return "No history notes found in source code"
324+ # Match any line starting with the version number
325+ match = re .search (version_pattern , history_content , re .DOTALL | re .MULTILINE )
326+ if match :
327+ return match .group (1 ).strip ()
328+ except Exception as e :
329+ print (f"Error getting history notes from wheel: { e } " )
340330
341- except Exception as e :
342- print (f"Error reading history from source: { e } " )
343- return "No history notes found for this version"
331+ # Return default message if no history found
332+ return f"Release { extension_name } { version } "
344333
345334
346335def main ():
@@ -389,20 +378,13 @@ def main():
389378 print (f"Tag { tag_name } already exists, skipping..." )
390379 continue
391380
392- # Try to get history notes from source code first
393- print (f"Getting history notes from source code..." )
394381 extension_name = re .match (r"^(.*?)[-_]\d+\.\d+\.\d+" , filename ).group (1 )
395- history_note = get_history_note_from_source (version , extension_name )
396-
397- # If no notes found in source code, try wheel package
398- if "No history notes found" in history_note :
399- print (f"No history notes found in source code, trying wheel package..." )
400- history_note = get_history_note (extension_info ["downloadUrl" ], version )
401-
402- # If still no notes found, use default release note
403- if "No history notes found" in history_note :
404- print (f"No history notes found in wheel package, using default release note..." )
405- history_note = f"Release { extension_name } { version } "
382+ print (f"Getting history notes..." )
383+ history_note = get_history_note (
384+ version ,
385+ extension_name ,
386+ extension_info ["downloadUrl" ]
387+ )
406388
407389 # Generate release body
408390 release_body = generate_release_body (history_note , extension_info ["sha256Digest" ], filename )
0 commit comments