Files
Max Gramser 8a587303d7 Give each screen its own YAML override that survives updates (0.2.61)
Override YAML on a screen edits <name>.local.yaml, a package loaded after
the shared board package. New profiles get an empty one; an existing
profile is attached on the first save without reformatting the file. The
editor validates YAML, refuses the managed sections and substitutions,
and Save & check runs ESPHome's full validation of the complete profile.

The example uses !extend: ESPHome appends package lists instead of
merging them by id, so a bare id added a second display without a
platform and failed the build. An override is 12 KB at most and a
too-large body answers as JSON instead of a bare 413. The sidecar is
written before the profile includes it, and a symlinked sidecar is
refused. Firmware stays 0.2.52.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 08:23:13 +02:00

3.7 KiB

Test results app 0.2.61 / firmware 0.2.52 (2026-09-17)

Max built the Override YAML feature with ChatGPT and asked for a review before release. The feature is app-only: installation_yaml gives every new profile a local_overrides: !include <name>.local.yaml package after the shared board package, Firmware.save_override attaches an existing profile on the first save (spliced into packages: without reformatting the rest), and the page edits the sidecar in a dialog with Save and Save & check (ESPHome config of the complete profile). The review changed four things before release:

  • The example was wrong. ESPHome 2026.6.2 merge_config appends package lists (old + new); it does not merge items by id. display: - id: my_display, model: ST7789V therefore adds a second display without a platform and esphome config fails with "'display' requires a 'platform' key". The example, placeholder and docs now use id: !extend my_display, which edits the display the shared package defines. Checked with the CLI (below).
  • A too-big body was a bare 413. The app accepts 16 KB request bodies; the override allowed 128 KB, so anything in between made aiohttp answer a 413 HTML page and the dialog said "That didn't work". The override is now 12 KB at most, and the guard middleware answers HTTPRequestEntityTooLarge as JSON like every other refusal.
  • Order of writes. The sidecar is written before the profile gets its include, so a profile never points at a file that isn't there. A profile whose packages: is the last section without a trailing newline no longer gets the include glued to its last line.
  • Symlinks. A symlinked <name>.local.yaml is refused for reading and writing; profile() already did that for profiles. The Save & check poller stops when the dialog closes instead of polling /api/firmware for two hours.

Automated

  • Python (.venv-portal): tests/test_overrides.py 11/11 OK: hidden empty sidecar on create, attach without reformatting and survive a reload, attach an existing profile, refuse managed sections / managed substitutions / bad YAML without writing, accept !extend, normalise empty text and a missing newline, refuse 12 KB+, refuse a symlinked sidecar without touching its target, append the include after a packages: section without newline, leave a profile with a foreign local_overrides alone; plus the HTTP round trip (CSRF 403, GET, PUT 200, managed section 400, oversized 413 as JSON, the sidecar stays out of the profile list).
  • Full Python suite: 291 tests, 1 failure in test_tile_icons (light: F0335). That test passes on a clean copy of HEAD; the failure comes from the binary-sensor-words session's uncommitted firmware headers in the shared working tree, not from this change.
  • node --check app.js clean.

ESPHome CLI (2026.6.2)

  • A profile generated by installation_yaml for a CYD, with the remote packages/cyd.yaml from GitHub and an override of display: - id: !extend my_display, model: ST7789V: Configuration is valid, the merged display shows model: ST7789V.
  • Minimal local configs: an empty {} sidecar is valid; a bare id: in the override fails ("requires a 'platform' key"); id: !extend merges into the package's component and a later package wins for scalars (logger.level).

Not tested / for the owner

  • Nothing was flashed and the Home Assistant add-on was not rebuilt locally. In the add-on: open a screen, Override YAML, Use example, Save & check; the status should end in "The complete profile is valid".
  • Existing profiles from before 0.2.61 have no include until the first save; the dialog says so ("Ready to attach").
  • The example changes the display controller. It is right only for a board that really has an ST7789V.