fix(dashboard-api): resolve depends_on for built-in extensions in enable/disable#1713
Open
tang-vu wants to merge 1 commit into
Open
fix(dashboard-api): resolve depends_on for built-in extensions in enable/disable#1713tang-vu wants to merge 1 commit into
tang-vu wants to merge 1 commit into
Conversation
…ble/disable The extensions router's dependency resolution only looked at USER_EXTENSIONS_DIR, while _resolve_extension_dir and _activate_service fully support built-in extensions under EXTENSIONS_DIR. Two consequences for built-in pairs like hermes-proxy (depends_on: [hermes, dashboard-api]): - POST /api/extensions/hermes-proxy/enable with hermes disabled found no manifest in user-extensions, read an empty dep list, and enabled the proxy alone. The merged compose project then declares depends_on on an undefined service, and compose config fails for the whole stack. - POST /api/extensions/hermes/disable scanned only user-extensions for dependents, so it disabled hermes with no warning at all while hermes-proxy stayed enabled -- same stack-wide failure. _read_direct_deps now resolves the manifest user-first, then built-in, matching _resolve_extension_dir's shadowing order, so the existing missing-deps 400 and auto_enable_deps flows work for built-ins. The disable dependents scan covers both directories and only reports peers whose compose.yaml is present: a disabled dependent is unaffected, and warning about it was noise. This mirrors the Linux CLI, which resolves deps from the full service registry and skips disabled dependents. The catalog endpoint already computed dependents across the whole EXTENSION_CATALOG, so the UI showed the relationship the mutation endpoints ignored.
Collaborator
|
Thanks for tightening the dashboard-api enable/disable path around built-in extension dependencies, especially the hermes/hermes-proxy failure mode. Advisory status: looks merge-ready What looks good:
What I checked:
Thanks again for pushing this forward. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The dashboard-api extensions router supports enabling/disabling built-in extensions (
_resolve_extension_dirand_activate_servicehandle theEXTENSIONS_DIR+ host-agent-rename path), but its dependency resolution never did — both_read_direct_depsand the disable-time dependents scan only looked atUSER_EXTENSIONS_DIR.For built-in pairs like
hermes-proxy→depends_on: [hermes, dashboard-api](bothcategory: recommended, both toggleable from the dashboard):POST /api/extensions/hermes-proxy/enablewith hermes disabled finds no manifest under user-extensions, reads an empty dep list, and enables the proxy alone. The merged compose project now hasdepends_onon an undefined service →docker compose configrejects the whole project, soods start/restarttakes down every service, not just the pair.POST /api/extensions/hermes/disablescans only user-extensions for dependents, so it disables hermes with no warning at all while hermes-proxy stays enabled — same stack-wide failure on the next compose operation.This is the dashboard-API sibling of #1712 (Windows CLI) and the same failure mode the Linux CLI already guards against:
ods-cliresolves deps from the full service registry (built-ins included) in both directions.Changes
_read_direct_depsnow resolves the manifest user-first, then built-in, matching_resolve_extension_dir's shadowing order. The existing missing-deps400response andauto_enable_deps=truecascade now work for built-in extensions (activation of built-in deps already worked — it goes through_activate_service→ host-agent rename)._parse_manifest_depsso the disable-time dependents scan reuses the same manifest parsing instead of its inline copy.compose.yamlis present: a disabled dependent is unaffected by the disable, and warning about it was noise. This mirrors the Linux CLI, which skips disabled dependents ([[ ! -f "$dep_cf" ]] && continue).Note: the catalog endpoint already computed
dependentsacross the wholeEXTENSION_CATALOG, so the UI displayed the exact relationship the mutation endpoints ignored.Tests
New cases (all fail on
main, pass with this change):TestBuiltinExtensionDeps::test_enable_builtin_missing_deps_returns_list— enabling a built-in with a disabled built-in dep returns400+missing_dependencies+auto_enable_available.TestBuiltinExtensionDeps::test_enable_builtin_auto_deps—auto_enable_deps=trueactivates the dep first via("activate", dep)host-agent rename, then the target.TestBuiltinExtensionDeps::test_user_manifest_shadows_builtin— a user copy of the same id takes precedence over the built-in manifest.TestDisableExtension::test_disable_warns_about_builtin_dependents— disabling a built-in with an enabled built-in dependent surfacesdependents_warning(the hermes/hermes-proxy shape).TestDisableExtension::test_disable_skips_disabled_dependents— a dependent that is itself disabled no longer triggers the warning.Verification
pytest tests/(dashboard-api): 1175 passed, 9 skipped; the only failures are the 3 pre-existing Windows-host baseline failures (test_setup_sentinel.py×2 bash-dependent,test_user_extensions.py::test_scan_symlink_skipped), identical on cleanmain.ruff check ods/ --select E,F,W --ignore E501,E701,E731,E741,E402: clean.