| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- #!/usr/bin/env python3
- """
- Main FastAPI application entry point.
- """
- from contextlib import asynccontextmanager
- from pathlib import Path
- import threading
- import os
- import argparse
- from fastapi import FastAPI
- from fastapi.staticfiles import StaticFiles
- from api.v1 import router as v1_router
- from ui import router as ui_router
- from core.config import get_settings
- from core.startup import initialize_application
- from core.logging_config import setup_logging
- import ap_git
- import metadata_manager
- import build_manager
- setup_logging()
- @asynccontextmanager
- async def lifespan(app: FastAPI):
- """
- Lifespan context manager for startup and shutdown events.
- """
- # Startup
- settings = get_settings()
- initialize_application(settings.base_dir)
- repo = ap_git.GitRepo.clone_if_needed(
- source=settings.ap_git_url,
- dest=settings.source_dir,
- recurse_submodules=True,
- )
- vehicles_manager = metadata_manager.VehiclesManager()
- ap_src_metadata_fetcher = metadata_manager.APSourceMetadataFetcher(
- ap_repo=repo,
- caching_enabled=True,
- redis_host=settings.redis_host,
- redis_port=settings.redis_port,
- )
- versions_fetcher = metadata_manager.VersionsFetcher(
- remotes_json_path=settings.remotes_json_path,
- ap_repo=repo
- )
- versions_fetcher.reload_remotes_json()
- build_mgr = build_manager.BuildManager(
- outdir=settings.outdir_parent,
- redis_host=settings.redis_host,
- redis_port=settings.redis_port
- )
- cleaner = build_manager.BuildArtifactsCleaner()
- progress_updater = build_manager.BuildProgressUpdater()
- inbuilt_builder = None
- inbuilt_builder_thread = None
- if settings.enable_inbuilt_builder:
- from builder.builder import Builder # noqa: E402
- inbuilt_builder = Builder(
- workdir=settings.workdir_parent,
- source_repo=repo
- )
- inbuilt_builder_thread = threading.Thread(
- target=inbuilt_builder.run,
- daemon=True
- )
- inbuilt_builder_thread.start()
- versions_fetcher.start()
- cleaner.start()
- progress_updater.start()
- app.state.repo = repo
- app.state.ap_src_metadata_fetcher = ap_src_metadata_fetcher
- app.state.versions_fetcher = versions_fetcher
- app.state.vehicles_manager = vehicles_manager
- app.state.build_manager = build_mgr
- app.state.inbuilt_builder = inbuilt_builder
- app.state.inbuilt_builder_thread = inbuilt_builder_thread
- yield
- # Shutdown
- versions_fetcher.stop()
- cleaner.stop()
- progress_updater.stop()
- if inbuilt_builder is not None:
- inbuilt_builder.shutdown()
- if (inbuilt_builder_thread is not None and
- inbuilt_builder_thread.is_alive()):
- inbuilt_builder_thread.join()
- # Create FastAPI application
- app = FastAPI(
- title="CustomBuild API",
- description="API for ArduPilot Custom Firmware Builder",
- version="1.0.0",
- docs_url="/api/docs",
- redoc_url="/api/redoc",
- lifespan=lifespan,
- )
- # Mount static files
- WEB_ROOT = Path(__file__).resolve().parent
- app.mount(
- "/static",
- StaticFiles(directory=str(WEB_ROOT / "static")),
- name="static"
- )
- # Include API v1 router
- app.include_router(v1_router, prefix="/api")
- # Include Web UI router
- app.include_router(ui_router)
- @app.get("/health")
- async def health_check():
- """Health check endpoint."""
- return {"status": "healthy"}
- if __name__ == "__main__":
- parser = argparse.ArgumentParser(description="CustomBuild API Server")
- parser.add_argument(
- "--port",
- type=int,
- default=int(os.getenv("WEB_PORT", 8080)),
- help="Port to run the server on (default: 8080 or WEB_PORT env var)"
- )
- args = parser.parse_args()
- import uvicorn
- uvicorn.run(
- "main:app",
- host="0.0.0.0",
- port=args.port,
- reload=True
- )
|