@@ -558,6 +558,16 @@ def update_changelog(self, new_version: str) -> bool:
558558 with open (changelog_file , 'r' ) as f :
559559 content = f .read ()
560560
561+ # Check if this version already exists
562+ version_already_exists = re .search (
563+ rf'## \[{ re .escape (new_version )} \]' ,
564+ content
565+ )
566+ if version_already_exists :
567+ print (f"⚠️ WARNING: Version [{ new_version } ] already exists in CHANGELOG.md" )
568+ print (f" Skipping CHANGELOG update (appears to be already prepared)" )
569+ return True
570+
561571 # Find the [Unreleased] section
562572 unreleased_pattern = r'## \[Unreleased\]\s*\n(.*?)(?=\n## |\Z)'
563573 match = re .search (unreleased_pattern , content , re .DOTALL )
@@ -844,36 +854,6 @@ def prepare_release(self, version: str) -> bool:
844854 print (f"PREPARING RELEASE { version } " )
845855 print (f"{ '=' * 70 } \n " )
846856
847- # Pre-flight check: Ensure CHANGELOG.md has release notes
848- changelog_file = self .project_root / "CHANGELOG.md"
849- if changelog_file .exists ():
850- try :
851- with open (changelog_file , 'r' ) as f :
852- content = f .read ()
853- unreleased_match = re .search (
854- r'## \[Unreleased\]\s*\n(.*?)(?=\n## |\Z)' ,
855- content ,
856- re .DOTALL
857- )
858- if unreleased_match :
859- unreleased_content = unreleased_match .group (1 ).strip ()
860- # Check if unreleased section is mostly empty (only has section headers)
861- if not unreleased_content or unreleased_content .count ('\n ' ) < 10 :
862- message = f"""📝 CHANGELOG.md appears to have minimal content in [Unreleased] section.
863-
864- Please:
865- 1. Edit CHANGELOG.md
866- 2. Add your release notes under the [Unreleased] section
867- 3. Commit your changes:
868- git add CHANGELOG.md
869- git commit -m "docs: Add release notes for { version } "
870- 4. Press ENTER to continue with release preparation
871-
872- The script will automatically move [Unreleased] → [{ version } ] when you continue."""
873- if not self .prompt_user_continue (message ):
874- return False
875- except Exception :
876- pass
877857
878858 # Step 1: Clean up temporary files
879859 print ("\n 🧹 Step 1: Cleaning up temporary files..." )
@@ -916,6 +896,31 @@ def prepare_release(self, version: str) -> bool:
916896 print ("\n 📝 Step 5: Updating markdown documentation..." )
917897 self .update_all_markdown_files (version )
918898
899+ # Checkpoint: Final chance to edit CHANGELOG before script modifies it
900+ changelog_file = self .project_root / "CHANGELOG.md"
901+ if changelog_file .exists ():
902+ # Check if version already exists
903+ with open (changelog_file , 'r' ) as f :
904+ content = f .read ()
905+ if not re .search (rf'## \[{ re .escape (version )} \]' , content ):
906+ # Version doesn't exist yet - give user final chance to edit
907+ message = f"""📝 FINAL CHECKPOINT: CHANGELOG.md Review
908+
909+ The script is about to modify CHANGELOG.md:
910+ - It will move [Unreleased] content → [{ version } ] section
911+ - It will create a fresh [Unreleased] section
912+
913+ LAST CHANCE to edit CHANGELOG.md if needed:
914+ 1. Edit CHANGELOG.md (add/modify release notes in [Unreleased])
915+ 2. If you made changes, commit them:
916+ git add CHANGELOG.md
917+ git commit -m "docs: Update release notes for { version } "
918+ 3. Press ENTER to let the script process CHANGELOG.md
919+
920+ If CHANGELOG is already correct, just press ENTER to continue."""
921+ if not self .prompt_user_continue (message ):
922+ return False
923+
919924 # Step 6: Update CHANGELOG.md (create for 0.1.0, update for later versions)
920925 print ("\n 📝 Step 6: Updating CHANGELOG.md..." )
921926 if not self .update_changelog (version ):
0 commit comments