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

1"""Command-line interface for qCradle.""" 

2 

3import sys 

4 

5import typer 

6from rich import print as rprint 

7from rich.console import Console 

8from rich.table import Table 

9 

10from .config import get_all_templates 

11 

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) 

18 

19# Initialize Rich console 

20console = Console() 

21 

22 

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()) 

28 

29 if not template_names: 

30 rprint("[bold red]No templates found![/bold red]") 

31 return 

32 

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") 

37 

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) 

43 

44 console.print(table) 

45 

46 

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()) 

65 

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) 

70 

71 # Get template information from config 

72 template_info = template_configs.get(template, None) 

73 

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) 

77 

78 template_url = template_info["url"] 

79 

80 output_dir = project_name 

81 

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 } 

89 

90 # Import copier here to avoid slow startup time 

91 import copier 

92 

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]") 

97 

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 ) 

106 

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 """) 

120 

121 except Exception as e: 

122 rprint(f"[bold red]Error creating project: {e}[/bold red]") 

123 sys.exit(1) 

124 

125 

126@app.callback() 

127def callback(): 

128 """Cradle CLI - A command-line interface for generating projects using Copier templates. 

129 

130 Templates are defined in a configuration file (~/.cradle/config.yaml) that maps 

131 template names to repository URLs. 

132 """ 

133 pass 

134 

135 

136def main(): 

137 """Entry point for the CLI.""" 

138 app() # pragma: no cover