Repository navigation
fix(settings): refuse a save that would leave no provider enabled - #1542
Conversation
An empty enabled_providers is contradictory in the backend: the recommendation filters read it as "all" while the scheduler collects nothing. After rebasing the tab's provider changes onto the server's current list, Save now aborts with an error toast before any config or service PUT when the merged list is empty. A save that does not touch the provider checkboxes is unaffected, so a stored empty list can still be left alone while editing other settings. Closes #1531 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Reject empty provider selections frontend/src/settings.ts, frontend/src/__tests__/settings.test.ts, frontend/tests-e2e/settings-save-changed-fields.spec.ts |
The save path shows an error and skips the global settings update when the rebased provider list is empty. Tests cover this behavior, saving with another provider enabled, unrelated edits with an empty stored list, and a provider enabled in the latest server response. |
Priority:
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix · Severity of issue fixed: Medium
Possibly related PRs
- LeanerCloud/cloud-commitments-platform#1487: This PR changes the same settings save path and provider-list write behavior.
Suggested reviewers: iamjsd
Merge Risk: 
Minimal · up to 4db63
-
No merge-blocking risk remains from the reviewed change.
Pre-merge checks: 
5
-
Full details: Linked Issues check
-
Explanation
The PR implements option 1 for
#1531. After rebasing provider changes,saveGlobalSettingsrefuses an emptyenabled_providerslist, showsEnable at least one provider before saving., and returns before config or service updates. The existingfinallypath remains responsible for re-enabling Save. The snapshot is not advanced on this path. The Jest tests cover the single-provider refusal, multi-provider save, stored empty-list unrelated save, and concurrent-provider merge. The Playwright test verifies the toast and zero PUT requests.
Full details: Out of Scope Changes check
-
Explanation
The changes stay within
#1531. They modify the settings save guard and add focused Jest and Playwright coverage for empty-provider behavior. No unrelated backend, API, or public declaration changes are included.
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 1 functions across 3 files.
-
Finishing Touches
-
📝 Generate docstrings
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.
|
Independent review 2 (claude-fleet, cold): APPROVE 4db63f1 Scope: frontend only, frontend/src/settings.ts (+6), plus jest and Playwright tests. I read saveGlobalSettings (frontend/src/settings.ts:3518-3756) to its closing brace. Findings: none blocking.
Attacked:
Verified locally (node_modules cloned from an identical lockfile, under the heavy lock):
Reviewed by an independent agent with no author context (second reviewer). Review only: nothing was pushed, and the GitHub review state is unchanged. |
|
VERDICT: APPROVE 4db63f1 Findings:
Backend claims, checked against the code:
Attacked:
|
|
Local verification at
|
Closes #1531 using option 1 from the issue: refuse an empty selection. What an empty list should mean in the backend stays open for the owner; see the issue comment.
Problem: the backend disagrees with itself about an empty
enabled_providers:config.FilterRecommendationsByEnabledProviderstreats empty as "all" (internal/config/recommendation_enabled_providers.go:7-9). The Opportunities handler, the scan handler and the plan-step resolver all use it.internal/scheduler/scheduler.go:322), so empty means "collect nothing".So an admin who unchecks the last enabled provider stops collection, while stored recommendations from every provider keep showing. #1530's rebase made it easier to send
[]: unchecking the last provider the server still has enabled now sends an empty list.Change (
frontend/src/settings.ts): insaveGlobalSettings, right afterrebaseMultiFieldKeysmerges this tab's checkbox changes onto the server's current list, an emptyenabled_providersaborts the whole save. It shows "Enable at least one provider before saving." and sends no config PUT and no service PUT. The snapshot is untouched, and the existingfinallyre-enables Save. Nothing changes when the providers weren't edited, so a fresh install whose stored default is[]still saves its other settings. There are no API or backend changes.Tests (written first):
settings.test.ts):['aws']and the user unchecks AWS: refused, with the toast, and noupdateConfigorupdateServiceConfigcall;['aws','gcp']and the user unchecks AWS:['gcp']is sent;[]and the user edits an unrelated field: it saves, without anenabled_providerskey;['gcp']keeps the merged list non-empty, so it saves.[]. It now asserts the save resolves without throwing and sends nothing.settings-save-changed-fields.spec.ts, on/admin/generalwhere the provider checkboxes live): uncheck AWS, click Save, then the toast shows and no PUT is sent. It fails on main'ssettings.ts(no toast, also on the retry).Local (macOS):
tsc --noEmitand eslint on the changed files are clean.settings-save-changed-fields.spec.tspasses 3/3, run withCI=1under the shared port lock.SKIP=hadolint,actionlint,zizmor,cfn-lint, because those hooks' environments can't be built locally. CI runs them.🤖 Generated with Claude Code
Summary by CodeRabbit