More impl for devops

This commit is contained in:
dongli 2025-06-07 11:32:48 -07:00
parent 217f33fc17
commit 308f82740d
8 changed files with 112 additions and 45 deletions

View File

@ -18,6 +18,11 @@ class SiteSettings(BaseSettings):
BASE_PATH: str = os.path.dirname(os.path.dirname((os.path.abspath(__file__))))
BASE_GITEA_URL: str = "https://gitea.freeleaps.mathmast.com"
# TODO: confirm with Zhenyu
BASE_RECONSILE_URL: str = "https://reconcile.freeleaps.mathmast.com"
class Config:
env_file = ".devbase-webapi.env"
env_file_encoding = "utf-8"

View File

@ -0,0 +1,6 @@
from app.common.daos.code_depot.code_depot_dao import CodeDepotDao
code_depot_dao = CodeDepotDao()
def get_code_depot_dao() -> CodeDepotDao:
return code_depot_dao

View File

@ -0,0 +1,19 @@
from app.common.models.code_depot.code_depot import CodeDepotDoc
class CodeDepotDao():
def __init__(self):
pass
async def get_code_depot_by_product_id(self, product_id: str) -> CodeDepotDoc:
"""
Retrieve code depot by product id
"""
return await CodeDepotDoc.find_one({"product_id": product_id})
async def insert_code_depot(self, code_depot: CodeDepotDoc) -> CodeDepotDoc:
"""
Insert a new code depot into the database
"""
return await CodeDepotDoc.insert_one(code_depot)

View File

@ -2,5 +2,5 @@ from app.common.daos.deployment.deployment_dao import DeploymentDao
deployment_dao = DeploymentDao()
def get_hello_world_dao() -> DeploymentDao:
def get_deployment_dao() -> DeploymentDao:
return deployment_dao

View File

@ -5,9 +5,10 @@ class DeploymentDao():
def __init__(self):
pass
async def create_deployment(self, deployment_data: Deployment):
async def create_deployment(self, deployment_data: Deployment) -> Deployment:
# Logic to create a new deployment
Deployment.insert(deployment_data)
return await Deployment.insert(deployment_data)
async def get_deployments_by_deployment_id(self, deployment_id: str):
# Logic to get a deployment by ID

View File

@ -1,4 +1,6 @@
from app.common.models.code_depot.code_depot import CodeDepotDoc
from app.common.models.deployment.deployment import Deployment
# list of beanie document models
db_models = [Deployment]
# list of beanie document models,
# must add here so that the mongo db collection can be automatically created
db_models = [Deployment, CodeDepotDoc]

View File

@ -4,6 +4,7 @@ from typing import List
from fastapi import APIRouter, Depends
from loguru import logger
from app.common.models import CodeDepotDoc
from app.common.models.deployment.deployment import Deployment, InitDeploymentRequest
from app.routes.deployment.service import DeploymentService, get_deployment_service
@ -31,3 +32,16 @@ async def check_deployment_status(
) -> List[Deployment]:
return await service.check_deployment_status(deployment_id)
@router.post("/createDummyCodeDepot")
async def create_dummy_code_depot(
service: DeploymentService = Depends(get_deployment_service)
) -> CodeDepotDoc:
"""
Create a dummy code depot for testing purposes.
"""
try:
depot_name = await service.create_dummy_code_depot()
return depot_name
except Exception as e:
logger.error(f"Failed to create dummy code depot: {e}")
raise e

View File

@ -3,9 +3,14 @@ from collections import defaultdict
from datetime import datetime, timedelta
from typing import List
from fastapi import HTTPException
import httpx
from fastapi import HTTPException, Depends
from app.common.config.site_settings import site_settings
from app.common.daos.code_depot import get_code_depot_dao, CodeDepotDao
from app.common.daos.deployment import DeploymentDao, get_deployment_dao
from app.common.models import Deployment
from app.common.models.code_depot.code_depot import CodeDepotDoc, DepotStatus
from app.common.models.deployment.deployment import InitDeploymentRequest
@ -16,27 +21,25 @@ class DeploymentService:
async def init_deployment(
self,
request: InitDeploymentRequest
request: InitDeploymentRequest,
dao: DeploymentDao = Depends(get_deployment_dao)
) -> Deployment:
"""
"""
# TODO validate permission with user_id
# currently skip
git_url = await self._retrieve_git_url_by_product_id(request.product_id)
code_depot = await self._get_code_depot_by_product_id(request.product_id)
git_url = await self._compose_git_url(code_depot.depot_name)
product_initialized = await self._check_if_project_initialized(git_url, request.product_id)
if not product_initialized:
await self._init_product(git_url, request.product_id)
# retrieve project name
project_name = "TODO"
# retrieve product info
# retrieve product info, depot name should be the same as product name
product_id = request.product_id
product_name = "TODO"
product_name = code_depot.depot_name
deployment = Deployment.model_construct(
deployment_id = str(uuid.uuid4()),
@ -57,8 +60,8 @@ class DeploymentService:
)
await self._start_deployment(deployment)
res = await dao.create_deployment(deployment)
res = await deployment.insert()
return res
async def check_deployment_status(
@ -111,47 +114,64 @@ class DeploymentService:
return True
async def _retrieve_git_url_by_product_id(
async def _get_code_depot_by_product_id(
self,
product_id: str
product_id: str,
code_depot_dao: CodeDepotDao = Depends(get_code_depot_dao)
) -> CodeDepotDoc:
"""
Retrieve code depot by product id
"""
code_depot = await code_depot_dao.get_code_depot_by_product_id(product_id)
if not code_depot:
raise HTTPException(status_code=404,
detail="Code depot not found for the given product id, "
"please initialize the product first"
)
return code_depot
async def _compose_git_url(
self,
code_depot_name: str,
gitea_base_url: str = site_settings.BASE_GITEA_URL
) -> str:
"""
Retrieve git url by product id
"""
# TODO implement this function
return "TODO-git_url"
async def _check_if_project_initialized(
self,
git_url: str,
product_id: str
) -> bool:
"""
Check if the project has been initialized
"""
# TODO implement this function
return True
async def _init_product(
self,
git_url: str,
product_id: str
) -> bool:
"""
Initialize the product
"""
# TODO implement this function
pass
return f"{gitea_base_url}/prodcuts/{code_depot_name.lower()}.git"
async def _start_deployment(
self,
deployment: Deployment
deployment: Deployment,
reconsile_base_url: str = site_settings.BASE_RECONSILE_URL,
) -> bool:
"""
Start the deployment
"""
# TODO implement this function
pass
async with httpx.AsyncClient() as client:
response = await client.post(
f"{reconsile_base_url}/api/devops/reconcile",
json=deployment.model_dump()
)
if response.status_code != 200:
raise HTTPException(status_code=response.status_code, detail=response.text)
return True
async def create_dummy_code_depot(
self,
code_depot_dao: CodeDepotDao = Depends(get_code_depot_dao)
) -> CodeDepotDoc:
"""
Create a dummy code depot for testing purposes.
"""
depot_name = f"dummy-depot-{uuid.uuid4()}"
code_depot = CodeDepotDoc(
depot_name=depot_name,
product_id="dummy-product-id",
depot_status=DepotStatus.CREATED
)
return await code_depot.insert_one(code_depot)
deployment_service = DeploymentService()