Coverage for src/jtech_installer/cli/main_clean.py: 0%

157 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-08-20 15:10 -0300

1#!/usr/bin/env python3 

2""" 

3🚀 JTECH™ Core Installer - CLI Principal 

4Instalador automatizado para configurar ambiente JTECH™ Core 

5""" 

6 

7import shutil 

8import sys 

9import time 

10from pathlib import Path 

11 

12import click 

13from rich.console import Console 

14from rich.panel import Panel 

15from rich.progress import Progress, SpinnerColumn, TextColumn 

16from rich.table import Table 

17 

18console = Console() 

19 

20 

21@click.group(invoke_without_command=True) 

22@click.option("--help", "-h", is_flag=True, help="Mostrar ajuda") 

23@click.option("--version", "-v", is_flag=True, help="Mostrar versão") 

24@click.option( 

25 "--team", 

26 "-t", 

27 type=click.Choice(["ide-minimal", "fullstack", "no-ui", "all"]), 

28 default="fullstack", 

29 help="Tipo de equipe/configuração", 

30) 

31@click.option("--force", "-f", is_flag=True, help="Forçar reinstalação") 

32@click.option( 

33 "--validate-only", is_flag=True, help="Apenas validar instalação existente" 

34) 

35@click.pass_context 

36def cli(ctx, help, version, team, force, validate_only): 

37 """ 

38 🚀 JTECH™ Core Installer 

39 

40 Instala e configura automaticamente o ambiente JTECH™ Core 

41 no projeto atual. 

42 

43 Exemplos: 

44 jtech-installer # Instala com configuração fullstack 

45 jtech-installer --team ide-minimal # Instala configuração mínima 

46 jtech-installer --validate-only # Apenas valida instalação 

47 jtech-installer --help # Mostra esta ajuda 

48 """ 

49 

50 if version: 

51 console.print("🚀 JTECH™ Core Installer v0.1.0", style="bold blue") 

52 return 

53 

54 if help or ctx.invoked_subcommand is not None: 

55 if help: 

56 console.print(ctx.get_help()) 

57 return 

58 

59 # Comando principal - instalar 

60 project_path = Path.cwd() 

61 

62 console.print( 

63 Panel.fit( 

64 f"[bold blue]🚀 JTECH™ Core Installer[/bold blue]\n" 

65 f"📁 Projeto: [cyan]{project_path}[/cyan]\n" 

66 f"⚙️ Tipo de equipe: [green]{team}[/green]", 

67 title="🔧 Configuração", 

68 border_style="blue", 

69 ) 

70 ) 

71 

72 if validate_only: 

73 return validate_installation(project_path, team) 

74 

75 return install_jtech_core(project_path, team, force) 

76 

77 

78def install_jtech_core( 

79 project_path: Path, team_type: str, force: bool = False 

80): 

81 """Executa a instalação completa do JTECH™ Core.""" 

82 

83 # Verificar se já existe instalação 

84 jtech_core = project_path / ".jtech-core" 

85 if jtech_core.exists() and not force: 

86 console.print("⚠️ Instalação JTECH™ Core já existe!", style="yellow") 

87 console.print("💡 Use --force para reinstalar", style="dim") 

88 

89 if not click.confirm("Deseja continuar e atualizar a instalação?"): 

90 console.print("❌ Instalação cancelada", style="red") 

91 return False 

92 

93 # Executar instalação com progress 

94 with Progress( 

95 SpinnerColumn(), 

96 TextColumn("[progress.description]{task.description}"), 

97 console=console, 

98 ) as progress: 

99 

100 task = progress.add_task("🏗️ Iniciando instalação...", total=None) 

101 

102 try: 

103 # Passo 1: Copiar estrutura .jtech-core completa 

104 progress.update(task, description="📦 Copiando framework...") 

105 copy_jtech_core_structure(project_path, force) 

106 time.sleep(0.5) 

107 

108 # Passo 2: Copiar chatmodes 

109 progress.update(task, description="💬 Configurando chatmodes...") 

110 copy_chatmodes(project_path) 

111 time.sleep(0.5) 

112 

113 # Passo 3: Configurar VS Code 

114 progress.update(task, description="🔧 Configurando VS Code...") 

115 copy_vscode_config(project_path) 

116 time.sleep(0.5) 

117 

118 # Passo 4: Finalizar 

119 progress.update(task, description="🔍 Finalizando...") 

120 time.sleep(0.5) 

121 

122 progress.remove_task(task) 

123 

124 except Exception as e: 

125 progress.remove_task(task) 

126 console.print(f"❌ Erro durante instalação: {e}", style="red") 

127 return False 

128 

129 # Mostrar resultado 

130 show_installation_result(True, project_path) 

131 return True 

132 

133 

134def copy_jtech_core_structure(project_path: Path, force: bool = False): 

135 """Copia toda a estrutura .jtech-core dos assets empacotados.""" 

136 assets_dir = Path(__file__).parent.parent / "assets" 

137 source_jtech = assets_dir / ".jtech-core" 

138 target_jtech = project_path / ".jtech-core" 

139 

140 if not source_jtech.exists(): 

141 console.print( 

142 "⚠️ Estrutura .jtech-core não encontrada nos assets", style="yellow" 

143 ) 

144 return 

145 

146 # Copiar toda a estrutura 

147 if target_jtech.exists() and force: 

148 shutil.rmtree(target_jtech) 

149 

150 if not target_jtech.exists(): 

151 shutil.copytree(source_jtech, target_jtech) 

152 console.print( 

153 "✅ Estrutura .jtech-core copiada dos assets", style="green" 

154 ) 

155 else: 

156 console.print("✅ Estrutura .jtech-core já existe", style="green") 

157 

158 

159def copy_chatmodes(project_path: Path): 

160 """Copia os chatmodes dos assets empacotados.""" 

161 assets_dir = Path(__file__).parent.parent / "assets" 

162 source_chatmodes = assets_dir / ".github" / "chatmodes" 

163 target_chatmodes = project_path / ".github" / "chatmodes" 

164 

165 if not source_chatmodes.exists(): 

166 console.print("⚠️ Chatmodes não encontrados nos assets", style="yellow") 

167 return 

168 

169 # Criar diretório target 

170 target_chatmodes.mkdir(parents=True, exist_ok=True) 

171 

172 # Copiar todos os arquivos .chatmode.md 

173 copied_files = [] 

174 

175 for chatmode_file in source_chatmodes.glob("*.chatmode.md"): 

176 target_file = target_chatmodes / chatmode_file.name 

177 shutil.copy2(chatmode_file, target_file) 

178 copied_files.append(chatmode_file.name) 

179 

180 console.print( 

181 f"✅ Copiados {len(copied_files)} chatmodes dos assets", style="green" 

182 ) 

183 

184 

185def copy_vscode_config(project_path: Path): 

186 """Copia a configuração do VS Code dos assets empacotados.""" 

187 assets_dir = Path(__file__).parent.parent / "assets" 

188 source_vscode = assets_dir / ".vscode" / "settings.json" 

189 target_vscode_dir = project_path / ".vscode" 

190 target_vscode_file = target_vscode_dir / "settings.json" 

191 

192 if not source_vscode.exists(): 

193 console.print( 

194 "⚠️ Configuração VS Code não encontrada nos assets", style="yellow" 

195 ) 

196 return 

197 

198 # Criar diretório target 

199 target_vscode_dir.mkdir(parents=True, exist_ok=True) 

200 

201 # Copiar configuração 

202 shutil.copy2(source_vscode, target_vscode_file) 

203 

204 console.print("✅ Configuração VS Code copiada dos assets", style="green") 

205 

206 

207def validate_installation(project_path: Path, team_type: str): 

208 """Valida uma instalação existente.""" 

209 console.print("🔍 Validando instalação JTECH™ Core...", style="blue") 

210 

211 # Verificar se existe instalação 

212 jtech_core = project_path / ".jtech-core" 

213 if not jtech_core.exists(): 

214 console.print( 

215 "❌ Nenhuma instalação JTECH™ Core encontrada", style="red" 

216 ) 

217 console.print( 

218 "💡 Execute 'jtech-installer' para instalar", style="dim" 

219 ) 

220 return False 

221 

222 # Verificar componentes principais 

223 components = [ 

224 (".jtech-core", "Estrutura principal"), 

225 (".jtech-core/agents", "Agentes"), 

226 (".jtech-core/tasks", "Tarefas"), 

227 (".jtech-core/templates", "Templates"), 

228 (".github/chatmodes", "ChatModes"), 

229 (".vscode/settings.json", "Configuração VS Code"), 

230 ] 

231 

232 # Tabela de resultados 

233 table = Table(title="🔍 Resultado da Validação") 

234 table.add_column("Componente", style="cyan") 

235 table.add_column("Status", style="white") 

236 

237 all_valid = True 

238 

239 for component_path, component_name in components: 

240 full_path = project_path / component_path 

241 if full_path.exists(): 

242 status = "✅ OK" 

243 else: 

244 status = "❌ FALTA" 

245 all_valid = False 

246 

247 table.add_row(component_name, status) 

248 

249 console.print(table) 

250 

251 # Resultado geral 

252 if all_valid: 

253 console.print("\n🎉 [bold green]Instalação válida![/bold green]") 

254 else: 

255 console.print( 

256 "\n⚠️ [bold yellow]Alguns componentes estão faltando[/bold yellow]" 

257 ) 

258 

259 return all_valid 

260 

261 

262def show_installation_result(success: bool, project_path: Path): 

263 """Mostra o resultado da instalação.""" 

264 

265 if success: 

266 console.print( 

267 Panel.fit( 

268 "[bold green]🎉 INSTALAÇÃO CONCLUÍDA COM SUCESSO![/bold green]\n\n" 

269 f"📁 Projeto: [cyan]{project_path}[/cyan]\n" 

270 f"🔧 Estrutura: [green].jtech-core/[/green] criada\n" 

271 f"💬 ChatModes: [green].github/chatmodes/[/green] configurados\n" 

272 f"⚙️ VS Code: [green].vscode/settings.json[/green] configurado", 

273 title="✅ Sucesso", 

274 border_style="green", 

275 ) 

276 ) 

277 

278 # Mostrar próximos passos 

279 next_steps = Table(title="📋 Próximos Passos") 

280 next_steps.add_column("Comando", style="cyan") 

281 next_steps.add_column("Descrição", style="white") 

282 

283 next_steps.add_row("code .", "Abrir projeto no VS Code") 

284 next_steps.add_row( 

285 "jtech-installer --validate-only", "Validar instalação" 

286 ) 

287 next_steps.add_row("ls .jtech-core/", "Explorar estrutura criada") 

288 

289 console.print(next_steps) 

290 

291 else: 

292 console.print( 

293 Panel.fit( 

294 "[bold yellow]⚠️ INSTALAÇÃO COM PROBLEMAS[/bold yellow]\n\n" 

295 f"📁 Projeto: [cyan]{project_path}[/cyan]\n" 

296 f"🔍 Verifique os logs acima", 

297 title="⚠️ Atenção", 

298 border_style="yellow", 

299 ) 

300 ) 

301 

302 

303@cli.command() 

304def validate(): 

305 """Valida a instalação JTECH™ Core no diretório atual.""" 

306 project_path = Path.cwd() 

307 return validate_installation(project_path, "fullstack") 

308 

309 

310@cli.command() 

311@click.option( 

312 "--team", 

313 "-t", 

314 type=click.Choice(["ide-minimal", "fullstack", "no-ui", "all"]), 

315 default="fullstack", 

316) 

317def install(team): 

318 """Instala JTECH™ Core no diretório atual.""" 

319 project_path = Path.cwd() 

320 return install_jtech_core(project_path, team, force=False) 

321 

322 

323@cli.command() 

324@click.option( 

325 "--team", 

326 "-t", 

327 type=click.Choice(["ide-minimal", "fullstack", "no-ui", "all"]), 

328 default="fullstack", 

329) 

330def reinstall(team): 

331 """Reinstala JTECH™ Core (força reinstalação).""" 

332 project_path = Path.cwd() 

333 return install_jtech_core(project_path, team, force=True) 

334 

335 

336def main(): 

337 """Ponto de entrada principal.""" 

338 try: 

339 cli() 

340 except KeyboardInterrupt: 

341 console.print("\n❌ Operação cancelada pelo usuário", style="red") 

342 sys.exit(1) 

343 except Exception as e: 

344 console.print(f"\n❌ Erro inesperado: {e}", style="red") 

345 sys.exit(1) 

346 

347 

348if __name__ == "__main__": 

349 main()