Initial commit: iOS Build Server
- FastAPI backend with build queue, WebSocket logs, task management - Vue 3 frontend with build/config/history views - Xcode project build automation with IPA export - Fix: initialize build_dir before try block to ensure cleanup on early failure
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
"""FastAPI 主入口"""
|
||||
from contextlib import asynccontextmanager
|
||||
from pathlib import Path
|
||||
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Request
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.responses import FileResponse
|
||||
|
||||
from .database import init_db
|
||||
from .routers import config, apps, tasks, auth
|
||||
from .services.log_streamer import log_streamer
|
||||
from .config import BACKEND_PORT
|
||||
|
||||
STATIC_DIR = Path(__file__).parent / "static"
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
"""应用生命周期"""
|
||||
init_db()
|
||||
yield
|
||||
|
||||
|
||||
app = FastAPI(
|
||||
title="iOS 自动打包服务",
|
||||
version="1.0.0",
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
# CORS
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# 路由
|
||||
app.include_router(auth.router)
|
||||
app.include_router(config.router)
|
||||
app.include_router(apps.router)
|
||||
app.include_router(tasks.router)
|
||||
|
||||
|
||||
@app.websocket("/ws/tasks/{task_id}")
|
||||
async def websocket_logs(websocket: WebSocket, task_id: str):
|
||||
"""WebSocket 实时日志"""
|
||||
await websocket.accept()
|
||||
try:
|
||||
async for msg in log_streamer.subscribe(task_id):
|
||||
await websocket.send_json(msg)
|
||||
except WebSocketDisconnect:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@app.get("/api/health")
|
||||
async def health():
|
||||
"""健康检查"""
|
||||
return {"status": "ok", "port": BACKEND_PORT}
|
||||
|
||||
|
||||
# 静态文件服务(生产模式:前端 build 产物由 FastAPI 直接 serving)
|
||||
if STATIC_DIR.exists():
|
||||
app.mount("/assets", StaticFiles(directory=str(STATIC_DIR / "assets")), name="assets")
|
||||
|
||||
@app.get("/{full_path:path}")
|
||||
async def serve_spa(request: Request, full_path: str):
|
||||
"""SPA catch-all:非 API 路由统一返回 index.html"""
|
||||
file_path = STATIC_DIR / full_path
|
||||
if file_path.is_file():
|
||||
return FileResponse(str(file_path))
|
||||
return FileResponse(str(STATIC_DIR / "index.html"))
|
||||
Reference in New Issue
Block a user