b7f52be4c9
Copilot Setup Steps / copilot-setup-steps (push) Waiting to run
CI / Run CI (push) Has been cancelled
CI / check-backend (push) Has been cancelled
CI / check-frontend (push) Has been cancelled
CI / tests (push) Has been cancelled
CI / e2e-tests (push) Has been cancelled
111 lines
3.4 KiB
Python
111 lines
3.4 KiB
Python
"""Build script gets called on uv/pip build."""
|
|
|
|
import pathlib
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
|
|
|
|
class BuildError(Exception):
|
|
"""Custom exception for build failures"""
|
|
|
|
pass
|
|
|
|
|
|
def run_subprocess(cmd: list[str], cwd: pathlib.Path) -> None:
|
|
"""
|
|
Run a subprocess, allowing natural signal propagation.
|
|
|
|
Args:
|
|
cmd: Command and arguments as a list of strings
|
|
cwd: Working directory for the subprocess
|
|
"""
|
|
|
|
print(f"-- Running: {' '.join(cmd)}")
|
|
subprocess.run(cmd, cwd=cwd, check=True)
|
|
|
|
|
|
def pnpm_install(project_root: pathlib.Path, pnpm_path: str):
|
|
run_subprocess([pnpm_path, "install", "--frozen-lockfile"], project_root)
|
|
|
|
|
|
def pnpm_buildui(project_root: pathlib.Path, pnpm_path: str):
|
|
run_subprocess([pnpm_path, "build"], project_root)
|
|
|
|
|
|
def copy_directory(src: pathlib.Path, dst: pathlib.Path, description: str):
|
|
"""Copy directory with proper error handling"""
|
|
print(f"Copying {description} from {src} to {dst}")
|
|
try:
|
|
if dst.exists():
|
|
shutil.rmtree(dst)
|
|
dst.mkdir(parents=True)
|
|
shutil.copytree(src, dst, dirs_exist_ok=True)
|
|
except KeyboardInterrupt:
|
|
print("\nInterrupt received during copy operation...")
|
|
# Clean up partial copies
|
|
if dst.exists():
|
|
shutil.rmtree(dst)
|
|
raise
|
|
except Exception as e:
|
|
raise BuildError(f"Failed to copy {src} to {dst}: {e!s}")
|
|
|
|
|
|
def copy_frontend(project_root: pathlib.Path):
|
|
"""Copy the frontend dist directory to the backend for inclusion in the package."""
|
|
backend_frontend_dir = project_root / "backend" / "chainlit" / "frontend" / "dist"
|
|
frontend_dist = project_root / "frontend" / "dist"
|
|
copy_directory(frontend_dist, backend_frontend_dir, "frontend assets")
|
|
|
|
|
|
def copy_copilot(project_root: pathlib.Path):
|
|
"""Copy the copilot dist directory to the backend for inclusion in the package."""
|
|
backend_copilot_dir = project_root / "backend" / "chainlit" / "copilot" / "dist"
|
|
copilot_dist = project_root / "libs" / "copilot" / "dist"
|
|
copy_directory(copilot_dist, backend_copilot_dir, "copilot assets")
|
|
|
|
|
|
def build():
|
|
"""Main build function with proper error handling"""
|
|
|
|
print(
|
|
"\n-- Building frontend, this might take a while!\n\n"
|
|
" If you don't need to build the frontend and just want dependencies installed, use:\n"
|
|
" `uv sync --no-install-project --no-editable`\n"
|
|
)
|
|
|
|
try:
|
|
# Find directory containing this file
|
|
backend_dir = pathlib.Path(__file__).resolve().parent
|
|
project_root = backend_dir.parent
|
|
|
|
# Dirty hack to distinguish between building wheel from sdist and from source code
|
|
if not (project_root / "package.json").exists():
|
|
return
|
|
|
|
pnpm = shutil.which("pnpm")
|
|
if not pnpm:
|
|
raise BuildError("pnpm not found!")
|
|
|
|
pnpm_install(project_root, pnpm)
|
|
pnpm_buildui(project_root, pnpm)
|
|
copy_frontend(project_root)
|
|
copy_copilot(project_root)
|
|
|
|
except KeyboardInterrupt:
|
|
print("\nBuild interrupted by user")
|
|
sys.exit(1)
|
|
except BuildError as e:
|
|
print(f"\nBuild failed: {e!s}")
|
|
sys.exit(1)
|
|
except Exception as e:
|
|
print(f"\nUnexpected error: {e!s}")
|
|
sys.exit(1)
|
|
|
|
|
|
class CustomBuildHook(BuildHookInterface):
|
|
def initialize(self, _, __):
|
|
build()
|