Skip to content

feat(installer): restart only the service units whose version changed - #48

Open
Developer-Simon wants to merge 15 commits into
mainfrom
feat/restart-updated-services
Open

Developer-Simon wants to merge 15 commits into
mainfrom
feat/restart-updated-services

Conversation

@Developer-Simon

Copy link
Copy Markdown
Owner

Squash-merge commit message

feat(installer): restart only the service units whose version changed

A redeploy used to restart every service unit unconditionally. Now it
restarts only the ones whose own version changed, or whose imported
shared library changed (energy_node_common -> every service,
battery_soc_core -> battery_soc alone). Unknown always means restart
(no installed manifest, a missing version, an older manifest without
per-service versions), and a stopped unit is always started regardless
of the rule. The operator can still tick "Restart all services" to get
the old behaviour back, in both the installer and the dashboard's
redeploy page, which share the same web UI.

One rule decides this (scripts/bootstrap/lib/restart_rule.py); the
service steps and plan.sh call it, and the dashboard's Go
updaterhost.Plan carries a copy that both languages test against a
shared JSON table of cases (scripts/bootstrap/testdata/restart_cases.json).
"Restart all" travels as `restart_all` through the installer's
RunRequest and the dashboard's job.json, becoming EN_RESTART=all for
the steps.

Three incidental fixes found while building and testing this on a Pi:

- build_local_wheels() silently killed make_bundle.sh with no error
  message on a checkout that had never built a wheel locally before
  (libs/<lib>/dist/ didn't exist yet; find on a missing directory fails,
  and under set -e/pipefail that propagated into the cached=$(...)
  assignment with the real error thrown away by 2>/dev/null).
- Two lines in the package-preparation log (repo-build announcement,
  device upload/verify) were raw German literals on the plain log
  channel instead of a translation key, so they showed up untranslated
  during an English-language run.
- The "prepare" step ran under the "connect" station in the installer's
  step chain instead of getting its own entry.

Closes #

Summary

Checklist

  • Subject line follows Conventional Commits
    (type(scope): summary) and matches the style in git log.
  • Relevant checks from
    CONTRIBUTING.md → Running the checks
    pass locally (Python bridges, HA integration, Go dashboard, dashboard JS,
    dashboard smoke test — whichever the change touches).
  • ./scripts/deploy/check_tracked_secrets.sh is clean — no real
    credentials, private-range IPs, or device serials.
  • AI assistance, if any, is disclosed per
    AI-DISCLAIMER.md.
  • For anything beyond a small fix: a linked issue describing the change.

Developer-Simon and others added 15 commits September 22, 2026 18:12
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ary changed

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ce steps

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ll switch

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
find on a directory that does not exist yet (a checkout that has never
built a wheel locally before) fails; under set -e and pipefail that
silently kills make_bundle.sh at the cached=$(find ...) assignment with
no error message, because the one message that would explain it is
thrown away by 2>/dev/null. Pre-existing bug, unrelated to the restart-
services work on this branch; found while building a bundle from this
worktree to test that work on a Pi.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Two lines in resolve.go's repo-build path and two in package.go's
upload/verify path were passed as raw German literals to the plain log
channel instead of a translation key on the note channel, so they showed
up untranslated during an English-language run (mixed in among otherwise
correctly localized lines like "Detecting the device's processor
architecture"). Give them catalog keys, following the existing
package.log.* pattern (package.log.extract, .repo_build, .upload,
.verify), and route them through note()/notef() instead of log()/logf().

The raw log() call that streams make_bundle.sh's own stdout is left
untouched -- that is genuine subprocess output, not installer UI text,
and cannot be a catalog key.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Preparing the package (fetching/building it, transferring it to the
device) ran under the "connect" station in the step chain, so the
operator saw "Connection" stay highlighted while a repo build or upload
was actually in progress. Add "prepare" to both FLOW tables, right after
"connect", and drop the special-case mapping that pointed the active
station back at "connect" while on the prepare screen.

It only appears when the screen will actually be visited: bootstrap.package
(the installer's own package selection, shown after connect) or
bootstrap.auto_prepare (the dashboard fetching its package by itself,
shown as the very first screen, connect skipped). Neither existing test
fixture sets either flag, so the five/three-station tests are unaffected;
new tests cover both the installer and dashboard cases where prepare does
show.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…g text

The label text sat inside the .settings-toggle element, which is sized
to fit only the switch itself (2.35rem x 1.32rem, per installer.css) --
the text wrapped inside that fixed box and overlapped the restart list
above it and the "stays as is" text below. Every other .settings-toggle
in this codebase (screen-configure.html's service rows) keeps the label
text as a sibling span outside the switch's own <label>; do the same
here, in a small flex row (.restart-all).

The new rule lives outside the "Aktualisieren" Vorlage block in
screens.css (draft-fidelity.test.mjs holds that block to the design
draft byte for byte) -- it did not exist in the original draft.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The reference drafts (test/reference/*.body.html, the design-fidelity
spec for test/e2e/layout.spec.mjs) still had the old five/four-station
steppers, so CI's browser suite failed once the product started
rendering a real "Vorbereitung" station: Main, Vorpruefung,
Konfiguration, Ausfuehrung, Ergebnis and Aktualisieren all gain it
between Verbindung and the next station, done once past it, renumbering
every station after it. redeploy.spec.mjs's own hardcoded stepper-label
assertion needed the same update.

Per test/reference/README.md ("change a draft here first, in its own
commit, then make the product follow"); the product side already
shipped in feat(webui): give the prepare step its own stepper entry, so
this closes the gap the other way round.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant