From 8eb03956140d97a7612b5f67dbf94043b2a37b41 Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Wed, 4 Jun 2025 09:46:34 +0545 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9A=20docs(changelog):=20update=20chan?= =?UTF-8?q?gelog=20format=20and=20add=20ChangelogGenerator=20class=20docum?= =?UTF-8?q?entation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 15 ++++ devtools/changelog/generator.py | 127 ++++++++++++++++++++------------ 2 files changed, 96 insertions(+), 46 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..bdfc18c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +## 1.0.0 + +Version 1.0.0 - Initial Release + +✨ Added +- Initial project structure and files + +📝 Documentation +- Updated LICENSE with appropriate licensing information + +🔧 Maintenance +- Initial commit of project to version control + +Please note that this is the first release, and future updates will include more features, bug fixes, and improvements. + diff --git a/devtools/changelog/generator.py b/devtools/changelog/generator.py index 73ee376..d02bac2 100644 --- a/devtools/changelog/generator.py +++ b/devtools/changelog/generator.py @@ -1,26 +1,57 @@ """ Changelog generation using AI. """ + from typing import List, Dict, Optional from ..shared.ai import AIService from ..shared.config import Config from ..shared.git import GitService + class ChangelogGenerator(AIService): """AI-powered changelog generator.""" - - def __init__(self, config: Config): - """Initialize changelog generator.""" + + def __init__(self, config: Config, git_service: Optional[GitService] = None): + """Initialize changelog generator. + + Args: + config: Configuration object + git_service: Optional GitService instance + """ super().__init__(config) - - def generate_changelog(self, version: str, changes: List[Dict[str, str]], temperature: Optional[float] = None) -> str: + self.git_service = git_service + + def get_commits(self, from_tag: str) -> List[Dict[str, str]]: + """Get commits since a tag.""" + if not self.git_service: + raise ValueError("GitService not provided") + return self.git_service.get_commits_since_tag(from_tag) + + def get_commits_since_date(self, days: int) -> List[Dict[str, str]]: + """Get commits since a date.""" + if not self.git_service: + raise ValueError("GitService not provided") + return self.git_service.get_commits_since_date(days) + + def get_last_n_commits(self, n: int) -> List[Dict[str, str]]: + """Get last N commits.""" + if not self.git_service: + raise ValueError("GitService not provided") + return self.git_service.get_commit_history(limit=n) + + def generate_changelog( + self, + version: str, + changes: List[Dict[str, str]], + temperature: Optional[float] = None, + ) -> str: """Generate a changelog from a list of changes. - + Args: version: Version number for the changelog - changes: List of changes, each with 'type' and 'description' + changes: List of changes, each with 'message' and 'hash' temperature: AI temperature for generation - + Returns: Generated changelog content """ @@ -39,66 +70,69 @@ class ChangelogGenerator(AIService): - 🔧 Maintenance - 🗑️ Removed - 🔒 Security""" - + # Format changes for the prompt - changes_text = "\n".join( - f"{change['type']}: {change['description']}" - for change in changes - ) - - user_prompt = f"Generate a changelog for version {version} with these changes:\n\n{changes_text}" - + changes_text = "\n".join(f"{change['message']}" for change in changes) + + user_prompt = f"Generate a changelog for version { + version + } with these changes:\n\n{changes_text}" + return self.generate_completion( - system_prompt, - user_prompt, - temperature=temperature + system_prompt, user_prompt, temperature=temperature ) - - def update_changelog_file(self, version: str, changes: List[Dict[str, str]], output_file: str, temperature: Optional[float] = None) -> None: + + def update_changelog_file( + self, + version: str, + changes: List[Dict[str, str]], + output_file: str, + temperature: Optional[float] = None, + ) -> None: """Generate and update a changelog file. - + Args: version: Version number for the changelog - changes: List of changes, each with 'type' and 'description' + changes: List of changes, each with 'message' and 'hash' output_file: Path to the changelog file temperature: AI temperature for generation """ changelog_content = self.generate_changelog(version, changes, temperature) - + # Read existing changelog if it exists try: with open(output_file, "r") as f: existing_content = f.read() except FileNotFoundError: existing_content = "" - + # Add new changelog entry at the top new_content = f"## {version}\n\n{changelog_content}\n\n" if existing_content: new_content += existing_content - + # Write updated changelog with open(output_file, "w") as f: f.write(new_content) - + def parse_changes_from_text(self, text: str) -> List[Dict[str, str]]: """Parse changes from text input. - + Args: text: Text containing changes - + Returns: List of changes with type and description """ changes = [] current_type = None current_description = [] - + for line in text.splitlines(): line = line.strip() if not line: continue - + # Check if line starts with a type marker type_markers = { "✨": "Added", @@ -108,32 +142,33 @@ class ChangelogGenerator(AIService): "📝": "Documentation", "🔧": "Maintenance", "🗑️": "Removed", - "🔒": "Security" + "🔒": "Security", } - + for marker, type_ in type_markers.items(): if line.startswith(marker): # Save previous change if exists if current_type and current_description: - changes.append({ - "type": current_type, - "description": " ".join(current_description) - }) - + changes.append( + { + "type": current_type, + "description": " ".join(current_description), + } + ) + # Start new change current_type = type_ - current_description = [line[len(marker):].strip()] + current_description = [line[len(marker) :].strip()] break else: # Continue current change if current_type: current_description.append(line) - + # Add last change if exists if current_type and current_description: - changes.append({ - "type": current_type, - "description": " ".join(current_description) - }) - - return changes \ No newline at end of file + changes.append( + {"type": current_type, "description": " ".join(current_description)} + ) + + return changes