xbp 0.4.1

XBP is a build pack and deployment management tool to deploy, rust, nextjs etc and manage the NGINX configs below it
Documentation
from fastapi import FastAPI, APIRouter, HTTPException
from dotenv import load_dotenv
import time

load_dotenv()
app = FastAPI()
router = APIRouter()

from pydantic import BaseModel, ValidationError

from add_commit_status import post_commit_comment, post_commit_status
from ssh_shell import execute_ssh_command
from deployments import PmDeployment


def message_builder():
    pass


async def handle_commit_messaging(deployment):

    if deployment.status == "pending":
        # Post a commit comment for status pending
        comment_body = f"XBP started building: {deployment.sha_short} by [{deployment.github_username}](https://github.com/{deployment.github_username}) \n\n View the deployment at [xylex.cloud/xylex/xylex.cloud/deployments/{deployment.deployment_id}](https://xylex.cloud/{deployment.organization_name}/{deployment.project_name}/deployments/{deployment.deployment_id})"
        commit_status = "XBP is building your app...   "
    elif deployment.status == "error":
        # Post a commit comment for status error
        comment_body = f"XBP encountered an error while building: {deployment.sha_short} by [{deployment.github_username}](https://github.com/{deployment.github_username}) \n\n Check the deployment logs at [xylex.cloud/xylex/xylex.cloud/deployments/{deployment.deployment_id}](https://xylex.cloud/{deployment.organization_name}/{deployment.project_name}/deployments/{deployment.deployment_id})"
        commit_status = "XBP encountered an error during the build process."
    elif deployment.status == "failure":
        # Post a commit comment for status failure
        comment_body = f"XBP failed to build: {deployment.sha_short} by [{deployment.github_username}](https://github.com/{deployment.github_username}) \n\n View the failure details at [xylex.cloud/xylex/xylex.cloud/deployments/{deployment.deployment_id}](https://xylex.cloud/{deployment.organization_name}/{deployment.project_name}/deployments/{deployment.deployment_id})"
        commit_status = "XBP failed to build your app."
    elif deployment.status == "success":
        # Post a commit comment for status success
        comment_body = f"XBP successfully built: {deployment.sha_short} by [{deployment.github_username}](https://github.com/{deployment.github_username}) \n\n View the deployment at [xylex.cloud/xylex/xylex.cloud/deployments/{deployment.deployment_id}](https://xylex.cloud/{deployment.organization_name}/{deployment.project_name}/deployments/{deployment.deployment_id})"
        commit_status = "XBP successfully built your app!"
    else:
        # Default case if status is unknown
        comment_body = f"XBP encountered an unknown status for: {deployment.sha_short} by [{deployment.github_username}](https://github.com/{deployment.github_username})"
        commit_status = "XBP encountered an unknown status."

    # handle the message builder
    post_commit_comment(deployment=deployment, comment_body=comment_body)
    post_commit_status(deployment=deployment, commit_status=commit_status)


@app.post("/report-deployment-status")
async def xbp_report(payload: dict):
    # Extract values from the request body
    print("🚀 ~ payload:", payload)
    from pydantic import BaseModel, ValidationError

    class Deployment(BaseModel):
        sha: str
        sha_short: str
        github_username: str
        organization_name: str
        project_name: str
        deployment_id: str
        status: str
        repository_name: str
        repository_owner: str
        xbp_command: str
        project_id: str

    try:
        deployment = Deployment(**payload)
    except ValidationError as e:
        return {"error": f"Invalid payload: {e.errors()}"}
    print("🚀 ~ deployment:", deployment)

    await handle_commit_messaging(deployment)
    # also update the deployment status in the database
    try:
        response = PmDeployment(**payload).update_deployment(
            deployment_id=deployment.deployment_id,
            update_data=payload)
        print("🚀 ~ Deployment update response:", response)
    except Exception as e:
        return {"error": f"Failed to update deployment: {str(e)}"}
    return {
        "message": "Sent commit status and comment",
        "status": "success",
        "sha": deployment.sha,
        "sha_short": deployment.sha_short,
        "deployment_id": deployment.deployment_id,
        "github_username": deployment.github_username,
        "organization_name": deployment.organization_name,
        "project_name": deployment.project_name,
        "status": deployment.status,
        "repository_name": deployment.repository_name,
        "repository_owner": deployment.repository_owner,
        "xbp_command": deployment.xbp_command,
        "project_id": deployment.project_id,
        "time": time.time(),
    }


from pydantic import BaseModel, ValidationError


@app.post("/deploy-github")
async def xbp(payload: dict):
    """
    Endpoint to handle GitHub deployment requests.

    Args:
        payload (dict): The deployment data from the request body.

    Returns:
        dict: Response containing deployment details and status.
    """
    print("🚀 ~ Received payload:", payload)

    class Deployment(BaseModel):
        sha: str
        sha_short: str
        github_username: str
        organization_name: str
        project_name: str
        deployment_id: str
        status: str
        repository_name: str
        repository_owner: str
        xbp_command: str
        project_id: str
        commit_comment: str
        repository_url: str

    try:
        deployment = Deployment(**payload)
    except ValidationError as e:
        return {"error": f"Invalid payload: {e.errors()}"}

    print("🚀 ~ Validated deployment:", deployment)

    # Handle commit messaging
    await handle_commit_messaging(deployment)

    # Create a new deployment in the database
    try:
        response = PmDeployment(**payload).create_deployment()
        print("🚀 ~ Deployment creation response:", response)
    except Exception as e:
        return {"error": f"Failed to create deployment: {str(e)}"}

    # Execute the deployment command via SSH
    try:
        ssh_result = await execute_ssh_command(
            deployment_id=deployment.deployment_id,
            command=deployment.xbp_command,
            deployment=deployment)
        print("🚀 ~ SSH command result:", ssh_result)
    except Exception as e:
        return {"error": f"Failed to execute SSH command: {str(e)}"}

    # Return the response
    return {
        "message": "Deployment initiated successfully",
        "status": "pending",
        "sha": deployment.sha,
        "sha_short": deployment.sha_short,
        "deployment_id": deployment.deployment_id,
        "github_username": deployment.github_username,
        "organization_name": deployment.organization_name,
        "project_name": deployment.project_name,
        "status": deployment.status,
        "repository_name": deployment.repository_name,
        "repository_owner": deployment.repository_owner,
        "xbp_command": deployment.xbp_command,
        "project_id": deployment.project_id,
        "time": time.time(),
        "ssh_result": ssh_result,
    }


@router.post("/create-deployment")
async def create_deployment(payload: dict):
    """
    Endpoint to create a new deployment in the Supabase database.

    Args:
        payload (dict): The deployment data to be created.

    Returns:
        dict: The response from the Supabase API or an error message.
    """
    try:
        deployment = PmDeployment(**payload)
        response = deployment.create_deployment()
        return {
            "message": "Deployment created successfully",
            "response": response
        }
    except ValidationError as e:
        raise HTTPException(status_code=400,
                            detail=f"Invalid payload: {e.errors()}")
    except Exception as e:
        raise HTTPException(status_code=500,
                            detail=f"An error occurred: {str(e)}")


@router.put("/update-deployment/{deployment_id}")
async def update_deployment(deployment_id: str, update_data: dict):
    """
    Endpoint to update an existing deployment in the Supabase database.

    Args:
        deployment_id (str): The ID of the deployment to update.
        update_data (dict): The fields to update in the deployment.

    Returns:
        dict: The response from the Supabase API or an error message.
    """
    try:
        deployment = PmDeployment(**update_data)
        response = deployment.update_deployment(deployment_id, update_data)
        return {
            "message": "Deployment updated successfully",
            "response": response
        }
    except ValidationError as e:
        raise HTTPException(status_code=400,
                            detail=f"Invalid update data: {e.errors()}")
    except Exception as e:
        raise HTTPException(status_code=500,
                            detail=f"An error occurred: {str(e)}")






if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=3398)