Coverage for src/cradle/cli.py: 100%
57 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-16 05:53 +0000
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-16 05:53 +0000
1"""Command-line interface for qCradle."""
3import sys
5import typer
6from rich import print as rprint
7from rich.console import Console
8from rich.table import Table
10from .config import get_all_templates
12# Initialize Typer app
13app = typer.Typer(
14 name="qCradle",
15 help="CLI tool for generating projects using Copier templates from configured repositories",
16 add_completion=False,
17)
19# Initialize Rich console
20console = Console()
23@app.command("list")
24def list_templates():
25 """List all available templates."""
26 template_configs = get_all_templates()
27 template_names = sorted(template_configs.keys())
29 if not template_names:
30 rprint("[bold red]No templates found![/bold red]")
31 return
33 table = Table(title="Available Templates")
34 table.add_column("Name", style="cyan")
35 table.add_column("Description", style="green")
36 table.add_column("URL", style="blue")
38 for name in template_names:
39 template_info = template_configs[name]
40 description = template_info.get("description", "No description available")
41 url = template_info.get("url", "")
42 table.add_row(name, description, url)
44 console.print(table)
47@app.command("create")
48def create_project(
49 template: str = typer.Argument(..., help="Template to use"),
50 project_name: str = typer.Option(..., "--name", "-n", help="Name of the project"),
51 description: str = typer.Option(
52 "A project created with Cradle CLI", "--description", "-d", help="Project description"
53 ),
54 user_name: str = typer.Option(..., "--username", "-u", help="GitHub username for repository URL"),
55 visibility: str = typer.Option(
56 "private",
57 "--visibility",
58 "-v",
59 help="Visibility of the GitHub repository: private, public, or internal",
60 ),
61):
62 """Create a new project from a template."""
63 template_configs = get_all_templates()
64 available_templates = sorted(template_configs.keys())
66 if template not in available_templates:
67 rprint(f"[bold red]Template '{template}' not found![/bold red]")
68 rprint(f"Available templates: {', '.join(available_templates)}")
69 sys.exit(1)
71 # Get template information from config
72 template_info = template_configs.get(template, None)
74 if not template_info or "url" not in template_info:
75 rprint(f"[bold red]Template '{template}' has no URL defined![/bold red]")
76 sys.exit(1)
78 template_url = template_info["url"]
80 output_dir = project_name
82 # Prepare data for copier
83 data = {
84 "project_name": project_name,
85 "description": description,
86 "username": user_name,
87 "repository": f"https://github.com/{user_name}/{project_name}",
88 }
90 # Import copier here to avoid slow startup time
91 import copier
93 try:
94 rprint(f"[bold]Creating project '{project_name}' from template '{template}'...[/bold]")
95 rprint(f"[bold]Using template URL: {template_url}[/bold]")
96 rprint(f"[bold green]Copying template to '{output_dir}'...[/bold green]")
98 # Run copier with the template URL
99 copier.run_copy(
100 src_path=template_url,
101 dst_path=output_dir,
102 data=data,
103 unsafe=True,
104 defaults=True,
105 )
107 rprint(f"[bold green]Project created successfully at '{output_dir}'![/bold green]")
108 rprint("To create the project on GitHub, run the following commands in your terminal:")
109 rprint("")
110 rprint(f"""
111 gh repo create --{visibility} {user_name}/{project_name} --description '{description}'
112 cd {output_dir}
113 git init
114 git add .
115 git commit -m "first commit"
116 git branch -M main
117 git remote add origin git@github.com:{user_name}/{project_name}.git
118 git push -u origin main
119 """)
121 except Exception as e:
122 rprint(f"[bold red]Error creating project: {e}[/bold red]")
123 sys.exit(1)
126@app.callback()
127def callback():
128 """Cradle CLI - A command-line interface for generating projects using Copier templates.
130 Templates are defined in a configuration file (~/.cradle/config.yaml) that maps
131 template names to repository URLs.
132 """
133 pass
136def main():
137 """Entry point for the CLI."""
138 app() # pragma: no cover