* build(#2695): add packaging metadata for the current runtime layout * docs(changelog): stamp #6337 pip-installable packaging metadata --------- Co-authored-by: Rod Boev <rod.boev@gmail.com> Co-authored-by: nesquena-hermes <agent@nesquena-hermes>
125 lines
3.5 KiB
Python
125 lines
3.5 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import zipfile
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
def _copy_repo_without_heavy_dirs(dst: Path) -> Path:
|
|
repo_copy = dst / "repo"
|
|
shutil.copytree(
|
|
ROOT,
|
|
repo_copy,
|
|
ignore=shutil.ignore_patterns(
|
|
".git",
|
|
".venv",
|
|
"node_modules",
|
|
".pytest_cache",
|
|
".ruff_cache",
|
|
"__pycache__",
|
|
),
|
|
)
|
|
return repo_copy
|
|
|
|
|
|
def _build_wheel(repo_copy: Path) -> Path:
|
|
dist_dir = repo_copy / "dist"
|
|
env = os.environ.copy()
|
|
env["SETUPTOOLS_SCM_PRETEND_VERSION_FOR_HERMES_WEBUI"] = "0.52.2695"
|
|
subprocess.run(
|
|
[
|
|
sys.executable,
|
|
"-m",
|
|
"pip",
|
|
"wheel",
|
|
".",
|
|
"--no-deps",
|
|
"--wheel-dir",
|
|
str(dist_dir),
|
|
],
|
|
cwd=repo_copy,
|
|
env=env,
|
|
check=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
text=True,
|
|
)
|
|
wheels = sorted(dist_dir.glob("hermes_webui-*.whl"))
|
|
assert wheels, "wheel build must produce a hermes_webui wheel"
|
|
return wheels[0]
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def extracted_wheel(tmp_path_factory):
|
|
tmp = tmp_path_factory.mktemp("packaged-runtime")
|
|
repo_copy = _copy_repo_without_heavy_dirs(tmp)
|
|
wheel = _build_wheel(repo_copy)
|
|
extract_dir = tmp / "wheel"
|
|
with zipfile.ZipFile(wheel) as zf:
|
|
zf.extractall(extract_dir)
|
|
return wheel, extract_dir
|
|
|
|
|
|
def test_wheel_build_contains_runtime_tree(extracted_wheel):
|
|
wheel, _ = extracted_wheel
|
|
with zipfile.ZipFile(wheel) as zf:
|
|
names = set(zf.namelist())
|
|
assert "bootstrap.py" in names
|
|
assert "server.py" in names
|
|
assert "mcp_server.py" in names
|
|
assert "api/config.py" in names
|
|
assert "api/_scm_version.py" in names
|
|
assert "static/__init__.py" in names
|
|
assert "static/index.html" in names
|
|
assert "static/ui.js" in names
|
|
assert "static/style.css" in names
|
|
assert "static/vendor/smd.min.js" in names
|
|
|
|
|
|
def test_extracted_wheel_resolves_static_root_without_console_entrypoint_contract_change(extracted_wheel):
|
|
_, extract_dir = extracted_wheel
|
|
script = """
|
|
import api.config as api_config
|
|
from api.updates import WEBUI_VERSION
|
|
print(api_config.__file__)
|
|
print(api_config.get_static_root())
|
|
print(api_config.get_index_html_path())
|
|
print(WEBUI_VERSION)
|
|
"""
|
|
env = os.environ.copy()
|
|
env["PYTHONPATH"] = str(extract_dir)
|
|
env["GIT_CEILING_DIRECTORIES"] = str(extract_dir.parent)
|
|
result = subprocess.run(
|
|
[sys.executable, "-c", script],
|
|
cwd=extract_dir,
|
|
env=env,
|
|
check=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
text=True,
|
|
)
|
|
lines = [line.strip() for line in result.stdout.splitlines() if line.strip()]
|
|
assert lines == [
|
|
str((extract_dir / "api" / "config.py").resolve()),
|
|
str((extract_dir / "static").resolve()),
|
|
str((extract_dir / "static" / "index.html").resolve()),
|
|
"v0.52.2695",
|
|
]
|
|
assert Path(lines[0]).exists()
|
|
assert Path(lines[1]).is_dir()
|
|
assert Path(lines[2]).is_file()
|
|
|
|
|
|
def test_checkout_static_root_stays_repo_relative():
|
|
import api.config as api_config
|
|
|
|
assert api_config.get_static_root() == ROOT / "static"
|
|
assert api_config.get_index_html_path() == ROOT / "static" / "index.html"
|