62 lines
2.1 KiB
Python
62 lines
2.1 KiB
Python
import logging
|
|
from collections.abc import Iterator
|
|
|
|
from fastapi import FastAPI, HTTPException, Request, status
|
|
from fastapi.responses import StreamingResponse
|
|
|
|
from app.auth import verify_build_token
|
|
from app.builder import BuildError, cleanup_build, prepare_build, stream_build_and_push
|
|
from app.models import parse_json_build, parse_multipart_build
|
|
|
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
|
|
|
|
app = FastAPI(title="Docker Build Service", version="0.1.0")
|
|
|
|
|
|
@app.get("/health")
|
|
def health() -> dict[str, str]:
|
|
return {"status": "ok"}
|
|
|
|
|
|
@app.post("/build")
|
|
async def build(request: Request) -> StreamingResponse:
|
|
content_type = request.headers.get("content-type", "")
|
|
if content_type.startswith("multipart/form-data"):
|
|
build_request = await parse_multipart_build(request)
|
|
elif content_type.startswith("application/json"):
|
|
build_request = await parse_json_build(request)
|
|
else:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,
|
|
detail="Content-Type must be application/json or multipart/form-data",
|
|
)
|
|
|
|
claims = verify_build_token(build_request.token)
|
|
uploads = (
|
|
build_request.uploads
|
|
if build_request.uploads and claims.uploads_authorized()
|
|
else None
|
|
)
|
|
prepared = prepare_build(
|
|
claims,
|
|
commit=build_request.commit,
|
|
uploads=uploads,
|
|
repo_username=build_request.repo_username,
|
|
repo_password=build_request.repo_password,
|
|
)
|
|
def generate() -> Iterator[str]:
|
|
try:
|
|
yield from stream_build_and_push(
|
|
prepared,
|
|
tags=build_request.tags,
|
|
remote=build_request.remote,
|
|
username=build_request.username,
|
|
password=build_request.password,
|
|
)
|
|
except BuildError as exc:
|
|
# Headers are already sent as 200 once streaming starts.
|
|
yield f"\n[build-service] ERROR: {exc.message}\n"
|
|
finally:
|
|
cleanup_build(prepared)
|
|
|
|
return StreamingResponse(generate(), media_type="text/plain; charset=utf-8")
|