Everything runs in containers — no host Python, Poetry, or dependencies required.
Lint and test are decoupled from the :dev deploy image (per the fleet Build & Deploy Standard — a check built FROM :dev inherits a stale artifact and goes quietly false). Each ingredient stays fresh on its own: ruff runs mount-only in the luxlint image, mypy on python:3.14-slim with a fresh pip install, and pytest in a lean image built from poetry.lock (Dockerfile.test, rebuilt only when the lock changes) with the working tree over-mounted — so tests always run against current source, never a bake.
make test # pytest (lock-keyed image, source over-mounted)
make lint # luxlint ruff (mount-only) + mypy tail
make check # lint + arch + audit + test + secret scanmake test-e2e proves the whole pipeline — fake Kasa devices → collector → InfluxDB — with zero physical devices and zero published host ports (so it's safe in CI and on a busy host).
make test-e2eWhat it does:
- Builds the collector image from the current source.
- Brings up
compose.e2e.ymlon a bridge network: an ephemeral InfluxDB, a roster of fake Kasa devices (harness/fake_kasa.pyspeaking the real TP-Link IOT protocol) — two emeter plugs (HS110, KP115), a non-emeter plug (HS103), and a 6-outlet power strip (HS300) — and the collector pointed at them viaKASA_COLLECTOR_DEVICE_HOSTS(auto-discovery off, since a bridge network can't broadcast). - Polls InfluxDB and asserts the emeter data for the plugs and the strip lands in the
emetermeasurement, and that the non-emeter plug is handled cleanly (no emeter data, collector stays healthy), then tears everything down.
To emulate other models or more devices, add services to compose.e2e.yml using the harness image and set KASA_FAKE_KIND (plug | plug_noemeter | strip), KASA_FAKE_MODEL, KASA_FAKE_ALIAS, KASA_FAKE_BASE_W, and (for strips) KASA_FAKE_OUTLETS. See harness/README.md and supported-devices.md for the device kinds the emulator covers.
Two self-contained stacks bring up the collector with a bundled, auto-provisioned InfluxDB + Grafana (open http://localhost:3000, admin / admin):
make demo-up— driven by fake devices (the harness emulators), so the dashboards populate with no hardware.make dev-up— driven by your real Kasa devices on the network.
Both build the collector image locally (no registry needed) and stop with make demo-down / make dev-down (add -clean to also drop the data volumes). The dashboards they provision are documented in grafana-dashboards.md.
- deployment.md — production deployment and release flow
- supported-devices.md — device compatibility and the emulator's device kinds