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
import os
import dotenv
import asyncio
import aiofiles
import asyncssh

from log_parser.nextjs import parse_nextjs_logs


async def execute_ssh_command(deployment_id, command, deployment):
    # Get SSH credentials from environment variables
    dotenv.load_dotenv()

    host = os.getenv('XLX_SSH_HOST')
    username = os.getenv('XLX_SSH_USER')
    password = os.getenv('XLX_SSH_PASS')

    if not all([host, username, password]):
        raise ValueError("Missing SSH credentials in environment variables")

    # Create the logs directory and deployment subdirectory
    log_dir = f"./logs/deployment_{deployment_id}"
    os.makedirs(log_dir, exist_ok=True)

    # Create the full path for the output file
    output_file_path = os.path.join(log_dir, f"{deployment_id}.txt")
    print(f"Output file path: {output_file_path}")
    try:
        # Use asyncssh to establish an SSH connection
        async with asyncssh.connect(host, username=username,
                                    password=password) as conn:
            # Execute the command
            print(f"Executing command: {command}")
            # The run() method returns a result object with stdout as an AsyncIterable
            process = await conn.create_process(command)

            # Capture the entire output (stdout + stderr)
            async with aiofiles.open(output_file_path, 'w',
                                     encoding='utf-8') as file:
                async for line in process.stdout:
                    # Process the log line
                    result = await parse_nextjs_logs(
                        line, deployment_data=deployment)
                    # If deployment is done, kill the process
                    if result:
                        print("Deployment completed. Terminating process.")
                        process.terminate()
                        break
                    # Stream output line by line
                    line = line.strip()
                    print(line)
                    await file.write(line + '\n')

                async for line in process.stderr:
                    # Handle errors in stderr
                    result = await parse_nextjs_logs(
                        line, deployment_data=deployment)
                    # If deployment is done, kill the process
                    if result:
                        print("Deployment completed. Terminating process.")
                        process.terminate()
                        break
                    line = line.strip()
                    print(line)
                    await file.write(line + '\n')  # Write to the log file

            print(f"Output saved to: {output_file_path}")

    except Exception as e:
        print(
            f"SSH connection or command execution failed: {str(e).encode('utf-8', errors='replace').decode('utf-8')}"
        )