-
-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathhatch_build.py
More file actions
80 lines (69 loc) · 3.39 KB
/
Copy pathhatch_build.py
File metadata and controls
80 lines (69 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# Copyright (c) 2025-2026 Datalayer, Inc.
# Distributed under the terms of the Modified BSD License.
"""Custom build hook to ensure UI is built before packaging."""
import subprocess
import sys
from pathlib import Path
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
class CustomBuildHook(BuildHookInterface):
"""Build hook to compile the UI before creating the Python package."""
PLUGIN_NAME = "custom"
@staticmethod
def _ensure_placeholder_dist(dist_dir: Path) -> None:
"""Create a minimal dist directory so wheel force-include always succeeds."""
dist_dir.mkdir(parents=True, exist_ok=True)
placeholder = dist_dir / ".placeholder"
if not placeholder.exists():
placeholder.write_text(
"UI assets were not built in this environment.\n",
encoding="utf-8",
)
def initialize(self, version: str, build_data: dict) -> None:
"""Build the UI before packaging."""
import os
ui_dir = Path(self.root) / "ui"
dist_dir = ui_dir / "dist"
# Allow skipping the UI build entirely via environment variable.
# Useful in CI environments where Node.js/npm may not be available.
if os.environ.get("MCP_COMPOSE_SKIP_UI_BUILD", "").lower() in ("1", "true", "yes"):
print("⏭ Skipping UI build (MCP_COMPOSE_SKIP_UI_BUILD is set)", file=sys.stderr)
self._ensure_placeholder_dist(dist_dir)
return
# Check if UI dist exists and has content
if not dist_dir.exists() or not list(dist_dir.iterdir()):
print("Building UI...", file=sys.stderr)
# Check if node_modules exists, if not run npm install
if not (ui_dir / "node_modules").exists():
print("Installing UI dependencies...", file=sys.stderr)
try:
subprocess.run(
["npm", "install"],
cwd=ui_dir,
check=True,
)
except subprocess.CalledProcessError as e:
print(f"✗ npm install failed with exit code {e.returncode}", file=sys.stderr)
print("Make sure Node.js and npm are installed and accessible", file=sys.stderr)
sys.exit(1)
except FileNotFoundError:
print("⚠ npm not found, skipping UI build. The web UI will not be available.", file=sys.stderr)
self._ensure_placeholder_dist(dist_dir)
return
# Build the UI
print("Running npm build...", file=sys.stderr)
try:
subprocess.run(
["npm", "run", "build"],
cwd=ui_dir,
check=True,
)
print("✓ UI built successfully", file=sys.stderr)
except subprocess.CalledProcessError as e:
print(f"✗ npm build failed with exit code {e.returncode}", file=sys.stderr)
sys.exit(1)
except FileNotFoundError:
print("⚠ npm not found, skipping UI build. The web UI will not be available.", file=sys.stderr)
self._ensure_placeholder_dist(dist_dir)
return
else:
print("✓ UI already built, skipping build step", file=sys.stderr)