Files
AstrBot/scripts/hatch_build.py
LIghtJUNction 569ff433ac fix(build): prevent wheel failure when dashboard not bundled
When ASTRBOT_BUILD_DASHBOARD is not set, the hatch build hook now
creates an empty target dir with a .placeholder file so the
artifacts glob matches and hatchling does not fail.
2026-03-24 19:19:55 +08:00

91 lines
3.3 KiB
Python

"""
Custom Hatchling build hook.
Only runs when the environment variable ASTRBOT_BUILD_DASHBOARD=1 is set,
so that `uv sync` / editable installs are never affected.
Usage:
ASTRBOT_BUILD_DASHBOARD=1 uv build
When enabled, this hook:
1. Runs `npm run build` inside the `dashboard/` directory.
2. Copies the resulting `dashboard/dist/` tree into
`astrbot/dashboard/dist/` so the static assets are shipped
inside the Python wheel.
"""
import os
import shutil
import subprocess
import sys
from logging import getLogger
from pathlib import Path
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
logger = getLogger(__name__)
class CustomBuildHook(BuildHookInterface):
PLUGIN_NAME = "custom"
def initialize(self, version: str, build_data: dict) -> None:
root = Path(self.root)
dashboard_src = root / "dashboard"
dist_src = dashboard_src / "dist"
dist_target = root / "astrbot" / "dashboard" / "dist"
if os.environ.get("ASTRBOT_BUILD_DASHBOARD", "").strip() != "1":
# Ensure the target directory and a placeholder exist so the wheel
# build does not fail when artifacts = ["..."] is declared.
dist_target.mkdir(parents=True, exist_ok=True)
if not dist_target.exists() or not any(dist_target.iterdir()):
placeholder = dist_target / ".placeholder"
placeholder.write_text("# dashboard placeholder\n")
return
if not dashboard_src.exists():
logger.warning(
"[hatch_build] 'dashboard/' directory not found: skipping dashboard build.",
file=sys.stderr,
)
dist_target.mkdir(parents=True, exist_ok=True)
placeholder = dist_target / ".placeholder"
placeholder.write_text("# dashboard placeholder\n")
return
# ── Install Node dependencies if node_modules is absent ─────────────
if not (dashboard_src / "node_modules").exists():
logger.info("[hatch_build] Installing dashboard Node dependencies...")
subprocess.run(
["npm", "install"],
cwd=dashboard_src,
check=True,
)
# ── Build the Vue/Vite dashboard ──────────────────────────────────────
logger.info("[hatch_build] Building Vue dashboard (npm run build)...")
subprocess.run(
["npm", "run", "build"],
cwd=dashboard_src,
check=True,
)
if not dist_src.exists():
logger.warning(
"[hatch_build] dashboard/dist not found after build: skipping copy.",
file=sys.stderr,
)
dist_target.mkdir(parents=True, exist_ok=True)
placeholder = dist_target / ".placeholder"
placeholder.write_text("# dashboard placeholder\n")
return
# ── Copy into the Python package tree ───────────────────────────────
if dist_target.exists():
shutil.rmtree(dist_target)
shutil.copytree(dist_src, dist_target)
logger.info(
f"[hatch_build] Dashboard dist copied → {dist_target.relative_to(root)}"
)