From 28186698d065dcf3abeaac72930747fc31522d82 Mon Sep 17 00:00:00 2001 From: Ethanfel Date: Thu, 2 Jul 2026 22:02:01 +0200 Subject: [PATCH] Fix manager install URL normalization --- .../test_generate_popular_node_signatures.py | 33 +++++++++++++++ tools/generate_popular_node_signatures.py | 40 ++++++++++++++----- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/tests/test_generate_popular_node_signatures.py b/tests/test_generate_popular_node_signatures.py index 4c3ef4c..ff448e0 100644 --- a/tests/test_generate_popular_node_signatures.py +++ b/tests/test_generate_popular_node_signatures.py @@ -5563,6 +5563,39 @@ class ManagerIngestionTests(unittest.TestCase): self.assertEqual(42, entries[0]["metrics"]["downloads"]) self.assertEqual("https://github.com/example/reference-nodes.git", entries[1]["repository"]) + def test_normalise_manager_entries_prefers_git_install_files_over_reference(self): + manager_data = { + "custom_nodes": [ + { + "id": "stale-reference", + "title": "Stale Reference", + "reference": "https://github.com/example/stale-or-docs", + "files": ["https://github.com/example/actual-install-repo"], + "install_type": "git-clone", + }, + ] + } + + entries = normalise_manager_entries(manager_data) + + self.assertEqual(1, len(entries)) + self.assertEqual("https://github.com/example/actual-install-repo", entries[0]["repository"]) + + def test_normalise_manager_entries_skips_copy_installs_even_with_github_reference(self): + manager_data = { + "custom_nodes": [ + { + "id": "copy-only", + "title": "Copy Only", + "reference": "https://github.com/example/copy-only-docs", + "files": ["https://raw.githubusercontent.com/example/copy-only/main/node.py"], + "install_type": "copy", + }, + ] + } + + self.assertEqual([], normalise_manager_entries(manager_data)) + def test_rank_packs_uses_popularity_metrics_then_stable_fallbacks(self): packs = [ { diff --git a/tools/generate_popular_node_signatures.py b/tools/generate_popular_node_signatures.py index 08da44e..ec38a8a 100644 --- a/tools/generate_popular_node_signatures.py +++ b/tools/generate_popular_node_signatures.py @@ -169,15 +169,26 @@ def _repository_candidates(item): yield candidate -def _manager_entry_repository(item): - install_type = str(item.get("install_type") or item.get("installType") or "").lower() - candidates = list(_repository_candidates(item)) - if "git" in install_type: - for candidate in candidates: - repository = _normalise_repository_url(candidate) - if repository: - return repository - return None +def _file_candidates(item): + files = item.get("files") + if isinstance(files, str): + yield files + elif isinstance(files, list): + for candidate in files: + yield candidate + + +def _fallback_repository_candidates(item): + for key in ("repository", "repo", "git", "git_url", "url", "reference"): + value = item.get(key) + if isinstance(value, str): + yield value + elif isinstance(value, list): + for candidate in value: + yield candidate + + +def _first_normalised_repository(candidates): for candidate in candidates: repository = _normalise_repository_url(candidate) if repository: @@ -185,6 +196,17 @@ def _manager_entry_repository(item): return None +def _manager_entry_repository(item): + install_type = str(item.get("install_type") or item.get("installType") or "").lower() + if "git" in install_type: + return _first_normalised_repository(_file_candidates(item)) or _first_normalised_repository( + _fallback_repository_candidates(item) + ) + if install_type: + return None + return _first_normalised_repository(_repository_candidates(item)) + + def _entry_metrics(item): metrics = {} sources = [item]