feat: add CLI and generator scripts to orchestrate project setup
This commit is contained in:
2 files changed
+194
No files matched your search
+111
@@ -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
|
||||
@@ -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()
|
||||
Reference in new issue
Block a user