1
+ #!/usr/bin/env python3
2
+ """
3
+ Script to automatically update the changelog with PR information.
4
+ """
5
+
6
+ import argparse
7
+ import re
8
+ import sys
9
+ from pathlib import Path
10
+
11
+
12
+ def find_unreleased_section (lines ):
13
+ """Find the line number where UNRELEASED section starts and ends."""
14
+ unreleased_start = None
15
+ content_start = None
16
+
17
+ for i , line in enumerate (lines ):
18
+ if line .strip () == "## UNRELEASED" :
19
+ unreleased_start = i
20
+ continue
21
+
22
+ if unreleased_start is not None and content_start is None :
23
+ # Skip empty lines after ## UNRELEASED
24
+ if line .strip () == "" :
25
+ continue
26
+ else :
27
+ content_start = i
28
+ break
29
+
30
+ return unreleased_start , content_start
31
+
32
+
33
+ def update_changelog (changelog_path , pr_number , pr_title , pr_url ):
34
+ """Update the changelog with the new PR entry."""
35
+
36
+ # Read the current changelog
37
+ with open (changelog_path , 'r' , encoding = 'utf-8' ) as f :
38
+ lines = f .readlines ()
39
+
40
+ # Find the UNRELEASED section
41
+ unreleased_start , content_start = find_unreleased_section (lines )
42
+
43
+ if unreleased_start is None :
44
+ print ("ERROR: Could not find '## UNRELEASED' section in changelog" )
45
+ return False
46
+
47
+ if content_start is None :
48
+ print ("ERROR: Could not find content start after UNRELEASED section" )
49
+ return False
50
+
51
+ # Create the new entry
52
+ new_entry = f"- { pr_title } [#{ pr_number } ]({ pr_url } )\n "
53
+
54
+ # Check if this PR entry already exists to avoid duplicates
55
+ for line in lines [content_start :]:
56
+ if f"[#{ pr_number } ]" in line :
57
+ print (f"Changelog entry for PR #{ pr_number } already exists" )
58
+ return False
59
+ # Stop checking when we reach the next section
60
+ if line .startswith ("## " ) and not line .strip () == "## UNRELEASED" :
61
+ break
62
+
63
+ # Insert the new entry at the beginning of the unreleased content
64
+ lines .insert (content_start , new_entry )
65
+
66
+ # Write the updated changelog
67
+ with open (changelog_path , 'w' , encoding = 'utf-8' ) as f :
68
+ f .writelines (lines )
69
+
70
+ print (f"Added changelog entry for PR #{ pr_number } : { pr_title } " )
71
+ return True
72
+
73
+
74
+ def main ():
75
+ parser = argparse .ArgumentParser (description = 'Update changelog with PR information' )
76
+ parser .add_argument ('--pr-number' , required = True , help = 'Pull request number' )
77
+ parser .add_argument ('--pr-title' , required = True , help = 'Pull request title' )
78
+ parser .add_argument ('--pr-url' , required = True , help = 'Pull request URL' )
79
+ parser .add_argument ('--changelog-path' , default = 'docs/changelog.md' , help = 'Path to changelog file' )
80
+
81
+ args = parser .parse_args ()
82
+
83
+ changelog_path = Path (args .changelog_path )
84
+
85
+ if not changelog_path .exists ():
86
+ print (f"ERROR: Changelog file not found: { changelog_path } " )
87
+ sys .exit (1 )
88
+
89
+ success = update_changelog (changelog_path , args .pr_number , args .pr_title , args .pr_url )
90
+
91
+ if not success :
92
+ sys .exit (1 )
93
+
94
+
95
+ if __name__ == '__main__' :
96
+ main ()
0 commit comments