feat: update changelog script to categorize commits and handle new changelog creation
This commit is contained in:
		
							
								
								
									
										15
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -1,5 +1,20 @@
 | 
				
			|||||||
# Changelog
 | 
					# Changelog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.0.4] - 2025-02-16
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					- improve changelog update script to handle absolute paths and create new changelog if missing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.0.3] - 2025-02-16
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					- 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## [1.0.2] - 2025-02-16
 | 
					## [1.0.2] - 2025-02-16
 | 
				
			||||||
### Added
 | 
					### Added
 | 
				
			||||||
- Feature 1
 | 
					- Feature 1
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,7 @@
 | 
				
			|||||||
; https://docs.platformio.org/page/projectconf.html
 | 
					; https://docs.platformio.org/page/projectconf.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[common]
 | 
					[common]
 | 
				
			||||||
version = "1.0.2"
 | 
					version = "1.0.4"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[env:esp32dev]
 | 
					[env:esp32dev]
 | 
				
			||||||
platform = espressif32
 | 
					platform = espressif32
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +1,11 @@
 | 
				
			|||||||
import os
 | 
					import os
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
 | 
					import subprocess
 | 
				
			||||||
from datetime import datetime
 | 
					from datetime import datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_version():
 | 
					def get_version():
 | 
				
			||||||
    # Get the script's directory
 | 
					 | 
				
			||||||
    script_dir = os.path.dirname(os.path.abspath(__file__))
 | 
					    script_dir = os.path.dirname(os.path.abspath(__file__))
 | 
				
			||||||
    # Get the project root directory (one level up)
 | 
					 | 
				
			||||||
    project_dir = os.path.dirname(script_dir)
 | 
					    project_dir = os.path.dirname(script_dir)
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    platformio_path = os.path.join(project_dir, 'platformio.ini')
 | 
					    platformio_path = os.path.join(project_dir, 'platformio.ini')
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    with open(platformio_path, 'r') as f:
 | 
					    with open(platformio_path, 'r') as f:
 | 
				
			||||||
@@ -15,41 +13,93 @@ def get_version():
 | 
				
			|||||||
        version_match = re.search(r'version\s*=\s*"([^"]+)"', content)
 | 
					        version_match = re.search(r'version\s*=\s*"([^"]+)"', content)
 | 
				
			||||||
        return version_match.group(1) if version_match else None
 | 
					        return version_match.group(1) if version_match else None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_last_tag():
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        result = subprocess.run(['git', 'describe', '--tags', '--abbrev=0'], 
 | 
				
			||||||
 | 
					                              capture_output=True, text=True)
 | 
				
			||||||
 | 
					        return result.stdout.strip()
 | 
				
			||||||
 | 
					    except subprocess.CalledProcessError:
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def categorize_commit(commit_msg):
 | 
				
			||||||
 | 
					    """Categorize commit messages based on conventional commits"""
 | 
				
			||||||
 | 
					    lower_msg = commit_msg.lower()
 | 
				
			||||||
 | 
					    if any(x in lower_msg for x in ['feat', 'add', 'new']):
 | 
				
			||||||
 | 
					        return 'Added'
 | 
				
			||||||
 | 
					    elif any(x in lower_msg for x in ['fix', 'bug']):
 | 
				
			||||||
 | 
					        return 'Fixed'
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        return 'Changed'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_changes_from_git():
 | 
				
			||||||
 | 
					    """Get changes from git commits since last tag"""
 | 
				
			||||||
 | 
					    changes = {
 | 
				
			||||||
 | 
					        'Added': [],
 | 
				
			||||||
 | 
					        'Changed': [],
 | 
				
			||||||
 | 
					        'Fixed': []
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    last_tag = get_last_tag()
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Get commits since last tag
 | 
				
			||||||
 | 
					    git_log_command = ['git', 'log', '--pretty=format:%s']
 | 
				
			||||||
 | 
					    if last_tag:
 | 
				
			||||||
 | 
					        git_log_command.append(f'{last_tag}..HEAD')
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        result = subprocess.run(git_log_command, capture_output=True, text=True)
 | 
				
			||||||
 | 
					        commits = result.stdout.strip().split('\n')
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Filter out empty commits and categorize
 | 
				
			||||||
 | 
					        for commit in commits:
 | 
				
			||||||
 | 
					            if commit:
 | 
				
			||||||
 | 
					                category = categorize_commit(commit)
 | 
				
			||||||
 | 
					                # Clean up commit message
 | 
				
			||||||
 | 
					                clean_msg = re.sub(r'^(feat|fix|chore|docs|style|refactor|perf|test)(\(.*\))?:', '', commit).strip()
 | 
				
			||||||
 | 
					                changes[category].append(clean_msg)
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					    except subprocess.CalledProcessError:
 | 
				
			||||||
 | 
					        print("Error: Failed to get git commits")
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return changes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def update_changelog():
 | 
					def update_changelog():
 | 
				
			||||||
    version = get_version()
 | 
					    version = get_version()
 | 
				
			||||||
    today = datetime.now().strftime('%Y-%m-%d')
 | 
					    today = datetime.now().strftime('%Y-%m-%d')
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    # Get absolute paths
 | 
					 | 
				
			||||||
    script_dir = os.path.dirname(os.path.abspath(__file__))
 | 
					    script_dir = os.path.dirname(os.path.abspath(__file__))
 | 
				
			||||||
    project_dir = os.path.dirname(script_dir)
 | 
					    project_dir = os.path.dirname(script_dir)
 | 
				
			||||||
    changelog_path = os.path.join(project_dir, 'CHANGELOG.md')
 | 
					    changelog_path = os.path.join(project_dir, 'CHANGELOG.md')
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    changelog_template = f"""## [{version}] - {today}
 | 
					    # Get changes from git
 | 
				
			||||||
### Added
 | 
					    changes = get_changes_from_git()
 | 
				
			||||||
- 
 | 
					    if not changes:
 | 
				
			||||||
 | 
					        print("No changes found or error occurred")
 | 
				
			||||||
### Changed
 | 
					        return
 | 
				
			||||||
-
 | 
					    
 | 
				
			||||||
 | 
					    # Create changelog entry
 | 
				
			||||||
### Fixed
 | 
					    changelog_entry = f"## [{version}] - {today}\n"
 | 
				
			||||||
-
 | 
					    for section, entries in changes.items():
 | 
				
			||||||
"""
 | 
					        if entries:  # Only add sections that have entries
 | 
				
			||||||
 | 
					            changelog_entry += f"### {section}\n"
 | 
				
			||||||
 | 
					            for entry in entries:
 | 
				
			||||||
 | 
					                changelog_entry += f"- {entry}\n"
 | 
				
			||||||
 | 
					            changelog_entry += "\n"
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if not os.path.exists(changelog_path):
 | 
					    if not os.path.exists(changelog_path):
 | 
				
			||||||
        # Create new changelog if it doesn't exist
 | 
					 | 
				
			||||||
        with open(changelog_path, 'w') as f:
 | 
					        with open(changelog_path, 'w') as f:
 | 
				
			||||||
            f.write(f"# Changelog\n\n{changelog_template}")
 | 
					            f.write(f"# Changelog\n\n{changelog_entry}")
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        # Update existing changelog
 | 
					 | 
				
			||||||
        with open(changelog_path, 'r') as f:
 | 
					        with open(changelog_path, 'r') as f:
 | 
				
			||||||
            content = f.read()
 | 
					            content = f.read()
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if f"[{version}]" not in content:
 | 
					        if f"[{version}]" not in content:
 | 
				
			||||||
            # Only add new version if it doesn't exist
 | 
					            updated_content = content.replace("# Changelog\n", f"# Changelog\n\n{changelog_entry}")
 | 
				
			||||||
            updated_content = content.replace("# Changelog\n", f"# Changelog\n\n{changelog_template}")
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            with open(changelog_path, 'w') as f:
 | 
					            with open(changelog_path, 'w') as f:
 | 
				
			||||||
                f.write(updated_content)
 | 
					                f.write(updated_content)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            print(f"Version {version} already exists in changelog")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if __name__ == "__main__":
 | 
					if __name__ == "__main__":
 | 
				
			||||||
    update_changelog()
 | 
					    update_changelog()
 | 
				
			||||||
		Reference in New Issue
	
	Block a user