Declarative full-config export / import (GitOps) #23
Labels
No labels
area/ai
area/backend
area/frontend
area/infra
area/scheduler
area/wled
good-first-issue
priority/high
priority/low
priority/medium
type/bug
type/chore
type/ci-cd
type/docs
type/feature
type/qa
v1.0.0
v1.1.0
v1.2.0
v2.0.0
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
rbrooks/Iris-WLED#23
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
Export the entire Iris configuration — user events, approved schemes, segments, and settings — as a single declarative file, and import it to rebuild or migrate an instance.
Why it's valuable
The existing export is WLED-
presets.json-shaped (device state), not Iris state. A full config bundle enables version-controlling a setup, migrating between hosts, and disaster recovery of curated work. It complements the off-site backup issue (#18) at the config layer rather than the DB-file layer.Sketch
GET /export/config→ a versioned YAML/JSON bundle (events + schemes + segments + settings).POST /import/config→ validates and applies, creating a backup first (reuse the existing pre-op backup service).Acceptance criteria
Proposed enhancement (brainstorm follow-up).
Done — #122 merged, CI green.
The round-trip test is weaker than it looks
Worth recording, because the obvious test for this feature does not do what it appears to.
Export → wipe → import → export → compare proves stability (import understands everything export writes) but not completeness. A field missing from the exporter is missing from both bundles, so they still compare equal. I checked this rather than assuming it, by deleting
effect_speedfrom the exporter and watching the round-trip stay green.I had already written the stronger claim into the test's docstring. That is corrected, and completeness is now a separate
TestExportCoveragethat walks the SQLAlchemy columns and fails when a model gains a field the exporter does not carry, with an explicit allow-list of deliberate omissions (surrogate keys, timestamps,stale). Witheffect_speeddeleted, that one fails as it should.This is the third time in this milestone a test has agreed with the code rather than with reality — after the
leds.segsfixture (#62) and the preset mock aliasing (#115).What the bundle excludes, and why
Builtin events regenerate per year, so exporting them adds rows that differ between instances by nothing that matters and conflict on import. Webhooks and the calendar feed token are credentials, and a file whose purpose is to be committed to a repository is the wrong home for those. Logs are history, not configuration.
The feed token is excluded structurally: settings serialise through
RuntimeSettings, and the token is not one of its fields, so there is no path by which it reaches the file even if someone later adds it to the settings table. A test asserts it does not appear.Determinism
Collections sort by a stable key and YAML is emitted with sorted keys. One non-obvious choice: segments sort by name, not
sort_order—sort_orderis itself editable, so sorting by it would reshuffle the whole file whenever someone reordered the UI list, producing a diff that says nothing.Behaviour worth knowing
source: user(#99 promotes on edit), so edited-but-unapproved work is preserved.set_all_settings, so imports get the same validation the API applies rather than a second, looser path.