Spaces:
Paused
Paused
| from fastapi import BackgroundTasks, FastAPI, HTTPException, Depends, Request, Form | |
| from fastapi.responses import HTMLResponse, RedirectResponse | |
| from fastapi.staticfiles import StaticFiles | |
| from fastapi.templating import Jinja2Templates | |
| from fastapi.middleware.gzip import GZipMiddleware | |
| import uuid | |
| from app.models import DeployRequest, DeployStatus | |
| from app.store import TaskStore | |
| from app.deploy import deploy_space, SpaceDeployError | |
| from app.auth import require_api_key | |
| app = FastAPI(title="HF Space Deployer", version="1.0.0") | |
| # Static files and templates | |
| app.mount("/static", StaticFiles(directory="app/static"), name="static") | |
| app.add_middleware(GZipMiddleware) | |
| templates = Jinja2Templates(directory="app/templates") | |
| # Web Interface Routes | |
| async def index(request: Request): | |
| return templates.TemplateResponse("index.html", {"request": request}) | |
| async def web_deploy( | |
| request: Request, | |
| hf_token: str = Form(...), | |
| git_repo_url: str = Form(...), | |
| space_name: str = Form(...), | |
| description: str = Form(""), | |
| space_port: int = Form(7860), | |
| private: bool = Form(False), | |
| env_vars_text: str = Form(""), | |
| deploy_path: str = Form("/"), | |
| bg: BackgroundTasks = BackgroundTasks() | |
| ): | |
| # Parse environment variables from textarea | |
| env_vars = {} | |
| if env_vars_text.strip(): | |
| for line in env_vars_text.strip().split('\n'): | |
| if '=' in line: | |
| key, value = line.split('=', 1) | |
| env_vars[key.strip()] = value.strip() | |
| deploy_req = DeployRequest( | |
| hf_token=hf_token, | |
| git_repo_url=git_repo_url, | |
| space_name=space_name, | |
| description=description, | |
| space_port=space_port, | |
| private=private, | |
| env_vars=env_vars, | |
| deploy_path=deploy_path | |
| ) | |
| task_id = str(uuid.uuid4()) | |
| TaskStore.save(DeployStatus(task_id=task_id, status="PENDING")) | |
| bg.add_task(_run_task, task_id, deploy_req) | |
| # Redirect to status page instead of returning HTML | |
| return RedirectResponse(url=f"/deploy/{task_id}", status_code=303) | |
| async def deploy_status_page(request: Request, task_id: str): | |
| status = TaskStore.load(task_id) | |
| if not status: | |
| raise HTTPException(status_code=404, detail="Task not found") | |
| return templates.TemplateResponse("deploy_status.html", { | |
| "request": request, | |
| "task_id": task_id, | |
| "status": status.status | |
| }) | |
| # API Routes | |
| async def deploy(req: DeployRequest, bg: BackgroundTasks): | |
| task_id = str(uuid.uuid4()) | |
| TaskStore.save(DeployStatus(task_id=task_id, status="PENDING")) | |
| bg.add_task(_run_task, task_id, req) | |
| return TaskStore.load(task_id) | |
| async def status(task_id: str): | |
| status = TaskStore.load(task_id) | |
| if not status: | |
| raise HTTPException(status_code=404, detail="Task not found") | |
| return status | |
| # ------------------------------------------------------------------ # | |
| def _run_task(task_id: str, req: DeployRequest): | |
| TaskStore.save(DeployStatus(task_id=task_id, status="IN_PROGRESS")) | |
| try: | |
| url = deploy_space(**req.dict()) | |
| TaskStore.save(DeployStatus(task_id=task_id, status="SUCCESS", detail={"space_url": url})) | |
| except SpaceDeployError as exc: | |
| TaskStore.save(DeployStatus(task_id=task_id, status="FAILED", detail={"error": str(exc)})) | |