fix(cli): report the installed repeater and core versions from ver

MeshCLI's `ver` read config["version"], which nothing sets, so every node
answered the fallback "openHop_repeater v13". Report the installed packages
instead: "openHop_repeater v<repeater> (core v<core>)".

The virtual companion's CLI `ver` now names the repeater too: the bridge
registers its version with the core's companion CLI when that core has one.
This commit is contained in:
agessaman authored and Rightup committed 2026-10-02 10:57:51 +01:00
1 parent d5e4bd754c
commit 016ee64cbb
4 files changed
+51 -3

No files matched your search

+7
View File
@@ -16,6 +16,8 @@ from typing import Any, Callable, Optional
from openhop_core.companion import CompanionBridge
from repeater import __version__ as repeater_version
logger = logging.getLogger("RepeaterCompanionBridge")
@@ -93,6 +95,11 @@ class RepeaterCompanionBridge(CompanionBridge):
radio_settings_getter=radio_settings_getter,
max_tx_power_getter=max_tx_power_getter,
)
# The companion CLI's `ver` names the openHop software; add the repeater
# ahead of the core. An older core has no companion CLI to tell.
add_version = getattr(getattr(self, "cli", None), "add_software_version", None)
if callable(add_version):
add_version("repeater", repeater_version)
def _save_prefs(self) -> None:
"""Persist full NodePrefs as JSON to SQLite."""
+10 -3
View File
@@ -4,6 +4,10 @@ import re
from pathlib import Path
from typing import Any, Callable, Dict, Optional
from openhop_core import __version__ as core_version
from repeater import __version__ as repeater_version
logger = logging.getLogger(__name__)
@@ -493,10 +497,13 @@ class MeshCLI:
return "Error: Not yet implemented"
def _cmd_version(self) -> str:
"""Get version information."""
"""Report the installed openHop repeater and core versions.
Nothing sets ``config["version"]``, so reading it answered the stale
fallback "v13" in every real deployment.
"""
role = "room_server" if self.identity_type == "room_server" else "repeater"
version = self.config.get("version", "13")
return f"openHop_{role} v{version}"
return f"openHop_{role} v{repeater_version} (core v{core_version})"
# ==================== Get Commands ====================
+20
View File
@@ -84,3 +84,23 @@ def test_bridge_accepts_host_radio_callbacks(identity):
"airtime_factor": 1.0,
}
assert bridge.get_max_tx_power_dbm() == 20
def test_companion_ver_names_the_repeater_and_core_versions():
"""The virtual companion's CLI `ver` (CMD_RUN_CLI_COMMAND / remote CLI)
reports the openHop software running it, repeater first."""
import openhop_core
from openhop_core.protocol import LocalIdentity
import repeater
from repeater.companion.bridge import RepeaterCompanionBridge
async def _inject(pkt, wait_for_ack=False, expected_crc=None):
return True
bridge = RepeaterCompanionBridge(LocalIdentity(), _inject, node_name="Comp")
if not hasattr(bridge, "cli"):
pytest.skip("installed openhop_core predates the companion CLI")
assert bridge.cli.handle("ver") == (
f"openHop repeater v{repeater.__version__}, core v{openhop_core.__version__}"
)
+14
View File
@@ -885,3 +885,17 @@ def test_neighbor_remove_takes_the_cached_scopes_with_it(tmp_path):
assert cli.handle_command(b"\x00" * 32, "neighbor.remove all", True) == "OK"
assert set(handler.get_neighbor_scopes()) == {companion}
@pytest.mark.parametrize(
("identity_type", "role"), [("repeater", "repeater"), ("room_server", "room_server")]
)
def test_ver_reports_the_installed_repeater_and_core_versions(identity_type, role):
"""Nothing sets config["version"], so it must not be the source: it answered
the stale fallback "v13" on every real node."""
import openhop_core
import repeater
cli = MeshCLI("/tmp/cfg.yaml", _base_config(), _cfg_mgr(), identity_type=identity_type)
assert cli.handle_command(b"\x00" * 32, "ver", True) == (
f"openHop_{role} v{repeater.__version__} (core v{openhop_core.__version__})"
)