Fix gateway advertising 'unknown' version in production installs
CI / Gateway plugin tests (push) Successful in 5m56s
CI / Kotlin tests (android host + desktop) (push) Successful in 7m29s

hermes plugins install <repo>#gateway-plugin ships ONLY the
gateway-plugin/ subdirectory into ~/.hermes/plugins/iris, so the
repo-root VERSION file is not present there and plugin_version()
fell back to 'unknown' — the app then showed a false
'App and gateway versions differ' warning.

- version.py: resolution chain repo-root VERSION (dev/symlink
  install) -> plugin.yaml version field (production install) ->
  'unknown'; stdlib-only parse, base= param for tests
- plugin.yaml: bump stale version 0.1.0 -> 0.1.2 (matches VERSION)
- scripts/check_version_sync.sh + pre-commit hook: fail commits
  where plugin.yaml drifts from the repo-root VERSION
- tests: regression test simulating the production layout
This commit is contained in:
ARIA committed 2026-08-27 09:33:31 +02:00
1 parent ea375fd88c
commit 0f5b5a16ab
5 files changed
+148 -16

No files matched your search

+40
View File
@@ -486,6 +486,46 @@ async def test_hello_ack_advertises_app_version_and_sse_header_is_stored(
assert device2["caps"].get("app_version") == "9.9.9"
def test_plugin_version_falls_back_to_plugin_yaml_in_production_layout(plugin, tmp_path):
"""Production install (``hermes plugins install <repo>#gateway-plugin``)
ships ONLY the ``gateway-plugin/`` subdirectory into
``~/.hermes/plugins/iris`` — the repo-root ``VERSION`` file is not
present there. The advertised version must then come from
``plugin.yaml``, not "unknown" (regression: the app showed
'Gateway vunknown' against a production gateway)."""
v = plugin.version
# Dev checkout / symlink install: repo-root VERSION is the source of truth.
root_version = Path(v.__file__).resolve().parent.parent / "VERSION"
root_value = root_version.read_text().strip() if root_version.is_file() else ""
if root_value:
assert v.plugin_version() == root_value
# Simulate the production layout: a plugin dir with a plugin.yaml but no
# VERSION file one level up.
prod_dir = tmp_path / "plugins" / "iris"
prod_dir.mkdir(parents=True)
(prod_dir / "plugin.yaml").write_text(
(Path(v.__file__).parent / "plugin.yaml").read_text()
)
advertised = v.plugin_version(base=prod_dir)
assert advertised != "unknown"
# The pre-commit hook (scripts/check_version_sync.sh) keeps plugin.yaml in
# sync with the repo-root VERSION, so the production fallback must
# advertise the same real value.
if root_value:
assert advertised == root_value
# A VERSION file one level up still wins when present.
(tmp_path / "plugins" / "VERSION").write_text("9.9.9\n")
assert v.plugin_version(base=prod_dir) == "9.9.9"
# Nothing at all -> "unknown".
empty = tmp_path / "empty"
empty.mkdir()
assert v.plugin_version(base=empty) == "unknown"
@pytest.mark.asyncio
async def test_disconnect_broadcasts_status_restarting(adapter):
"""Teardown broadcasts ``status{state=restarting}`` before closing the