Files
houseplan-card/docs/DEVELOPMENT.md
T

90 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Development and deployment
## Environment (cowork sessions)
- The source of truth is **GitHub `main`** (https://github.com/Matysh/houseplan-card).
In a sandbox session restore from it or from `houseplan-card.git.bundle`
(`git clone houseplan-card.git.bundle hpcN` into a **fresh** /tmp directory).
- The user's folder `houseplan/houseplan-card/` is a file mirror (synced after every commit)
+ an up-to-date `houseplan-card.git.bundle`. The mount cannot delete files — stale
artifacts linger there; git is authoritative.
- `/tmp` persists between sessions, **but files created in previous sessions belong to
`nobody` and are unreadable** (this hit `/tmp/hpc`, `/tmp/ha_jb`, `/tmp/shots/srv`).
Always clone into a new directory and re-run `npm ci`; ask the user to re-upload `ha_jb`.
- Headless Chromium for smoke tests: `PLAYWRIGHT_BROWSERS_PATH=/tmp/pw npx playwright
install chromium-headless-shell`, then run with `LD_LIBRARY_PATH` pointing to the
extracted lib dirs (`libs/lib/x86_64-linux-gnu:libs/usr/lib/x86_64-linux-gnu:.../nss`).
- Restart HA over SSH with `nohup ha core restart >/dev/null 2>&1 </dev/null &` —
a plain `ha core restart` holds the SSH session until the sandbox call times out.
- GitHub pushes: classic PAT (repo+workflow scopes), created via the user's Chrome;
stored in `~/.git-credentials` for the session.
### ⚠️ File-sync pitfalls (critical)
1. The network mount sometimes serves files **truncated/scrambled** — edits via the Edit tool
from the Windows side are unreliable. Rule: **apply python patches against a clean copy in /tmp,
write via bash**, with an assert that count(old)==1.
2. **Run the rollup build ONLY in /tmp/hpc** (`npm ci` is already done). A build on the mount once
produced a syntactically valid but broken bundle ("wi is not defined") that crashed the rendering
of ALL HA dashboards (the card is loaded as an extra_module on every page!).
3. `.git` cannot be created on the mount ("Operation not permitted" on dot-directories) — hence the bundle.
## Tests
- Frontend: `npm test` — compiles src/logic.ts+rules.ts (tsconfig.test.json) and runs node:test
(test/*.test.mjs). Strict typing: `npm run typecheck` (tsc --noEmit, part of `npm run build`).
- Backend: `python -m pytest tests_backend/` — pure validation of custom_components/houseplan/validation.py
(loaded by path, without importing the HA package).
- IMPORTANT (audit lesson): the rollup typescript plugin reports a syntax error as a WARNING and still
builds the bundle — a truncated file can "pass". That is why the build starts with `tsc --noEmit`,
which fails on such errors. Always build with `npm run build`, never bare `rollup -c`.
## Build
```bash
cd /tmp/hpc && npm ci # once
npx rollup -c # → dist/houseplan-card.js
node --check dist/houseplan-card.js
cp dist/houseplan-card.js custom_components/houseplan/frontend/
```
## Deployment to the dacha (ha.jbstudio.pro)
- SSH: port **323**, root, key `ha_jb` (the user uploads it to the chat; in the sandbox /tmp/ha_jb, chmod 600).
- JS: `scp -P 323 -i /tmp/ha_jb dist/houseplan-card.js root@ha.jbstudio.pro:/config/custom_components/houseplan/frontend/`
- The whole integration: tar c custom_components/houseplan (--exclude __pycache__) → tar x on the server.
- **Verification is mandatory**: `md5sum` locally == on the server == `curl http://homeassistant:8123/houseplan_files/houseplan-card.js | md5sum`
(inside the SSH add-on `localhost` is NOT HA, use the host `homeassistant`).
- Python changes require an HA restart (`ha core restart`, holds the connection until it finishes, HTTP
comes back up in 13 min). JS changes — just a page refresh (the static path is served
with no-cache).
- After deploying JS — check in the browser (Ctrl+F5) and the console (there must be no errors from
houseplan-card.js; a broken bundle takes down all dashboards).
## Frontend cache and the "empty view"
- The card module URL contains `?v=<VERSION from const.py>`. Browsers keep the ES module in
memory cache: after deploying new JS **bump VERSION in const.py and restart HA**,
otherwise a plain F5 will keep the old version.
- After a page reload the HA frontend (with kiosk-mode) sometimes leaves the view empty
("InvalidStateError: Transition was aborted", hui-view is not created for 12 min).
Cured by repeating the SPA navigation: pushState + a location-changed event, or just waiting.
## Release
Tag `vX.Y.Z` + GitHub Release → the workflow `.github/workflows/release.yml` builds and attaches
`houseplan-card.js`. Bump the version everywhere in sync: `src/houseplan-card.ts` (CARD_VERSION),
`package.json`, `custom_components/houseplan/manifest.json`, `custom_components/houseplan/const.py`.
## Reproducible scripts (data)
- Extracting the geometry/backgrounds from the prototype and generating `src/data/*` — see the commit
history and docs/ARCHITECTURE.md (SVG→base-space transforms: f1 0.647/(490,27), f2 0.896/(351,21)).
- Room fitting: render the plan with rectangles overlaid (cv2) → snap to walls → manual fine-tuning.
## Production objects in HA (the dacha)
- Dashboard `plan-doma`, panel view, card `custom:houseplan-card` (icon_size 2.5).
- The houseplan integration: entry loaded, `.storage/houseplan.layout` — the layout (server-side).
- The old prototype `/config/www/houseplan/` (iframe) is kept as a fallback, do not touch.
- configuration.yaml backups: `.bak-avgtemp` (before the average-temperature sensor edit).