Initial upload: git-insights-cli with CI/CD workflow
This commit is contained in:
227
src/cli.py
Normal file
227
src/cli.py
Normal file
@@ -0,0 +1,227 @@
|
||||
from typing import Optional
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
import click
|
||||
from rich.console import Console
|
||||
|
||||
from src.git_insights import GitInsights
|
||||
from src.utils.config import load_config
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
@click.group()
|
||||
@click.option(
|
||||
"--repo-path",
|
||||
"-p",
|
||||
default=".",
|
||||
help="Path to git repository",
|
||||
)
|
||||
@click.option(
|
||||
"--days",
|
||||
"-d",
|
||||
default=30,
|
||||
type=int,
|
||||
help="Number of days to analyze",
|
||||
)
|
||||
@click.option(
|
||||
"--config",
|
||||
"-c",
|
||||
default=None,
|
||||
type=str,
|
||||
help="Path to config file",
|
||||
)
|
||||
@click.pass_context
|
||||
def main(
|
||||
ctx: click.Context,
|
||||
repo_path: str,
|
||||
days: int,
|
||||
config: Optional[str],
|
||||
) -> None:
|
||||
"""Git Insights CLI - Analyze git repositories for productivity insights."""
|
||||
ctx.ensure_object(dict)
|
||||
ctx.obj["repo_path"] = repo_path
|
||||
ctx.obj["days"] = days
|
||||
ctx.obj["config"] = config
|
||||
|
||||
|
||||
@main.command()
|
||||
@click.option(
|
||||
"--format",
|
||||
"-f",
|
||||
type=click.Choice(["json", "markdown", "html", "console"]),
|
||||
default="console",
|
||||
help="Output format",
|
||||
)
|
||||
@click.pass_context
|
||||
def analyze(ctx: click.Context, format: str) -> None:
|
||||
"""Analyze repository for commit patterns, code churn, and productivity metrics."""
|
||||
repo_path = ctx.obj["repo_path"]
|
||||
days = ctx.obj["days"]
|
||||
config_path = ctx.obj["config"]
|
||||
|
||||
config = load_config(config_path) if config_path else None
|
||||
|
||||
if not os.path.isdir(repo_path):
|
||||
console.print(f"[red]Error: Directory not found: {repo_path}[/red]")
|
||||
return
|
||||
|
||||
try:
|
||||
insights = GitInsights(
|
||||
repo_path=repo_path,
|
||||
days=days,
|
||||
config=config,
|
||||
)
|
||||
|
||||
results = insights.analyze()
|
||||
|
||||
if format == "json":
|
||||
from src.formatters import JSONFormatter
|
||||
console.print(JSONFormatter.format(results))
|
||||
elif format == "markdown":
|
||||
from src.formatters import MarkdownFormatter
|
||||
console.print(MarkdownFormatter.format(results))
|
||||
elif format == "html":
|
||||
from src.formatters import HTMLFormatter
|
||||
console.print(HTMLFormatter.format(results))
|
||||
else:
|
||||
from src.formatters import DashboardFormatter
|
||||
DashboardFormatter.display(results)
|
||||
|
||||
except Exception as e:
|
||||
console.print(f"[red]Error: {e}[/red]")
|
||||
raise
|
||||
|
||||
|
||||
@main.command()
|
||||
@click.pass_context
|
||||
def dashboard(ctx: click.Context) -> None:
|
||||
"""Display productivity metrics in an interactive dashboard."""
|
||||
repo_path = ctx.obj["repo_path"]
|
||||
days = ctx.obj["days"]
|
||||
config_path = ctx.obj["config"]
|
||||
|
||||
config = load_config(config_path) if config_path else None
|
||||
|
||||
if not os.path.isdir(repo_path):
|
||||
console.print(f"[red]Error: Directory not found: {repo_path}[/red]")
|
||||
return
|
||||
|
||||
try:
|
||||
insights = GitInsights(
|
||||
repo_path=repo_path,
|
||||
days=days,
|
||||
config=config,
|
||||
)
|
||||
|
||||
results = insights.analyze()
|
||||
from src.formatters import DashboardFormatter
|
||||
DashboardFormatter.display(results)
|
||||
|
||||
except Exception as e:
|
||||
console.print(f"[red]Error: {e}[/red]")
|
||||
raise
|
||||
|
||||
|
||||
@main.command()
|
||||
@click.option(
|
||||
"--format",
|
||||
"-f",
|
||||
type=click.Choice(["json", "markdown", "html"]),
|
||||
default="json",
|
||||
help="Output format",
|
||||
)
|
||||
@click.option(
|
||||
"--output",
|
||||
"-o",
|
||||
default=None,
|
||||
type=str,
|
||||
help="Output file path",
|
||||
)
|
||||
@click.pass_context
|
||||
def export(ctx: click.Context, format: str, output: Optional[str]) -> None:
|
||||
"""Export analysis results to a file."""
|
||||
repo_path = ctx.obj["repo_path"]
|
||||
days = ctx.obj["days"]
|
||||
config_path = ctx.obj["config"]
|
||||
|
||||
config = load_config(config_path) if config_path else None
|
||||
|
||||
if not os.path.isdir(repo_path):
|
||||
console.print(f"[red]Error: Directory not found: {repo_path}[/red]")
|
||||
return
|
||||
|
||||
try:
|
||||
insights = GitInsights(
|
||||
repo_path=repo_path,
|
||||
days=days,
|
||||
config=config,
|
||||
)
|
||||
|
||||
results = insights.analyze()
|
||||
|
||||
if format == "json":
|
||||
from src.formatters import JSONFormatter
|
||||
output_str = JSONFormatter.format(results)
|
||||
elif format == "markdown":
|
||||
from src.formatters import MarkdownFormatter
|
||||
output_str = MarkdownFormatter.format(results)
|
||||
else:
|
||||
from src.formatters import HTMLFormatter
|
||||
output_str = HTMLFormatter.format(results)
|
||||
|
||||
if output:
|
||||
with open(output, "w") as f:
|
||||
f.write(output_str)
|
||||
console.print(f"[green]Exported to {output}[/green]")
|
||||
else:
|
||||
console.print(output_str)
|
||||
|
||||
except Exception as e:
|
||||
console.print(f"[red]Error: {e}[/red]")
|
||||
raise
|
||||
|
||||
|
||||
@main.command()
|
||||
@click.option(
|
||||
"--output",
|
||||
"-o",
|
||||
default=None,
|
||||
type=str,
|
||||
help="Output file path",
|
||||
)
|
||||
@click.pass_context
|
||||
def report(ctx: click.Context, output: Optional[str]) -> None:
|
||||
"""Generate a comprehensive productivity report."""
|
||||
repo_path = ctx.obj["repo_path"]
|
||||
days = ctx.obj["days"]
|
||||
config_path = ctx.obj["config"]
|
||||
|
||||
config = load_config(config_path) if config_path else None
|
||||
|
||||
if not os.path.isdir(repo_path):
|
||||
console.print(f"[red]Error: Directory not found: {repo_path}[/red]")
|
||||
return
|
||||
|
||||
try:
|
||||
insights = GitInsights(
|
||||
repo_path=repo_path,
|
||||
days=days,
|
||||
config=config,
|
||||
)
|
||||
|
||||
results = insights.analyze()
|
||||
from src.formatters import HTMLFormatter
|
||||
report_str = HTMLFormatter.format(results)
|
||||
|
||||
if output:
|
||||
with open(output, "w") as f:
|
||||
f.write(report_str)
|
||||
console.print(f"[green]Report generated: {output}[/green]")
|
||||
else:
|
||||
console.print(report_str)
|
||||
|
||||
except Exception as e:
|
||||
console.print(f"[red]Error: {e}[/red]")
|
||||
raise
|
||||
Reference in New Issue
Block a user