310c0244df
- Resolve the Hermes gateway API lazily via get_adapter_class() so the adapter
always inherits the real gateway.platforms.base.BasePlatformAdapter instead
of the ImportError fallback stub (root cause of the AttributeError:
'set_message_handler' crash at gateway startup).
- Pass Platform('meshtastic') enum to super().__init__ and align
connect(*, is_reconnect=False) -> bool with the gateway contract.
- Split pure formatting utils into formatting.py; remove the stub fallback.
- Add tests/contract (L0-L3): real-base binding, ABC instantiation, gateway
run.py wiring replay, signature and event-shape conformance, run against
hermes-agent pinned to the deployed image source (v2026.8.31).
- Add scripts/contract-test.sh and a contract-test CI job; release publish
now requires contract tests to pass.
- Untrack stray __pycache__ artifacts.
62 lines
2.3 KiB
Bash
Executable File
62 lines
2.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Gateway contract tests for hermes-meshtastic.
|
|
#
|
|
# Runs the plugin's contract suite (tests/contract/) against the REAL Hermes
|
|
# gateway API, pinned to the same upstream commit the deployed container image
|
|
# is built from (NousResearch/hermes-agent @ v2026.8.31 — the image tag used in
|
|
# k8s-flux apps/base/coder/hermes-agent).
|
|
#
|
|
# Why: the adapter used to be developed by guessing the gateway API and only
|
|
# failing at gateway startup after a release (AttributeError: ... no attribute
|
|
# 'set_message_handler'). These tests replay the gateway's adapter bootstrap
|
|
# (registry registration -> factory -> set_* wiring) so API drift fails here,
|
|
# in seconds, without deploying.
|
|
#
|
|
# Requires: uv (https://docs.astral.sh/uv/) and network on first run.
|
|
#
|
|
# Usage: scripts/contract-test.sh
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
PLUGIN_DIR="$REPO_ROOT/plugin"
|
|
VENV="$PLUGIN_DIR/.venv-contract"
|
|
HERMES_SRC="$PLUGIN_DIR/.hermes-src"
|
|
HERMES_TAG="${HERMES_TAG:-v2026.8.31}" # must match k8s-flux hermes image tag
|
|
HERMES_COMMIT="${HERMES_COMMIT:-29112bef099274229cadff79cdff7bf7b99c4b77}"
|
|
|
|
if ! command -v uv >/dev/null 2>&1; then
|
|
echo "error: uv is required (https://docs.astral.sh/uv/)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -d "$HERMES_SRC/.git" ]; then
|
|
echo "== cloning hermes-agent @ $HERMES_TAG (deployed image source) =="
|
|
git clone --depth 1 --branch "$HERMES_TAG" \
|
|
https://github.com/NousResearch/hermes-agent.git "$HERMES_SRC"
|
|
fi
|
|
actual="$(git -C "$HERMES_SRC" rev-parse HEAD)"
|
|
if [ "$actual" != "$HERMES_COMMIT" ]; then
|
|
echo "error: $HERMES_SRC is at $actual, expected $HERMES_COMMIT ($HERMES_TAG)." >&2
|
|
echo " Refresh deliberately: HERMES_TAG=<new tag> scripts/contract-test.sh" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -x "$VENV/bin/python" ]; then
|
|
echo "== creating contract venv (python 3.13, matching the Hermes image) =="
|
|
uv venv --python 3.13 "$VENV"
|
|
fi
|
|
uv pip install --python "$VENV/bin/python" -q -e "$HERMES_SRC"
|
|
uv pip install --python "$VENV/bin/python" -q pytest
|
|
|
|
echo "== running contract tests (HERMES_CONTRACT_REQUIRED=1) =="
|
|
(
|
|
cd "$PLUGIN_DIR"
|
|
HERMES_CONTRACT_REQUIRED=1 "$VENV/bin/python" -m pytest tests/contract -q "$@"
|
|
)
|
|
|
|
echo "== running standalone unit tests (no gateway needed) =="
|
|
(
|
|
cd "$PLUGIN_DIR"
|
|
"$VENV/bin/python" -m pytest tests/test_adapter.py -q
|
|
)
|