HA config-sync: two-way (push live /config changes back as a PR) #91

Merged
k.renner merged 1 commits from feat-config-sync-two-way into master 2026-06-29 22:02:54 +00:00
Owner

What

Flips the config-sync sidecar from one-way (git → /config, force-overwrite) to two-way, per request: changes made inside Home Assistant (code-server, or the UI automation/script editors that write automations.yaml/scripts.yaml) are now pushed back to the repo.

Behavior

  • Push — each cycle, changes to the tracked config paths are committed (bot identity HA Config Sync) onto a dedicated live branch, pushed, and a PR live → main is kept open for review (created via the gitea token already embedded in the PVC's remote URL — no new secret). Your live edits stay live and are captured for review.
  • Pull — when main advances (you merge the live PR, or push from elsewhere), the commits are merged back into live/the working tree and HA reloads.
  • Conflicts → git — a merge that conflicts is aborted (never written into the live files, which would break HA) and logged to resolve in the PR. No silent discards.
  • Reload — fires only on changes pulled from main; your own local edits are already applied by HA (a plain code-server file edit would need a manual reload). Also fixes the reload race: reload_all now retries until HA is serving (the previous one-shot lost the race right after a pod start).

Scope unchanged: only the config paths (incl. the bespoke www/heizungsanlage-card.js); the rest of www/ (HACS) and untracked runtime state (.storage/, DB, secrets) are untouched. Auto-gc still disabled.

Rollout / notes

  • After merge, needs a one-time kubectl rollout restart deploy/home-assistant -n home-assistant (stable-name script ConfigMap). On first start the sidecar moves /config onto the live branch (no working-tree change).
  • Pushes go to live + a PR, never force-pushing main — so it respects any main protection; you stay the merge gatekeeper.
  • Known edge: if a future main commit changes an www/community/* (HACS) file while /config has the usual HACS drift there, the merge will refuse and log — resolve by reconciling that path. (No such changes happen today.)

Validated: sh -n, kubectl kustomize, and the remote-URL→token/host/repo parsing. Not deployed — Flux rolls on merge.

🤖 Generated with Claude Code

## What Flips the `config-sync` sidecar from **one-way** (git → /config, force-overwrite) to **two-way**, per request: changes made *inside* Home Assistant (code-server, or the UI automation/script editors that write `automations.yaml`/`scripts.yaml`) are now pushed back to the repo. ## Behavior - **Push** — each cycle, changes to the tracked config paths are committed (bot identity `HA Config Sync`) onto a dedicated **`live`** branch, pushed, and a PR **`live → main`** is kept open for review (created via the gitea token already embedded in the PVC's remote URL — no new secret). Your live edits **stay live** and are captured for review. - **Pull** — when `main` advances (you merge the live PR, or push from elsewhere), the commits are merged back into `live`/the working tree and HA reloads. - **Conflicts → git** — a merge that conflicts is **aborted** (never written into the live files, which would break HA) and logged to resolve in the PR. No silent discards. - **Reload** — fires only on changes pulled *from* main; your own local edits are already applied by HA (a plain code-server file edit would need a manual reload). Also **fixes the reload race**: `reload_all` now retries until HA is serving (the previous one-shot lost the race right after a pod start). Scope unchanged: only the config paths (incl. the bespoke `www/heizungsanlage-card.js`); the rest of `www/` (HACS) and untracked runtime state (`.storage/`, DB, secrets) are untouched. Auto-gc still disabled. ## Rollout / notes - After merge, needs a one-time `kubectl rollout restart deploy/home-assistant -n home-assistant` (stable-name script ConfigMap). On first start the sidecar moves `/config` onto the `live` branch (no working-tree change). - Pushes go to `live` + a PR, never force-pushing `main` — so it respects any `main` protection; you stay the merge gatekeeper. - Known edge: if a future `main` commit changes an `www/community/*` (HACS) file while /config has the usual HACS drift there, the merge will refuse and log — resolve by reconciling that path. (No such changes happen today.) Validated: `sh -n`, `kubectl kustomize`, and the remote-URL→token/host/repo parsing. Not deployed — Flux rolls on merge. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
k.renner added 1 commit 2026-06-29 22:00:02 +00:00
The sidecar was one-way and git-authoritative: it force-overwrote local edits to
the synced config paths, so changes made inside HA (code-server, the UI
automation/script editors) were reverted on the next tick.

Now it is two-way:
- PUSH: changes to the tracked config paths are committed (bot identity) onto a
  dedicated `live` branch, pushed, and a PR `live -> main` is kept open (via the
  gitea token already in the remote URL). Live edits stay live AND are captured
  for review.
- PULL: when `main` advances (merged PR / external push) the commits are merged
  back into `live`/the working tree and HA reloads.

Conflicts are left to git: a conflicting merge is ABORTED (never written into the
live files, which would break HA) and logged to resolve in the PR. Reloads fire
only on changes pulled from main (local edits are already applied by HA).

Also fixes the reload race: reload_all now retries until HA is serving, instead
of failing once right after a pod start. Scope unchanged (config paths only; rest
of www/ and untracked runtime state untouched); auto-gc still disabled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgbyKgrN1yYWrkAA32rJE5
k.renner merged commit 72dba58390 into master 2026-06-29 22:02:54 +00:00
Sign in to join this conversation.