Skip to content

Commit 921b1d2

Browse files
Merge main into expand/collapse-all branch
Resolve conflicts in instrumentation-browser, schema-renderer and configuration-builder-page: keep the SectionExpansionProvider/toolbar wiring while adopting the i18n labels introduced on main.
2 parents cef551f + ed54c00 commit 921b1d2

132 files changed

Lines changed: 39355 additions & 870 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ecosystem-automation/collector-watcher/src/collector_watcher/schema_copier.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import shutil
2626
from pathlib import Path
2727

28+
import yaml
2829
from watcher_common.content_hashing import compute_content_hash
2930

3031
logger = logging.getLogger(__name__)
@@ -44,7 +45,8 @@ def store_schema(self, repo_path: Path, schemas_dir: Path) -> str | None:
4445
The destination is ``schemas_dir / f"{schema_hash}.yaml"``. If a file
4546
with that name already exists (because the same schema content was
4647
stored previously), the copy is skipped — the existing file is the
47-
canonical record. Returns the schema hash on success.
48+
canonical record. Returns the schema hash on success. The schema hash
49+
is computed from the normalized YAML content (ignoring comments and key order).
4850
4951
Args:
5052
repo_path: Path to the checked-out collector repository.
@@ -61,7 +63,7 @@ def store_schema(self, repo_path: Path, schemas_dir: Path) -> str | None:
6163
logger.debug("Schema file not found in repo at %s, skipping store", src)
6264
return None
6365

64-
schema_hash = compute_content_hash(src.read_bytes())
66+
schema_hash = self.compute_schema_hash(src)
6567
dst = schemas_dir / f"{schema_hash}.yaml"
6668
if dst.exists():
6769
logger.debug("Schema %s already stored at %s, skipping copy", schema_hash, dst)
@@ -74,8 +76,9 @@ def store_schema(self, repo_path: Path, schemas_dir: Path) -> str | None:
7476

7577
def compute_schema_hash(self, schema_path: Path) -> str:
7678
"""
77-
Compute the content hash of a schema file.
79+
Compute the content hash of a schema file, ignoring comments and formatting.
7880
81+
The hash is computed from the normalized YAML representation of the schema.
7982
Returns ``UNKNOWN_HASH`` when the file is absent — used by component
8083
YAMLs scanned from older collector tags that pre-date the schema file.
8184
@@ -87,4 +90,8 @@ def compute_schema_hash(self, schema_path: Path) -> str:
8790
"""
8891
if not schema_path.exists():
8992
return UNKNOWN_HASH
90-
return compute_content_hash(schema_path.read_bytes())
93+
94+
with open(schema_path, "r", encoding="utf-8") as f:
95+
data = yaml.safe_load(f)
96+
normalized_yaml = yaml.safe_dump(data, sort_keys=True)
97+
return compute_content_hash(normalized_yaml)

ecosystem-automation/collector-watcher/tests/test_schema_copier.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from pathlib import Path
2121

2222
import pytest
23+
import yaml
2324
from collector_watcher.schema_copier import (
2425
SCHEMA_RELATIVE_PATH,
2526
UNKNOWN_HASH,
@@ -75,7 +76,10 @@ def test_store_schema_returns_hash_matching_content(fake_repo, schemas_dir):
7576
schema_hash = copier.store_schema(fake_repo, schemas_dir)
7677

7778
src = fake_repo / SCHEMA_RELATIVE_PATH
78-
expected = hashlib.sha256(src.read_bytes()).hexdigest()[:12]
79+
with open(src, "r", encoding="utf-8") as f:
80+
data = yaml.safe_load(f)
81+
normalized = yaml.safe_dump(data, sort_keys=True)
82+
expected = hashlib.sha256(normalized.encode("utf-8")).hexdigest()[:12]
7983
assert schema_hash == expected
8084

8185

@@ -169,7 +173,10 @@ def test_compute_schema_hash_matches_sha256(fake_repo):
169173
copier = CollectorSchemaCopier()
170174
result = copier.compute_schema_hash(schema_path)
171175

172-
expected = hashlib.sha256(schema_path.read_bytes()).hexdigest()[:12]
176+
with open(schema_path, "r", encoding="utf-8") as f:
177+
data = yaml.safe_load(f)
178+
normalized = yaml.safe_dump(data, sort_keys=True)
179+
expected = hashlib.sha256(normalized.encode("utf-8")).hexdigest()[:12]
173180
assert result == expected
174181

175182

@@ -201,6 +208,20 @@ def test_compute_schema_hash_returns_unknown_when_absent(temp_dir):
201208
assert result == UNKNOWN_HASH
202209

203210

211+
def test_compute_schema_hash_ignores_comments(fake_repo):
212+
schema_path = fake_repo / SCHEMA_RELATIVE_PATH
213+
copier = CollectorSchemaCopier()
214+
215+
h1 = copier.compute_schema_hash(schema_path)
216+
217+
content = schema_path.read_text(encoding="utf-8")
218+
content_with_comments = f"# This is a comment\n{content}\n# Another comment\n"
219+
schema_path.write_text(content_with_comments, encoding="utf-8")
220+
221+
h2 = copier.compute_schema_hash(schema_path)
222+
assert h1 == h2
223+
224+
204225
# ---------------------------------------------------------------------------
205226
# Round-trip: store then hash the stored copy
206227
# ---------------------------------------------------------------------------

ecosystem-automation/explorer-db-builder/src/explorer_db_builder/declarative_name_corrections.py

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,55 @@ def apply_declarative_name_corrections(inventory: dict[str, Any]) -> dict[str, A
5151
for config in item.get("configurations") or []:
5252
if not isinstance(config, dict):
5353
continue
54-
current = config.get("declarative_name")
55-
corrected = DECLARATIVE_NAME_CORRECTIONS.get(current)
54+
original_name = config.get("declarative_name")
55+
corrected = DECLARATIVE_NAME_CORRECTIONS.get(original_name)
56+
5657
if corrected is not None:
5758
config["declarative_name"] = corrected
5859
logger.debug(
5960
"Corrected declarative_name %r -> %r for config %r",
60-
current,
61+
original_name,
6162
corrected,
6263
config.get("name"),
6364
)
6465

66+
current_name = config.get("declarative_name")
67+
if current_name == "java.common.service_peer_mapping":
68+
config["declarative_type"] = "structured_list"
69+
config["declarative_schema"] = {
70+
"type": "object",
71+
"required": ["peer", "service_name"],
72+
"properties": {
73+
"peer": {
74+
"type": "string",
75+
"description": "Host name or IP address to match against."
76+
},
77+
"service_name": {
78+
"type": "string",
79+
"description": "Peer service name to record for matching peers.",
80+
},
81+
},
82+
}
83+
elif current_name and current_name.endswith("url_template_rules"):
84+
config["declarative_type"] = "structured_list"
85+
config["declarative_schema"] = {
86+
"type": "object",
87+
"required": ["pattern", "template"],
88+
"properties": {
89+
"pattern": {
90+
"type": "string",
91+
"description": "Regular expression matched against the request URL.",
92+
},
93+
"template": {
94+
"type": "string",
95+
"description": "Template used to derive the low-cardinality route.",
96+
},
97+
"override": {
98+
"type": "boolean",
99+
"default": False,
100+
"description": "Whether this rule overrides an already-applied template.",
101+
},
102+
},
103+
}
104+
65105
return inventory

ecosystem-automation/explorer-db-builder/tests/test_declarative_name_corrections.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,47 @@ def test_config_without_declarative_name_is_ignored(self):
110110
apply_declarative_name_corrections(inventory)
111111

112112
assert "declarative_name" not in inventory["libraries"][0]["configurations"][0]
113+
114+
def test_injects_structured_list_schema_for_service_peer_mapping(self):
115+
"""java.common.service_peer_mapping receives a structured_list schema injection."""
116+
inventory = {
117+
"libraries": [
118+
{
119+
"name": "some-lib",
120+
"configurations": [
121+
{"declarative_name": "java.common.service_peer_mapping"}
122+
],
123+
}
124+
]
125+
}
126+
127+
apply_declarative_name_corrections(inventory)
128+
129+
config = inventory["libraries"][0]["configurations"][0]
130+
assert config["declarative_type"] == "structured_list"
131+
assert config["declarative_schema"]["type"] == "object"
132+
assert "peer" in config["declarative_schema"]["required"]
133+
assert "service_name" in config["declarative_schema"]["required"]
134+
135+
def test_injects_structured_list_schema_for_url_template_rules(self):
136+
"""url_template_rules receives a structured_list schema injection."""
137+
inventory = {
138+
"libraries": [
139+
{
140+
"name": "some-lib",
141+
"configurations": [
142+
{"declarative_name": "some.prefix.url_template_rules"}
143+
],
144+
}
145+
]
146+
}
147+
148+
apply_declarative_name_corrections(inventory)
149+
150+
config = inventory["libraries"][0]["configurations"][0]
151+
assert config["declarative_type"] == "structured_list"
152+
assert config["declarative_schema"]["type"] == "object"
153+
assert "pattern" in config["declarative_schema"]["required"]
154+
assert "template" in config["declarative_schema"]["required"]
155+
assert "override" in config["declarative_schema"]["properties"]
156+

0 commit comments

Comments
 (0)