feat: add CLI and generator scripts to orchestrate project setup

This commit is contained in:
sankalp committed 2025-10-28 22:58:37 +05:45
1 parent 172cfd2a22
commit 15929d9ca5
2 files changed
+194

No files matched your search

+111
View File
@@ -0,0 +1,111 @@
"""
Main CLI orchestrator for djinit.
Coordinates between different managers to create a complete Django project.
"""
import os
from typing import Callable, List, Tuple
from src.scripts.cicd_config_generator import CICDConfigGenerator
from src.scripts.console_ui import UIFormatter
from src.scripts.deployment_files_generator import DeploymentConfigGenerator
from src.scripts.secretkey_generator import generate_secret_command
from src.templates.files import FileManager
from src.templates.project import ProjectManager
from src.templates.settings import SettingsManager
class Cli:
def __init__(self, project_dir: str, project_name: str, primary_app: str, app_names: list, metadata: dict):
self.project_dir = project_dir
self.project_name = project_name
self.primary_app = primary_app
self.app_names = app_names
self.metadata = metadata
self.project_root = os.path.join(os.getcwd(), project_dir)
# Initialize managers
self.project_manager = ProjectManager(project_dir, project_name, app_names)
self.settings_manager = SettingsManager(self.project_root, project_name, app_names)
self.file_manager = FileManager(self.project_root, project_name, app_names)
self.deployment_manager = DeploymentConfigGenerator(self.project_root, project_name)
self.cicd_manager = CICDConfigGenerator(self.project_root, project_name)
def run_setup(self) -> bool:
steps: List[Tuple[str, Callable[[], bool]]] = [
("Creating Django project", self.project_manager.create_project),
("Creating Django apps", self.project_manager.create_apps),
("Validating project structure", self.project_manager.validate_project_structure),
("Setting up project structure", self.settings_manager.create_settings_structure),
("Configuring base settings", self.settings_manager.update_base_settings),
("Configuring development settings", self.settings_manager.update_development_settings),
("Configuring production settings", self.settings_manager.update_production_settings),
("Creating utility files", self._create_utility_files),
("Setting up app URLs", self.file_manager.create_app_urls),
("Configuring comprehensive URLs", self.file_manager.update_project_urls),
("Updating WSGI configuration", self.file_manager.update_wsgi_file),
("Updating ASGI configuration", self.file_manager.update_asgi_file),
("Updating manage.py", self.file_manager.update_manage_py),
("Creating Justfile", self.deployment_manager.create_justfile),
("Creating Procfile", self.deployment_manager.create_procfile),
("Creating runtime.txt", lambda: self.deployment_manager.create_runtime_txt("3.13")),
("Creating CI/CD pipelines", self._create_cicd_pipelines),
]
total_steps = len(steps)
success = True
# Create live progress display
progress, task = UIFormatter.create_live_progress(description="Setup Progress", total_steps=total_steps)
with progress:
# Execute each step with progress tracking
for step_number, (description, step_func) in enumerate(steps, 1):
result = step_func()
if not result:
success = False
UIFormatter.print_error(f"Step {step_number} failed: {description}")
break
# Update the same progress bar
progress.update(task, advance=1, description=f"Step {step_number}/{total_steps}")
return success
def _create_utility_files(self) -> bool:
utility_steps = [
self.file_manager.create_gitignore,
self.file_manager.create_requirements,
self.file_manager.create_readme,
self.file_manager.create_env_file,
lambda: self.file_manager.create_pyproject_toml(self.metadata),
]
for step_func in utility_steps:
result = step_func()
if not result:
return False
UIFormatter.print_success("Created all utility files successfully!")
return True
def _create_cicd_pipelines(self) -> bool:
if self.metadata.get("use_github_actions", True):
result = self.cicd_manager.create_github_actions()
if not result:
return False
if self.metadata.get("use_gitlab_ci", True):
result = self.cicd_manager.create_gitlab_ci()
if not result:
return False
return True
def generate_secret_keys(self) -> bool:
try:
generate_secret_command()
return True
except Exception as e:
UIFormatter.print_error(f"Failed to generate secret keys: {e}")
return False
+83
View File
@@ -0,0 +1,83 @@
"""
Main script entry point for djinit.
Handles user input validation and orchestrates the setup process.
"""
import os
import subprocess
import sys
from src.cli import Cli
from src.scripts.command_handler import handle_app_command, handle_secret_command, parse_arguments
from src.scripts.console_ui import UIFormatter, console
from src.scripts.input_handler import confirm_setup, get_user_input
def clear_screen() -> None:
try:
if os.name == "nt":
subprocess.run("cls", shell=True, check=True) # Windows
else:
subprocess.run("clear", shell=True, check=True) # Linux/MacOS
except subprocess.CalledProcessError:
# If clearing fails, just print some newlines
console.print("\n" * 50)
def main() -> None:
try:
# Parse command line arguments
args = parse_arguments()
# Handle secret command
if args.command == "secret":
handle_secret_command(args)
return
# Handle app command
if args.command == "app":
handle_app_command(args)
return
# Default to setup command
# Clear screen
clear_screen()
# Display welcome screen
console.print()
console.print(UIFormatter.create_welcome_panel())
console.print()
# Get user input
project_dir, project_name, primary_app, app_names, metadata = get_user_input()
# Confirm setup
if not confirm_setup(project_dir, project_name, app_names, metadata):
UIFormatter.print_info("Setup cancelled by user.")
return
# Run setup
console.print()
UIFormatter.print_info("Starting Django project setup...")
console.print()
django_cli = Cli(project_dir, project_name, primary_app, app_names, metadata)
success = django_cli.run_setup()
# Display completion summary
UIFormatter.create_summary_panel(project_dir, project_name, app_names, True)
# Exit with appropriate code
sys.exit(0 if success else 1)
except KeyboardInterrupt:
UIFormatter.print_info("\nSetup cancelled by user.")
sys.exit(0)
except Exception as e:
UIFormatter.print_error(f"Unexpected error: {str(e)}")
console.print("[dim]Please check your environment and try again.[/dim]")
sys.exit(1)
if __name__ == "__main__":
main()