diff --git a/.github/actions/uv-python-install/action.yaml b/.github/actions/uv-python-install/action.yaml index 87f252faf0..9cecc2b182 100644 --- a/.github/actions/uv-python-install/action.yaml +++ b/.github/actions/uv-python-install/action.yaml @@ -32,6 +32,6 @@ runs: with: python-version: ${{ inputs.python-version }} - name: Install Python dependencies - run: uv sync ${{ inputs.extra-dependencies }} + run: uv sync --no-install-project --no-editable ${{ inputs.extra-dependencies }} shell: bash working-directory: ${{ inputs.working-directory }} diff --git a/.github/workflows/lint-backend.yaml b/.github/workflows/lint-backend.yaml index 9da0bb358e..8a67459b96 100644 --- a/.github/workflows/lint-backend.yaml +++ b/.github/workflows/lint-backend.yaml @@ -28,5 +28,5 @@ jobs: changed-files: "true" args: "format --check" - name: Run Mypy - run: uv run mypy chainlit/ + run: uv run --no-project mypy chainlit/ working-directory: ${{ env.BACKEND_DIR }} diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index fc0a2a7ec0..113c728ea0 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -54,15 +54,11 @@ jobs: with: working-directory: ${{ env.BACKEND_DIR }} - - name: Build frontend and prepare assets - run: uv run python build.py - working-directory: ${{ env.BACKEND_DIR }} - - name: Build Python distribution run: uv build working-directory: ${{ env.BACKEND_DIR }} - - name: List wheel contents + - name: Check frontend and copilot folder included run: | pip install wheel python -m wheel unpack dist/chainlit-*.whl -d unpacked diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 59ca93fceb..cbf0f08fab 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -26,5 +26,5 @@ jobs: run: pnpm run buildUi timeout-minutes: 5 - name: Run Pytest - run: uv run pytest --cov=chainlit/ + run: uv run --no-project pytest --cov=chainlit/ working-directory: ${{ env.BACKEND_DIR }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0382c68462..9d4e088bb5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -79,14 +79,6 @@ cd backend uv sync --extra tests --extra mypy --extra dev --extra custom-data ``` -### Build Frontend - -The following will build the frontend distributions locally. From the root of the repo: - -```sh -pnpm run buildUi -``` - ## Start the Chainlit server from source Start by running `backend/hello.py` as an example. diff --git a/backend/build.py b/backend/build.py index 9990ba6f00..a5c294cdc7 100644 --- a/backend/build.py +++ b/backend/build.py @@ -1,11 +1,12 @@ """Build script gets called on uv/pip build.""" -import os import pathlib import shutil import subprocess import sys +from hatchling.builders.hooks.plugin.interface import BuildHookInterface + class BuildError(Exception): """Custom exception for build failures""" @@ -13,7 +14,7 @@ class BuildError(Exception): pass -def run_subprocess(cmd: list[str], cwd: os.PathLike) -> None: +def run_subprocess(cmd: list[str], cwd: pathlib.Path) -> None: """ Run a subprocess, allowing natural signal propagation. @@ -26,19 +27,21 @@ def run_subprocess(cmd: list[str], cwd: os.PathLike) -> None: subprocess.run(cmd, cwd=cwd, check=True) -def pnpm_install(project_root, pnpm_path): +def pnpm_install(project_root: pathlib.Path, pnpm_path: str): run_subprocess([pnpm_path, "install", "--frozen-lockfile"], project_root) -def pnpm_buildui(project_root, pnpm_path): +def pnpm_buildui(project_root: pathlib.Path, pnpm_path: str): run_subprocess([pnpm_path, "buildUi"], project_root) -def copy_directory(src, dst, description): +def copy_directory(src: pathlib.Path, dst: pathlib.Path, description: str): """Copy directory with proper error handling""" - print(f"Copying {src} to {dst}") + print(f"Copying {description} from {src} to {dst}") try: - dst.mkdir(parents=True, exist_ok=True) + 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...") @@ -50,14 +53,14 @@ def copy_directory(src, dst, description): raise BuildError(f"Failed to copy {src} to {dst}: {e!s}") -def copy_frontend(project_root): +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): +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" @@ -70,7 +73,7 @@ def build(): 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-build`\n" + " `uv sync --no-install-project --no-editable`\n" ) try: @@ -78,6 +81,10 @@ def build(): 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!") @@ -98,5 +105,6 @@ def build(): sys.exit(1) -if __name__ == "__main__": - build() +class CustomBuildHook(BuildHookInterface): + def initialize(self, _, __): + build() diff --git a/backend/pyproject.toml b/backend/pyproject.toml index e80cb1faf3..037c254bfc 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -116,17 +116,20 @@ exclude = [ "chainlit/copilot/**/**/" ] -[tool.hatch.build.targets.wheel] -packages = ["chainlit"] +[tool.hatch.build.hooks.custom] +path = "build.py" + +[tool.hatch.build.targets.sdist] artifacts = [ - "chainlit/frontend/dist/**/*", - "chainlit/copilot/dist/**/*" + "chainlit/frontend/dist/**/*", + "chainlit/copilot/dist/**/*" ] -[tool.hatch.build.targets.sdist] +[tool.hatch.build.targets.wheel] +packages = ["chainlit"] artifacts = [ - "chainlit/frontend/dist/**/*", - "chainlit/copilot/dist/**/*" + "chainlit/frontend/dist/**/*", + "chainlit/copilot/dist/**/*" ] [tool.hatch.version]