fix(manifest_ingest): resolve inherited groupId and ${...} properties in pom.xml (#3806)

(cherry picked from commit 292b9d8465)
This commit is contained in:
Vladimir Babin authored and safishamsi committed 2026-09-25 16:01:47 +01:00
1 parent d197ae36fa
commit cac084cf3d
2 files changed
+65 -4

No files matched your search

+26 -4
View File
@@ -289,17 +289,39 @@ def _parse_pom(text: str) -> dict | None:
text = re.sub(r'\sxmlns="[^"]*"', '', text, count=1)
root = ET.fromstring(text)
aid = root.findtext("artifactId")
gid = root.findtext("groupId")
gid = root.findtext("groupId") or root.findtext("parent/groupId")
version = root.findtext("version") or root.findtext("parent/version")
if not aid:
return None
props: dict[str, str] = {}
for prop in root.findall("properties/*"):
if isinstance(prop.tag, str) and prop.text:
props[prop.tag] = prop.text.strip()
for key, value in (
("project.groupId", gid),
("project.artifactId", aid),
("project.version", version),
("project.parent.groupId", root.findtext("parent/groupId")),
("project.parent.version", root.findtext("parent/version")),
):
if value:
props.setdefault(key, value.strip())
def _resolve(value: str | None) -> str | None:
if not value:
return value
return re.sub(r"\$\{([^}]+)\}", lambda m: props.get(m.group(1), m.group(0)), value.strip())
gid = _resolve(gid)
version = _resolve(version)
name = f"{gid}:{aid}" if gid else aid
deps: list[str] = []
for dep in root.findall(".//dependencies/dependency"):
da = dep.findtext("artifactId")
dg = dep.findtext("groupId")
da = _resolve(dep.findtext("artifactId"))
dg = _resolve(dep.findtext("groupId"))
if da:
deps.append(f"{dg}:{da}" if dg else da)
return {"name": name, "version": root.findtext("version"), "deps": deps}
return {"name": name, "version": version, "deps": deps}
_PARSERS = {
+39
View File
@@ -163,3 +163,42 @@ def test_cargo_workspace_inherited_version_does_not_crash(tmp_path):
'[package]\nname = "member"\nversion.workspace = true\n')
pkg = _pkg_nodes(extract_package_manifest(p))[0]
assert pkg["label"] == "member" and "version" not in pkg
# ── #3806: inherited groupId and ${...} properties in pom.xml ────────────────
def test_pom_inherits_groupid_and_resolves_properties(tmp_path):
_write(tmp_path / "rsc/pom.xml",
'<project xmlns="http://maven.apache.org/POM/4.0.0">\n'
' <parent><groupId>org.acme</groupId><artifactId>main</artifactId><version>1.0</version></parent>\n'
' <groupId>org.acme</groupId>\n <artifactId>acme-rsc</artifactId>\n</project>\n')
_write(tmp_path / "server/pom.xml",
'<project xmlns="http://maven.apache.org/POM/4.0.0">\n'
' <parent><groupId>org.acme</groupId><artifactId>main</artifactId><version>1.0</version></parent>\n'
' <artifactId>acme-server</artifactId>\n'
' <properties><core.suffix>2.12</core.suffix></properties>\n'
' <dependencies>\n'
' <dependency><groupId>${project.groupId}</groupId><artifactId>acme-rsc</artifactId></dependency>\n'
' <dependency><groupId>org.acme</groupId><artifactId>acme-core_${core.suffix}</artifactId></dependency>\n'
' </dependencies>\n</project>\n')
_write(tmp_path / "web/pom.xml",
'<project xmlns="http://maven.apache.org/POM/4.0.0">\n'
' <parent><groupId>org.acme</groupId><artifactId>main</artifactId><version>1.0</version></parent>\n'
' <artifactId>acme-web</artifactId>\n'
' <dependencies>\n'
' <dependency><groupId>org.acme</groupId><artifactId>acme-server</artifactId></dependency>\n'
' </dependencies>\n</project>\n')
server = extract_package_manifest(tmp_path / "server/pom.xml")
pkg = _pkg_nodes(server)[0]
assert pkg["label"] == "org.acme:acme-server" and pkg["version"] == "1.0"
targets = {e["target"] for e in server["edges"] if e["relation"] == "depends_on"}
assert {"pkg_org_acme_acme_rsc", "pkg_org_acme_acme_core_2_12"} <= targets
result = extract(sorted(tmp_path.rglob("pom.xml")), cache_root=tmp_path)
g = build_from_json(result)
labels = {n: d.get("label") for n, d in g.nodes(data=True)}
dep_edges = {frozenset((labels[u], labels[v])) for u, v, d in g.edges(data=True)
if d.get("relation") == "depends_on"}
assert frozenset(("org.acme:acme-server", "org.acme:acme-rsc")) in dep_edges
assert frozenset(("org.acme:acme-web", "org.acme:acme-server")) in dep_edges