Skip to content

fix(ui): restore per-node installed backend removal - #12785

Merged
mudler merged 6 commits into
masterfrom
fix/installed-per-node-backend-removal
Oct 19, 2026
Merged

mudler merged 6 commits into
masterfrom
fix/installed-per-node-backend-removal

Conversation

@mudler-agent

Copy link
Copy Markdown
Collaborator

Description

Restore confirmed per-node removal of concrete backend builds from Backends → Installed.

Expanded rows load actual node inventory. Removal requires a healthy backend node, an exact concrete name, and explicitly false system/meta protection flags. The confirmation captures the node and build, then rechecks status and inventory before sending one node-scoped request. This does not fan out deletion across nodes.

Keep successful Installed data visible when refresh fails. Distinguish ordinary refresh failures from successful deletion followed by stale data. Refresh retries do not repeat deletion. Block conflicting targeted installs, scoped removals, and generic deletions through pending requests and post-delete refresh, including when navigation clears the target.

Update backend documentation and English strings. This branch is independent of the development-backend preference change in #12782.

Notes for Reviewers

Verification against the final rebuilt UI and re-embedded Go test server:

  • Four focused Playwright suites: 64 passed (36 Installed-removal cases plus existing backend management, lifecycle, and node-action cases):
    npx playwright test e2e/backends-installed-node-removal.spec.js \
      e2e/backends-management.spec.js e2e/backends-lifecycle.spec.js \
      e2e/nodes-per-node-backend-actions.spec.js --workers=1
    Build the UI and tests/e2e-ui server first; configure the mock backend and Chromium as documented by the UI test harness.
  • Scoped ESLint passed for Backends.jsx, useDistributedMode.js, and the new spec.
  • Inline-style gate passed: 199, unchanged baseline. Cumulative diff checks passed.
  • Test-first evidence: initial missing-action regression; review regressions reproduced misleading refresh feedback and install conflicts (4 failed / 2 passed); generic removal boundary tests reproduced 3 failures; targeted-install/generic-delete cases reproduced 2 failures. Final combined run passed all 64.
  • Fresh independent cumulative static review passed after those fixes.

Limitations: full UI/coverage suites were not run. Full ESLint retains two existing errors in unchanged e2e/coverage-fixtures.js:44,53 and existing warnings. An intermediate combined run had 61 passes and one invalid recovery assertion expecting a Remove button after its backend disappeared; the assertion now checks disappearance. No coverage baseline or tolerance changed. Browser tests use synthetic mocked inventory and mutation responses, not real backend deletion. No rollout or live model acceptance test is claimed.

Signed commits

  • Yes, I signed my commits (maintainer-operated DCO sign-off; AI involvement recorded with Assisted-by).
  • Documentation updated (docs/content/features/backends.md).

The coverage script ran ginkgo per test root with `|| fail=1`, which
swallowed the exit code. Combined with `make --output-sync=target`,
which buffers all output and flushes at the end, the actual ginkgo
error was invisible in interleaved CI logs. Every test suite passed
but the script still exited 1, and the error message was buried in
22 000 lines of buffered output.

Each ginkgo invocation now captures combined stdout+stderr to a
per-root log file. On failure the last 80 lines are printed to
stderr so the error is visible in the CI log. On success the log is
replayed to stdout so test output remains visible.

The build flags (--tags, --coverpkg) are quoted correctly so values
containing spaces (e.g. --tags="debug auth") are preserved through
eval.

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
The previous commit added per-root log files but forgot to create
the output directory before the first ginkgo invocation. On CI the
coverage/ dir did not exist yet, so the shell redirect to
cover-pkg.out.log failed with "No such file or directory" before
ginkgo even ran.

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Commit 9ad7838 added GET /api/canvas/preview/:id as a public route
(no auth — the random id is the capability, an iframe cannot send API
key headers) but did not add it to expectedPublicRoutes in the route
auth coverage test. The test flagged the route as an anonymous-access
leak, failing the entire ./core ginkgo suite on every CI run since.

The POST /api/canvas/preview endpoint is auth-gated (returns 401 to
anonymous requests) and is intentionally absent from the allowlist.

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Verify exact node inventory and protection before offering and confirming removal. Capture the node/backend target, guard duplicate requests, and preserve installed data when refresh fails. Reuse the flow for catalog target removal and document scoped retry behavior.

Assisted-by: nib:gpt-6.1-sol

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Distinguish ordinary refresh failures from successful deletion with stale data. Lock target installs synchronously and block conflicting install/removal actions through completion-driven refresh. Cover retry wording, deferred mutation races, obsolete inventory responses, and final installation selection cleanup.

Assisted-by: nib:gpt-6.1-sol

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Keep generic deletion blocked during scoped removal and targeted installs.
Recheck conflicts after dependency lookup and before confirmation so
navigation cannot expose a conflicting delete action.

Assisted-by: nib:gpt-6.1-sol

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
@mudler
mudler merged commit 0de4a7e into master Oct 19, 2026
21 of 23 checks passed
@mudler
mudler deleted the fix/installed-per-node-backend-removal branch October 19, 2026 21:36
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.

2 participants