|
12 | 12 | import re |
13 | 13 | import subprocess |
14 | 14 | import sys |
| 15 | +from datetime import datetime |
15 | 16 | from pathlib import Path |
16 | 17 | from typing import Tuple |
17 | 18 |
|
@@ -51,6 +52,52 @@ def update_version(new_version: str) -> None: |
51 | 52 | print(f"Updated __init__.py version to {new_version}") |
52 | 53 |
|
53 | 54 |
|
| 55 | +def update_changelog(new_version: str) -> None: |
| 56 | + """Move Unreleased content to new version section in CHANGELOG.md""" |
| 57 | + changelog_path = Path("CHANGELOG.md") |
| 58 | + if not changelog_path.exists(): |
| 59 | + print("Warning: CHANGELOG.md not found, skipping changelog update") |
| 60 | + return |
| 61 | + |
| 62 | + content = changelog_path.read_text(encoding="utf-8") |
| 63 | + |
| 64 | + # Check if version already exists |
| 65 | + if f"## [{new_version}]" in content: |
| 66 | + print(f"Version {new_version} already exists in CHANGELOG.md") |
| 67 | + return |
| 68 | + |
| 69 | + # Find Unreleased section |
| 70 | + import re |
| 71 | + from datetime import datetime |
| 72 | + |
| 73 | + unreleased_match = re.search(r"(## \[Unreleased\])(.*?)(?=\n## \[|$)", content, re.DOTALL) |
| 74 | + |
| 75 | + if not unreleased_match: |
| 76 | + print("Warning: [Unreleased] section not found in CHANGELOG.md") |
| 77 | + return |
| 78 | + |
| 79 | + unreleased_content = unreleased_match.group(2).strip() |
| 80 | + |
| 81 | + if not unreleased_content: |
| 82 | + print("Warning: [Unreleased] section is empty") |
| 83 | + return |
| 84 | + |
| 85 | + # Get today's date |
| 86 | + today = datetime.now().strftime("%Y-%m-%d") |
| 87 | + |
| 88 | + # Create new version section |
| 89 | + new_section = f"\n\n## [{new_version}] - {today}\n\n{unreleased_content}" |
| 90 | + |
| 91 | + # Replace content: keep Unreleased header but empty its content |
| 92 | + new_content = content.replace( |
| 93 | + unreleased_match.group(0), |
| 94 | + f"## [Unreleased]{new_section}" |
| 95 | + ) |
| 96 | + |
| 97 | + changelog_path.write_text(new_content, encoding="utf-8") |
| 98 | + print(f"Updated CHANGELOG.md: moved Unreleased content to [{new_version}]") |
| 99 | + |
| 100 | + |
54 | 101 | def parse_version(version: str) -> Tuple[int, int, int]: |
55 | 102 | """Parse semantic version string""" |
56 | 103 | try: |
@@ -109,7 +156,7 @@ def create_and_push_tag(version: str, dry_run: bool = False) -> None: |
109 | 156 |
|
110 | 157 | if not dry_run: |
111 | 158 | # Commit version changes |
112 | | - run_command(["git", "add", "pyproject.toml", "src/repomix/__init__.py"]) |
| 159 | + run_command(["git", "add", "pyproject.toml", "src/repomix/__init__.py", "CHANGELOG.md"]) |
113 | 160 | run_command(["git", "commit", "-m", f"bump: version {version}"]) |
114 | 161 |
|
115 | 162 | # Create tag |
@@ -162,8 +209,11 @@ def main(): |
162 | 209 |
|
163 | 210 | # Update version files |
164 | 211 | update_version(new_version) |
| 212 | + |
| 213 | + # Update CHANGELOG |
| 214 | + update_changelog(new_version) |
165 | 215 | else: |
166 | | - print("[DRY RUN] Would update version files") |
| 216 | + print("[DRY RUN] Would update version files and CHANGELOG") |
167 | 217 |
|
168 | 218 | # Create and push tag |
169 | 219 | create_and_push_tag(new_version, args.dry_run) |
|
0 commit comments