diff --git a/CHANGELOG.md b/CHANGELOG.md index bdfc18c..401f25a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,30 @@ ## 1.0.0 -Version 1.0.0 - Initial Release - -✨ Added -- Initial project structure and files - 📝 Documentation -- Updated LICENSE with appropriate licensing information + +- 📚 docs(changelog): updated changelog format for clarity and consistency +- 📚 docs(changelog): added documentation for ChangelogGenerator class + +🚀 Performance + +- No performance changes in this version + +🐛 Fixed + +- No fixes in this version 🔧 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. +- Updated LICENSE file for legal compliance +🗑️ Removed + +- No features or components removed in this version + +🔒 Security + +- No security improvements in this version + +✨ Added + +- Initial commit of project files and structure diff --git a/README.md b/README.md index 6c3aaa1..bd804fb 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ A collection of developer tools to enhance your workflow. This package includes ```bash # Clone the repository $ git clone https://github.com/S4NKALP/DevTools.git -$ cd devtools +$ cd DevTools # Install in editable mode -$ pip install -e . +$ pipx install -e . ``` ## Configuration @@ -82,6 +82,53 @@ conventional_commits: true repositories: [] ``` +## Configuration via CLI + +You can set up all configuration options for DevTools using the CLI. This is the recommended way to configure your `~/.devtools/config.yaml` file: + +```bash +# Set OpenRouter API key (required for AI features) +devtools config set openrouter_api_key "your-openrouter-api-key" + +# Set preferred AI model (optional, default is Mixtral) +devtools config set model "mistralai/mixtral-8x7b-instruct" + +# Set temperature for AI completions (optional, default is 0.7) +devtools config set temperature 0.7 + +# Set maximum tokens for AI completions (optional, default is 150) +devtools config set max_tokens 150 + +# Set conventional commit style (optional, default is true) +devtools config set conventional_commits true + +# Set output format (optional, e.g., text or markdown) +devtools config set output_format text + +# Set repositories list (optional, usually not needed) +devtools config set repositories "[]" +``` + +To view your current configuration: + +```bash +devtools config show +``` + +To delete a config value: + +```bash +devtools config delete output_format +``` + +To clear all config: + +```bash +devtools config clear +``` + +All configuration is stored in `~/.devtools/config.yaml` and can be managed entirely through these commands. You do not need to manually edit the YAML file. + ## Usage All tools are available under the main `devtools` command: diff --git a/devtools/commitgen/cli.py b/devtools/commitgen/cli.py index 295075f..2393a64 100644 --- a/devtools/commitgen/cli.py +++ b/devtools/commitgen/cli.py @@ -1,6 +1,7 @@ """ Command-line interface for commitgen tool. """ + import click from rich.console import Console from rich.prompt import Prompt @@ -17,27 +18,47 @@ import os console = Console() + @click.group() def cli(): """Generate commit messages and changelogs using AI.""" pass + @cli.command() -@click.option('--files', '-f', multiple=True, help='Specific files to generate commit messages for') -@click.option('--repo', '-r', help='Repository path') -@click.option('--commit', '-c', is_flag=True, help='Automatically commit changes') -@click.option('--push', '-p', is_flag=True, help='Push changes after commit') -@click.option('--conventional/--no-conventional', default=True, help='Use conventional commit format') -@click.option('--no-stage', is_flag=True, help='Skip automatic staging of changes') -@click.option('--sign', is_flag=True, help='Sign commits with GPG') -@click.option('--temperature', type=float, help='AI temperature (0.0-1.0)') -def generate(files: tuple, repo: str, commit: bool, push: bool, conventional: bool, no_stage: bool, sign: bool, temperature: float): +@click.option( + "--files", + "-f", + multiple=True, + help="Specific files to generate commit messages for", +) +@click.option("--repo", "-r", help="Repository path") +@click.option("--commit", "-c", is_flag=True, help="Automatically commit changes") +@click.option("--push", "-p", is_flag=True, help="Push changes after commit") +@click.option( + "--conventional/--no-conventional", + default=True, + help="Use conventional commit format", +) +@click.option("--no-stage", is_flag=True, help="Skip automatic staging of changes") +@click.option("--sign", is_flag=True, help="Sign commits with GPG") +@click.option("--temperature", type=float, help="AI temperature (0.0-1.0)") +def generate( + files: tuple, + repo: str, + commit: bool, + push: bool, + conventional: bool, + no_stage: bool, + sign: bool, + temperature: float, +): """Generate commit messages for staged changes""" try: with Progress( SpinnerColumn(), TextColumn("[progress.description]{task.description}"), - console=console + console=console, ) as progress: # Initialize services config = Config() @@ -61,7 +82,9 @@ def generate(files: tuple, repo: str, commit: bool, push: bool, conventional: bo # Generate commit message task = progress.add_task("Generating commit message...", total=None) - commit_message = ai_service.generate_commit_message(staged_changes, temperature) + commit_message = ai_service.generate_commit_message( + staged_changes, temperature + ) progress.update(task, completed=True) # Show preview and confirm @@ -69,45 +92,57 @@ def generate(files: tuple, repo: str, commit: bool, push: bool, conventional: bo console.print(Panel(commit_message, title="Preview", border_style="blue")) if commit: - if Prompt.ask("\nApply this commit message?", choices=["y", "n"], default="y") == "y": - task = progress.add_task("Committing changes...", total=None) - git_service.commit_changes(commit_message, sign=sign) + task = progress.add_task("Committing changes...", total=None) + git_service.commit_changes(commit_message, sign=sign) + progress.update(task, completed=True) + + if push: + task = progress.add_task("Pushing changes...", total=None) + git_service.push_changes() progress.update(task, completed=True) - if push: - task = progress.add_task("Pushing changes...", total=None) - git_service.push_changes() - progress.update(task, completed=True) - - console.print("[green]Changes committed successfully![/green]") - else: - console.print("[yellow]Commit cancelled.[/yellow]") + console.print("[green]Changes committed successfully![/green]") else: - console.print("[yellow]Use --commit to apply the commit message.[/yellow]") + console.print( + "[yellow]Use --commit to apply the commit message.[/yellow]" + ) except Exception as e: console.print(f"[red]Error: {str(e)}[/red]") raise click.Abort() + @cli.group() def changelog(): """Generate and manage changelogs""" pass -@changelog.command(name='generate') -@click.option('--version', '-v', required=True, help='Version number for the changelog entry') -@click.option('--from-tag', '-t', help='Generate changelog from this tag') -@click.option('--days', '-d', type=int, help='Generate changelog from the last N days') -@click.option('--commits', '-n', type=int, help='Generate changelog from the last N commits') -@click.option('--output', '-o', help='Output file path (default: CHANGELOG.md)') -@click.option('--temperature', type=float, help='AI temperature (0.0-1.0)') -def generate_log(version: str, from_tag: str, days: int, commits: int, output: str, temperature: float): + +@changelog.command(name="generate") +@click.option( + "--version", "-v", required=True, help="Version number for the changelog entry" +) +@click.option("--from-tag", "-t", help="Generate changelog from this tag") +@click.option("--days", "-d", type=int, help="Generate changelog from the last N days") +@click.option( + "--commits", "-n", type=int, help="Generate changelog from the last N commits" +) +@click.option("--output", "-o", help="Output file path (default: CHANGELOG.md)") +@click.option("--temperature", type=float, help="AI temperature (0.0-1.0)") +def generate_log( + version: str, + from_tag: str, + days: int, + commits: int, + output: str, + temperature: float, +): """Generate a changelog from git history""" try: with Progress( SpinnerColumn(), TextColumn("[progress.description]{task.description}"), - console=console + console=console, ) as progress: # Initialize services config = Config() @@ -115,7 +150,7 @@ def generate_log(version: str, from_tag: str, days: int, commits: int, output: s changelog_gen = ChangelogGenerator(config, git_service) task = progress.add_task("Analyzing commit history...", total=None) - + # Determine which method to use for getting commits if from_tag: entries = changelog_gen.get_commits(from_tag) @@ -126,11 +161,13 @@ def generate_log(version: str, from_tag: str, days: int, commits: int, output: s else: # Default: get commits from the last 7 days entries = changelog_gen.get_commits_since_date(7) - + progress.update(task, completed=True) if not entries: - console.print("[yellow]No conventional commits found in the specified range.[/yellow]") + console.print( + "[yellow]No conventional commits found in the specified range.[/yellow]" + ) return task = progress.add_task("Generating changelog...", total=None) @@ -138,20 +175,24 @@ def generate_log(version: str, from_tag: str, days: int, commits: int, output: s changelog_gen.update_changelog_file(version, entries, output_path) progress.update(task, completed=True) - console.print(f"[green]Changelog generated successfully at {output_path}![/green]") + console.print( + f"[green]Changelog generated successfully at {output_path}![/green]" + ) except Exception as e: console.print(f"[red]Error: {str(e)}[/red]") raise click.Abort() + @cli.group() def config(): """Manage configuration""" pass + @config.command() -@click.option('--key', '-k', required=True, help='Configuration key') -@click.option('--value', '-v', required=True, help='Configuration value') +@click.option("--key", "-k", required=True, help="Configuration key") +@click.option("--value", "-v", required=True, help="Configuration value") def set(key: str, value: str): """Set configuration value""" try: @@ -162,62 +203,66 @@ def set(key: str, value: str): console.print(f"[red]Error: {str(e)}[/red]") raise click.Abort() + @config.command() def show(): """Show current configuration""" try: config = Config() - console.print(Panel( - "\n".join(f"{k}: {v}" for k, v in config.get_all().items()), - title="[blue]Current Configuration[/blue]", - border_style="blue" - )) + console.print( + Panel( + "\n".join(f"{k}: {v}" for k, v in config.get_all().items()), + title="[blue]Current Configuration[/blue]", + border_style="blue", + ) + ) except Exception as e: console.print(f"[red]Error: {str(e)}[/red]") raise click.Abort() + @cli.command() def status(): """Show the current state of the repository.""" try: # Initialize services git = GitService(os.getcwd()) - + # Get repository info repo_name = git.get_repo_name() current_branch = git.get_current_branch() - + # Get changes staged_files = git.get_staged_files() unstaged_files = git.get_unstaged_files() - + # Create status table table = Table(title=f"Repository Status: {repo_name} ({current_branch})") table.add_column("Status", style="cyan") table.add_column("Files", style="green") - + # Add staged changes if staged_files: staged_content = "\n".join(f" • {file}" for file in staged_files) table.add_row("Staged", staged_content) else: table.add_row("Staged", "No staged changes") - + # Add unstaged changes if unstaged_files: unstaged_content = "\n".join(f" • {file}" for file in unstaged_files) table.add_row("Unstaged", unstaged_content) else: table.add_row("Unstaged", "No unstaged changes") - + # Show status console.print("\n[bold]Repository Status:[/bold]") console.print(table) - + # Show diffs if there are changes if staged_files or unstaged_files: console.print("\n[bold]Changes:[/bold]") - + # Show staged diffs if staged_files: console.print("\n[cyan]Staged Changes:[/cyan]") @@ -225,7 +270,7 @@ def status(): diff = git.get_diff(file, staged=True) if diff: console.print(Syntax(diff, "diff", theme="monokai")) - + # Show unstaged diffs if unstaged_files: console.print("\n[yellow]Unstaged Changes:[/yellow]") @@ -233,15 +278,16 @@ def status(): diff = git.get_diff(file, staged=False) if diff: console.print(Syntax(diff, "diff", theme="monokai")) - + except Exception as e: console.print(f"[red]Error: {str(e)}[/red]") raise click.Abort() + # Add command aliases -cli.add_command(generate, name='g') -cli.add_command(config, name='c') -cli.add_command(changelog, name='log') +cli.add_command(generate, name="g") +cli.add_command(config, name="c") +cli.add_command(changelog, name="log") if __name__ == "__main__": - cli() \ No newline at end of file + cli()