feat(Self-Check): update self-check output with flush for immediate display and improve public assets check to allow source tree without build

This commit is contained in:
Ivan 2026-07-08 16:24:06 -05:00
parent ff7b1a43ec
commit 461d0fc60b
No known key found for this signature in database
4 changed files with 60 additions and 21 deletions

View file

@ -20440,9 +20440,9 @@ def main():
if args.self_check:
results = reticulum_meshchat.run_self_test()
print("\n================================")
print(" System Self-Check Results")
print("================================")
print("\n================================", flush=True)
print(" System Self-Check Results", flush=True)
print("================================", flush=True)
all_passed = True
from meshchatx.src.backend.self_check import SELF_CHECK_LABELS
@ -20450,20 +20450,20 @@ def main():
for key, name in SELF_CHECK_LABELS.items():
check = results.get(key, {"status": "failed", "reason": "No result"})
if check["status"] == "ok":
print(f"[OK] {name}")
print(f"[OK] {name}", flush=True)
else:
all_passed = False
reason = check.get("reason") or "Unknown error"
print(f"[FAILED] {name} - Reason: {reason}")
print(f"[FAILED] {name} - Reason: {reason}", flush=True)
print("================================")
print("================================", flush=True)
if all_passed:
print("Status: SUCCESS (All checks passed)")
print("================================\n")
print("Status: SUCCESS (All checks passed)", flush=True)
print("================================\n", flush=True)
sys.exit(0)
else:
print("Status: FAILED")
print("================================\n")
print("Status: FAILED", flush=True)
print("================================\n", flush=True)
sys.exit(1)
if args.reset_password:

View file

@ -398,10 +398,13 @@ class BotHandler:
if sys.platform.startswith("win"):
# Use absolute path if possible to avoid S607
taskkill = shutil.which("taskkill") or "taskkill"
# Process may already have exited; suppress "not found" noise.
subprocess.run(
[taskkill, "/PID", str(pid), "/T", "/F"],
check=False,
timeout=5,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
else:
try:

View file

@ -181,25 +181,48 @@ def check_temp_filesystem() -> dict[str, str]:
os.unlink(path)
def _is_frozen_executable() -> bool:
return bool(getattr(sys, "frozen", False))
def _frontend_source_available() -> bool:
"""True when running from a source tree with Vite frontend sources.
Built ``meshchatx/public/`` is gitignored and often absent in CI / E2E
(Vite serves the UI). Frozen desktop builds still require bundled public.
"""
try:
package_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
frontend = os.path.join(package_dir, "src", "frontend")
return os.path.isdir(frontend) and os.path.isfile(
os.path.join(frontend, "main.js")
)
except Exception:
return False
def check_public_assets(public_path_fn: Callable[[str], str]) -> dict[str, str]:
try:
root = public_path_fn("")
index_path = public_path_fn("index.html") if root else ""
if root and os.path.isdir(root):
if os.path.isfile(index_path):
return _status(True)
names = [n for n in os.listdir(root) if not n.startswith(".")]
if names:
return _status(True)
# Source / CI / E2E: no built public dir, but frontend sources exist.
if not _is_frozen_executable() and _frontend_source_available():
return _status(True)
if not root or not os.path.isdir(root):
return _status(False, f"Public assets directory missing: {root!r}")
index_path = public_path_fn("index.html")
if not os.path.isfile(index_path):
names = os.listdir(root)
if not names:
return _status(False, "Public assets directory is empty")
return _status(True)
return _status(False, "Public assets directory is empty")
except Exception as exc:
return _status(False, f"Public assets check failed: {exc}")
def _is_frozen_executable() -> bool:
return bool(getattr(sys, "frozen", False))
def check_meshchatx_run_module() -> dict[str, str]:
"""Verify ``--meshchatx-run-module`` re-entry used by bots/rnsh on frozen builds."""
marker_dir = tempfile.mkdtemp(prefix="meshchatx_run_module_check_")

View file

@ -64,12 +64,25 @@ def test_check_public_assets_ok(tmp_path):
assert self_check.check_public_assets(public_path)["status"] == "ok"
def test_check_public_assets_missing(tmp_path):
def test_check_public_assets_allows_source_tree_without_build(tmp_path, monkeypatch):
missing = tmp_path / "nope"
def public_path(name=""):
return str(missing / name) if name else str(missing)
monkeypatch.setattr(self_check, "_is_frozen_executable", lambda: False)
monkeypatch.setattr(self_check, "_frontend_source_available", lambda: True)
assert self_check.check_public_assets(public_path)["status"] == "ok"
def test_check_public_assets_missing_when_frozen(tmp_path, monkeypatch):
missing = tmp_path / "nope"
def public_path(name=""):
return str(missing / name) if name else str(missing)
monkeypatch.setattr(self_check, "_is_frozen_executable", lambda: True)
monkeypatch.setattr(self_check, "_frontend_source_available", lambda: False)
result = self_check.check_public_assets(public_path)
assert result["status"] == "failed"