mirror of
https://github.com/AstrBotDevs/AstrBot.git
synced 2026-08-30 17:33:24 +08:00
fix: warn when an explicitly configured WebUI dist is stale (#9518)
* fix: warn when an explicitly configured WebUI dist is stale resolve_dashboard_dist() returns an explicitly configured --webui-dir immediately, without checking the version it declares. Every other branch in the same function verifies compatibility and warns on a mismatch, so this is the one way to end up serving assets that do not match the running core with no diagnostic at all. That is the case a packaged distribution hits: when the launcher updates the backend but keeps its bundled WebUI directory, the dashboard silently stays on the previous release. Features added by the new core are simply missing from the UI and nothing explains why. Behaviour is unchanged -- the directory is still served, since refusing to serve it would be worse than serving an old one. It is just no longer silent. * refactor: tidy the explicit WebUI dist resolution Build the Path once instead of twice, and hold the version read for the warning in a local so the log call only carries values.
This commit is contained in:
@@ -141,8 +141,20 @@ def resolve_dashboard_dist(webui_dir: str | Path | None = None) -> Path | None:
|
||||
Explicit, managed, bundled, or stale fallback dist in priority order;
|
||||
None when an existing managed dist is incomplete.
|
||||
"""
|
||||
if webui_dir and Path(webui_dir).exists():
|
||||
return Path(webui_dir).absolute()
|
||||
explicit_dist = Path(webui_dir).absolute() if webui_dir else None
|
||||
if explicit_dist is not None and explicit_dist.exists():
|
||||
if not _is_dist_compatible(explicit_dist, VERSION):
|
||||
explicit_version = _read_dashboard_version(explicit_dist) or "unknown"
|
||||
logger.warning(
|
||||
"Serving the explicitly configured WebUI directory even though it "
|
||||
"does not declare a version matching core: %s, expected v%s (%s). "
|
||||
"Some dashboard features may not work until matching assets are "
|
||||
"available.",
|
||||
explicit_version,
|
||||
VERSION,
|
||||
explicit_dist,
|
||||
)
|
||||
return explicit_dist
|
||||
|
||||
user_dist = Path(get_astrbot_data_path()) / "dist"
|
||||
bundled_dist = _get_bundled_dist_path()
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
"""Tests for resolve_dashboard_dist() when an explicit WebUI directory is used."""
|
||||
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
|
||||
from astrbot.core.config.default import VERSION
|
||||
from astrbot.core.dashboard_assets import resolve_dashboard_dist
|
||||
|
||||
WARNING_FRAGMENT = "does not declare a version matching core"
|
||||
|
||||
|
||||
def _make_dist(root, version: str | None) -> str:
|
||||
assets = root / "assets"
|
||||
assets.mkdir(parents=True)
|
||||
(root / "index.html").write_text("<html></html>", encoding="utf-8")
|
||||
if version is not None:
|
||||
(assets / "version").write_text(version, encoding="utf-8")
|
||||
return str(root)
|
||||
|
||||
|
||||
class TestExplicitWebuiDir:
|
||||
def test_matching_version_is_served_quietly(self, tmp_path, caplog):
|
||||
"""The happy path must not add startup noise."""
|
||||
dist = _make_dist(tmp_path / "webui", f"v{VERSION}")
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
resolved = resolve_dashboard_dist(dist)
|
||||
|
||||
assert resolved is not None
|
||||
assert str(resolved) == str(tmp_path / "webui")
|
||||
assert WARNING_FRAGMENT not in caplog.text
|
||||
|
||||
def test_mismatched_version_warns_but_is_still_served(self, tmp_path, caplog):
|
||||
"""A stale packaged WebUI must not be swapped in silently."""
|
||||
dist = _make_dist(tmp_path / "webui", "v0.0.1")
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
resolved = resolve_dashboard_dist(dist)
|
||||
|
||||
assert resolved is not None # behaviour unchanged: still served
|
||||
assert WARNING_FRAGMENT in caplog.text
|
||||
assert "v0.0.1" in caplog.text
|
||||
assert VERSION in caplog.text
|
||||
|
||||
def test_missing_version_marker_warns_as_unknown(self, tmp_path, caplog):
|
||||
"""Assets without a version marker cannot be verified, so say so."""
|
||||
dist = _make_dist(tmp_path / "webui", None)
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
resolved = resolve_dashboard_dist(dist)
|
||||
|
||||
assert resolved is not None
|
||||
assert WARNING_FRAGMENT in caplog.text
|
||||
assert "unknown" in caplog.text
|
||||
|
||||
def test_nonexistent_dir_falls_through(self, tmp_path, caplog):
|
||||
"""A path that does not exist must not be reported as a stale dist."""
|
||||
with caplog.at_level(logging.WARNING):
|
||||
resolve_dashboard_dist(str(tmp_path / "does-not-exist"))
|
||||
|
||||
assert WARNING_FRAGMENT not in caplog.text
|
||||
|
||||
@pytest.mark.parametrize("empty", ["", None])
|
||||
def test_no_explicit_dir_falls_through(self, empty, caplog):
|
||||
"""Without --webui-dir the managed/bundled resolution path is used."""
|
||||
with caplog.at_level(logging.WARNING):
|
||||
resolve_dashboard_dist(empty)
|
||||
|
||||
assert WARNING_FRAGMENT not in caplog.text
|
||||
Reference in New Issue
Block a user