|
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")
|
|
|
|
|
|
app.mount("/static", StaticFiles(directory="app/static"), name="static")
|
|
app.add_middleware(GZipMiddleware)
|
|
templates = Jinja2Templates(directory="app/templates")
|
|
|
|
|
|
|
|
@app.get("/", response_class=HTMLResponse)
|
|
async def index(request: Request):
|
|
return templates.TemplateResponse("index.html", {"request": request})
|
|
|
|
|
|
@app.post("/web/deploy")
|
|
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()
|
|
):
|
|
|
|
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)
|
|
|
|
|
|
return RedirectResponse(url=f"/deploy/{task_id}", status_code=303)
|
|
|
|
|
|
@app.get("/deploy/{task_id}", response_class=HTMLResponse)
|
|
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
|
|
})
|
|
|
|
|
|
|
|
@app.post("/deploy", response_model=DeployStatus, status_code=202)
|
|
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)
|
|
|
|
|
|
@app.get("/deploy/status/{task_id}", response_model=DeployStatus)
|
|
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)}))
|
|
|