]> git.ipfire.org Git - pbs.git/commitdiff
api: builds: Add endpoints to fetch bugs and finish a build
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 15 Jul 2025 11:09:26 +0000 (11:09 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 15 Jul 2025 11:09:26 +0000 (11:09 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/api/builds.py

index 3e7194cdc6c8c6bb5084903c8dfa8f89f20d32a8..dd7a265a7df28232a262105ed4b0686df388a674 100644 (file)
 ###############################################################################
 
 import fastapi
+import pydantic
 
 from uuid import UUID
 
 from . import apiv1
+from . import auth
 from . import backend
 
 # Import types
+from ..bugtracker import Bug
 from ..builds import Build
+from ..users import User
 
+# Import errors
+from ..errors import NoSuchDistroError
 
 # Create a new router for all builds endpoints
 router = fastapi.APIRouter(
@@ -39,15 +45,89 @@ async def get_build_by_uuid(uuid: UUID) -> Build | None:
        """
                Fetches a build by its UUID
        """
-       return await backend.builds.get_by_uuid(uuid)
+       build = await backend.builds.get_by_uuid(uuid)
 
-@router.get("/{uuid}")
-async def get(build: Build = fastapi.Depends(get_build_by_uuid)) -> Build:
        # Raise 404 if the build could not be found
        if not build:
                raise fastapi.HTTPException(404, "Build not found")
 
        return build
 
+class CreateBuildRequest(pydantic.BaseModel):
+       # Upload
+       upload: UUID
+
+       # Repository
+       repo: str | None = None
+
+       # Architectures
+       arches: list[str] = []
+
+       # Disable test builds?
+       disable_test_builds: bool = False
+
+@router.post("")
+async def post(
+               request: CreateBuildRequest, current_user: User = fastapi.Depends(auth.get_current_user),
+       ) -> Build:
+       """
+               Creates a new (scratch) build
+       """
+       # Fetch the upload
+       upload = await backend.uploads.get_by_uuid(request.upload)
+       if not upload:
+               raise fastapi.HTTPException(422, "Could not find upload %s" % request.upload)
+
+       # Check if the user has permissions
+       if not upload.has_perm(current_user):
+               raise fastapi.HTTPException(403, "Permission denied to access the upload")
+
+       async with backend.db as session:
+               # Import the package
+               try:
+                       package = await backend.packages.create(upload)
+
+               # Fail if no matching distribution
+               except NoSuchDistroError as e:
+                       raise fastapi.HTTPException(422, "Could not find distro: %s" % e) from e
+
+               try:
+                       # Fetch the repo
+                       # XXX DUMMY
+                       repo = await current_user.get_repo(package.distro, None)
+                       assert repo, "NO REPO"
+
+                       # Create a new build
+                       build = await backend.builds.create(
+                               repo, package, owner=current_user, disable_test_builds=request.disable_test_builds,
+                       )
+
+               # If anything went wrong, we will delete the package
+               except Exception as e:
+                       await package.delete(current_user)
+
+                       raise e
+
+               # Delete the upload
+               await upload.delete()
+
+               # XXX Launch the build (should be a background task)
+
+
+       return build
+
+@router.get("/{uuid}")
+async def get(build: Build = fastapi.Depends(get_build_by_uuid)) -> Build:
+       return build
+
+#
+# Bugs
+#
+
+@router.get("/{uuid}/bugs")
+async def get_bugs(build: Build = fastapi.Depends(get_build_by_uuid)) -> list[Bug]:
+       # Return all bugs
+       return await build.get_bugs()
+
 # Add everything to the APIv1
 apiv1.include_router(router)