refactor(cli): extract _finalize_resolve helper, add CNR nightly fallback and pydantic guard
CI / Validate OpenAPI Specification (push) Has been cancelled
CI / Code Quality Checks (push) Has been cancelled
Python Linting / Run Ruff (push) Has been cancelled

- Extract `_finalize_resolve()` to eliminate 7x duplicated uv-compile
  error handling blocks in cm_cli (~-85 lines)
- Move conflict attribution regex to `attribute_conflicts()` in
  unified_dep_resolver.py for direct testability
- Update 4 attribution tests to call production function instead of
  re-implementing regex
- Add CNR nightly fallback: when node is absent from nightly manifest,
  fall back to cnr_map repository URL (glob + legacy)
- Add pydantic Union guard: use getattr for is_unknown in uninstall
  and disable handlers to prevent Union type mismatch
- Add E2E test suites for endpoint install/uninstall and uv-compile
  CLI commands (conflict + success cases)
- Add nightly CNR fallback regression tests
This commit is contained in:
Dr.Lt.Data
2026-03-14 07:57:16 +09:00
parent e0f8e653c7
commit 57eb67f615
9 changed files with 969 additions and 148 deletions
+12 -2
View File
@@ -1417,8 +1417,18 @@ class UnifiedManager:
else: # nightly
repo_url = the_node['repository']
else:
result = ManagedResult('install')
return result.fail(f"Node '{node_id}@{version_spec}' not found in [{channel}, {mode}]")
# Fallback for nightly only: use repository URL from CNR map
# when node is registered in CNR but absent from nightly manifest
if version_spec == 'nightly':
cnr_fallback = self.cnr_map.get(node_id)
if cnr_fallback is not None and cnr_fallback.get('repository'):
repo_url = cnr_fallback['repository']
else:
result = ManagedResult('install')
return result.fail(f"Node '{node_id}@{version_spec}' not found in [{channel}, {mode}]")
else:
result = ManagedResult('install')
return result.fail(f"Node '{node_id}@{version_spec}' not found in [{channel}, {mode}]")
if self.is_enabled(node_id, version_spec):
return ManagedResult('skip').with_target(f"{node_id}@{version_spec}")
+4 -3
View File
@@ -995,7 +995,7 @@ async def task_worker():
return OperationResult.failed.value
node_name = params.node_name
is_unknown = params.is_unknown
is_unknown = getattr(params, 'is_unknown', False) # guard: pydantic Union may match UpdatePackParams
logging.debug(
"[ComfyUI-Manager] Uninstalling node: name=%s, is_unknown=%s",
@@ -1019,15 +1019,16 @@ async def task_worker():
async def do_disable(params: DisablePackParams) -> str:
node_name = params.node_name
is_unknown = getattr(params, 'is_unknown', False) # guard: pydantic Union may match UpdatePackParams
logging.debug(
"[ComfyUI-Manager] Disabling node: name=%s, is_unknown=%s",
node_name,
params.is_unknown,
is_unknown,
)
try:
res = core.unified_manager.unified_disable(node_name, params.is_unknown)
res = core.unified_manager.unified_disable(node_name, is_unknown)
if res:
return OperationResult.success.value