From 1deb31f8498e4396075957352bcf751094ac5d16 Mon Sep 17 00:00:00 2001 From: Jeppe Fredsgaard Blaabjerg Date: Thu, 12 Nov 2026 13:09:30 +0100 Subject: [PATCH 1/2] fix(manifest): resolve Maven modules inside their class realm Maven resolves a project inside its class realm, where the artifact types its build extensions define are visible (LifecycleDependencyResolver). The facts extension resolved each module after the build, outside that realm, so such a type fell back to Maven's default handler: a type that includes its dependencies was traversed anyway, and its file extension was wrong for --with-files. Each module is now resolved inside its project's class realm. Resolves REA-1163. --- CHANGELOG.md | 5 ++ .../socket/SocketFactsRecordsEngine.java | 10 ++- .../scripts/test/maven-compat/.gitignore | 3 + .../test/maven-compat/extension-type/pom.xml | 55 +++++++++++++ .../maven-compat/smoke-test-extension-type.sh | 78 +++++++++++++++++++ .../manifest/scripts/test/run-compat.sh | 1 + 6 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 src/commands/manifest/scripts/test/maven-compat/extension-type/pom.xml create mode 100755 src/commands/manifest/scripts/test/maven-compat/smoke-test-extension-type.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a75f087f..76b080c6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## [Unreleased] + +### Fixed +- Maven Socket facts honor artifact types that build extensions define, so they no longer list dependencies Maven doesn't resolve, or fetch files under the wrong extension. + ## [1.15.0](https://github.com/SocketDev/socket-cli/releases/tag/v1.15.0) - 2026-11-12 ### Added diff --git a/src/commands/manifest/scripts/maven-extension/src/main/java/tech/coana/socket/SocketFactsRecordsEngine.java b/src/commands/manifest/scripts/maven-extension/src/main/java/tech/coana/socket/SocketFactsRecordsEngine.java index 14e098e1e..725cede43 100644 --- a/src/commands/manifest/scripts/maven-extension/src/main/java/tech/coana/socket/SocketFactsRecordsEngine.java +++ b/src/commands/manifest/scripts/maven-extension/src/main/java/tech/coana/socket/SocketFactsRecordsEngine.java @@ -168,7 +168,15 @@ public void run(MavenSession session, List reactor, File rootDir, if (SocketSupport.isExcludedDir(excludeBase, module.getBasedir().toPath(), excludes)) continue; Map nodes = new LinkedHashMap<>(); Set directIds = new HashSet<>(); - collectModule(session, module, passingScopes, reactorGavs, populateGavs, opts, nodes, directIds, failures, unscannable); + // As in Maven's LifecycleDependencyResolver: artifact types the build extensions contribute are + // only found from inside the project's class realm. + ClassLoader previous = Thread.currentThread().getContextClassLoader(); + if (module.getClassRealm() != null) Thread.currentThread().setContextClassLoader(module.getClassRealm()); + try { + collectModule(session, module, passingScopes, reactorGavs, populateGavs, opts, nodes, directIds, failures, unscannable); + } finally { + Thread.currentThread().setContextClassLoader(previous); + } rootIdx = emitModuleRoots(lines, rootIdx, projectKey(module), nodes, directIds); } diff --git a/src/commands/manifest/scripts/test/maven-compat/.gitignore b/src/commands/manifest/scripts/test/maven-compat/.gitignore index eca432613..8c20122e9 100644 --- a/src/commands/manifest/scripts/test/maven-compat/.gitignore +++ b/src/commands/manifest/scripts/test/maven-compat/.gitignore @@ -19,3 +19,6 @@ descriptor-failure/*/target/ unsolvable-conflict/records.tsv unsolvable-conflict/target/ unsolvable-conflict/localrepo/ +extension-type/localrepo/ +extension-type/records.tsv +extension-type/target/ diff --git a/src/commands/manifest/scripts/test/maven-compat/extension-type/pom.xml b/src/commands/manifest/scripts/test/maven-compat/extension-type/pom.xml new file mode 100644 index 000000000..86e622b6f --- /dev/null +++ b/src/commands/manifest/scripts/test/maven-compat/extension-type/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + demo + extension-type + 1.0 + + file://${maven.multiModuleProjectDirectory}/localrepo + + + + socket-stubs + ${stub.repo.url} + + true + ignore + + + false + + + + + + socket-stubs + ${stub.repo.url} + + true + ignore + + + false + + + + + + + demo.ext + fat + 1.0 + fat + + + + + + demo.ext + types-ext + 1.0 + + + + diff --git a/src/commands/manifest/scripts/test/maven-compat/smoke-test-extension-type.sh b/src/commands/manifest/scripts/test/maven-compat/smoke-test-extension-type.sh new file mode 100755 index 000000000..ea9057b4f --- /dev/null +++ b/src/commands/manifest/scripts/test/maven-compat/smoke-test-extension-type.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +# Regression guard: an artifact type a build extension defines must apply as it does in Maven's own +# resolution. Type fat, from the types-ext extension, includes its dependencies and is a jar on disk, +# so demo.ext:inner below demo.ext:fat must not be emitted, and --with-files must fetch fat-1.0.jar. +# +# Usage: smoke-test-extension-type.sh +set -euo pipefail +HERE="$(cd "$(dirname "$0")" && pwd)" +MVN="${1:?usage: smoke-test-extension-type.sh }" +JAR="${2:?usage: smoke-test-extension-type.sh }" +PROJECT="$HERE/extension-type" +RECORDS="$PROJECT/records.tsv" +STUBS="$PROJECT/localrepo" +# shellcheck source=SCRIPTDIR/../compat-cache.sh +. "$HERE/../compat-cache.sh" +M2="$SOCKET_COMPAT_CACHE/m2" + +bash "$HERE/../make-stub-repo.sh" "$STUBS" \ + 'demo.ext:types-ext:1.0' \ + 'demo.ext:fat:1.0+demo.ext:inner:1.0' \ + 'demo.ext:inner:1.0' +# The extension is a components.xml registering Maven's own handler class for type fat. +EXT_DIR="$(mktemp -d)" +trap 'rm -rf "$EXT_DIR"' EXIT +mkdir -p "$EXT_DIR/META-INF/plexus" +cat > "$EXT_DIR/META-INF/plexus/components.xml" <<'XML' + + + + org.apache.maven.artifact.handler.ArtifactHandler + fat + org.apache.maven.artifact.handler.DefaultArtifactHandler + + fat + jar + java + true + true + + + + +XML +( cd "$EXT_DIR" && jar cf "$STUBS/demo/ext/types-ext/1.0/types-ext-1.0.jar" META-INF ) +rm -rf "$M2/demo/ext/types-ext" "$M2/demo/ext/fat" "$M2/demo/ext/inner" "$RECORDS" + +echo "+ $("$MVN" -v 2>/dev/null | head -1) (extension type)" +( cd "$PROJECT" && "$MVN" --batch-mode -q \ + "-Dmaven.ext.class.path=$JAR" \ + -Dcoana.task=socket-facts \ + -Dsocket.withFiles=true \ + "-Dmaven.repo.local=$M2" \ + "-Dstub.repo.url=file://$STUBS" \ + "-Dsocket.recordsFile=$RECORDS" \ + validate ) + +python3 - "$RECORDS" <<'PY' +import sys +rows = [l.rstrip('\n').split('\t') for l in open(sys.argv[1]) if l.strip()] +nodes = {r[2] for r in rows if r[0] == 'node'} +files = {r[3] for r in rows if r[0] == 'file' and r[2].startswith('demo.ext:fat:')} +failures = [r[1:] for r in rows if r[0] in ('failure', 'unscannable')] +errors = [] +if not any(n.startswith('demo.ext:fat:') for n in nodes): + errors.append(f"demo.ext:fat missing; nodes={sorted(nodes)}") +if any(n.startswith('demo.ext:inner:') for n in nodes): + errors.append("demo.ext:inner emitted, though type fat includes its dependencies") +if not any(p.endswith('fat-1.0.jar') for p in files): + errors.append(f"fat-1.0.jar not materialized; files={sorted(files)}") +if failures: + errors.append(f"no failures expected; got {failures}") +if errors: + print("FAIL:") + for e in errors: + print(" -", e) + sys.exit(1) +print("PASS (extension type): fat emitted as a jar, inner not resolved below it") +PY diff --git a/src/commands/manifest/scripts/test/run-compat.sh b/src/commands/manifest/scripts/test/run-compat.sh index 3e503016e..e21ded508 100755 --- a/src/commands/manifest/scripts/test/run-compat.sh +++ b/src/commands/manifest/scripts/test/run-compat.sh @@ -118,6 +118,7 @@ run_maven() { bash "$HERE/maven-compat/smoke-test-graph-failure.sh" "$dir/bin/mvn" "$jar" bash "$HERE/maven-compat/smoke-test-descriptor-failure.sh" "$dir/bin/mvn" "$jar" bash "$HERE/maven-compat/smoke-test-unsolvable-conflict.sh" "$dir/bin/mvn" "$jar" + bash "$HERE/maven-compat/smoke-test-extension-type.sh" "$dir/bin/mvn" "$jar" done } From 33e37f47183b5cb30f957b789f53db3216f24e48 Mon Sep 17 00:00:00 2001 From: Jeppe Fredsgaard Blaabjerg Date: Thu, 12 Nov 2026 16:47:53 +0100 Subject: [PATCH 2/2] test(manifest): keep only the artifact type fields the realm test relies on --- .../main/java/tech/coana/socket/SocketFactsRecordsEngine.java | 4 ++-- .../scripts/test/maven-compat/smoke-test-extension-type.sh | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/commands/manifest/scripts/maven-extension/src/main/java/tech/coana/socket/SocketFactsRecordsEngine.java b/src/commands/manifest/scripts/maven-extension/src/main/java/tech/coana/socket/SocketFactsRecordsEngine.java index 725cede43..0400d7680 100644 --- a/src/commands/manifest/scripts/maven-extension/src/main/java/tech/coana/socket/SocketFactsRecordsEngine.java +++ b/src/commands/manifest/scripts/maven-extension/src/main/java/tech/coana/socket/SocketFactsRecordsEngine.java @@ -168,8 +168,6 @@ public void run(MavenSession session, List reactor, File rootDir, if (SocketSupport.isExcludedDir(excludeBase, module.getBasedir().toPath(), excludes)) continue; Map nodes = new LinkedHashMap<>(); Set directIds = new HashSet<>(); - // As in Maven's LifecycleDependencyResolver: artifact types the build extensions contribute are - // only found from inside the project's class realm. ClassLoader previous = Thread.currentThread().getContextClassLoader(); if (module.getClassRealm() != null) Thread.currentThread().setContextClassLoader(module.getClassRealm()); try { @@ -194,6 +192,8 @@ private static String projectKey(MavenProject module) { // ---- resolution ---- + // Run inside the module's class realm, as Maven's LifecycleDependencyResolver does: artifact types + // the build extensions contribute are only found from there. private void collectModule( MavenSession session, MavenProject module, diff --git a/src/commands/manifest/scripts/test/maven-compat/smoke-test-extension-type.sh b/src/commands/manifest/scripts/test/maven-compat/smoke-test-extension-type.sh index ea9057b4f..b941c41f6 100755 --- a/src/commands/manifest/scripts/test/maven-compat/smoke-test-extension-type.sh +++ b/src/commands/manifest/scripts/test/maven-compat/smoke-test-extension-type.sh @@ -33,9 +33,7 @@ cat > "$EXT_DIR/META-INF/plexus/components.xml" <<'XML' fat jar - java true - true