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..bdf677ef7 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
@@ -53,7 +53,7 @@
* (same contract as the Gradle/SBT scripts; no JSON/hashing here). Per module: a test root with the
* whole resolution and a compile root with the nodes kept with a prod scope (compile/runtime/system),
* each with the resolved edges between its own nodes. A reactor module becomes a component only
- * where another depends on it, by its bare {@code groupId:artifactId:version} id.
+ * where another depends on one of its artifacts, each of which names the module as its project.
*
*
Resolution goes through {@link ProjectDependenciesResolver} — the same component Maven's own
* lifecycle uses to build a project's classpath — so the graph, the scope and management semantics,
@@ -309,9 +309,8 @@ private void collectModule(
reportUnscannable(unscannable, moduleCoord, "dependencies resolved without the socket-facts graph transformer");
}
if (graph == null) return;
- Set visited = new HashSet<>();
for (DependencyNode child : edges.get(graph)) {
- String id = visit(child, edges, passingScopes, reactorGavs, unresolved, opts, nodes, visited);
+ String id = visit(child, edges, passingScopes, reactorGavs, unresolved, opts, nodes);
if (id != null) directIds.add(id);
}
for (String id : unfetched) {
@@ -410,8 +409,7 @@ private String visit(
Set reactorGavs,
Set unresolved,
Options opts,
- Map nodes,
- Set visited) {
+ Map nodes) {
Dependency dep = dn.getDependency();
Artifact artifact = dn.getArtifact();
if (dep == null || artifact == null) return null;
@@ -423,20 +421,17 @@ private String visit(
boolean internal = reactorGavs.contains(gav);
String type = artifact.getProperty(ARTIFACT_PROPERTY_TYPE, artifact.getExtension());
String classifier = artifact.getClassifier();
- String version = artifact.getBaseVersion();
- String key = externalId(artifact);
- String id = internal ? SocketSupport.bareId(artifact.getGroupId(), artifact.getArtifactId(), version) : key;
+ String id = externalId(artifact);
- // One walk per artifact: a shared subtree is already recorded. Keyed by coordinate, as a sibling's jar
- // and test-jar share a node but can collect different children, e.g. when one declaration has exclusions.
- if (!visited.add(key)) return id;
+ // One walk per artifact: a shared subtree is already recorded.
+ if (nodes.containsKey(id)) return id;
- Node node = internal
- ? upsert(nodes, id, artifact.getGroupId(), artifact.getArtifactId(), "", "", version, gav)
- : upsert(nodes, id, artifact.getGroupId(), artifact.getArtifactId(),
- type == null ? "" : type, classifier == null ? "" : classifier, version, "");
- // A sibling's jar and test-jar share a node, each kept with its own scope.
- if (isProd(scope)) node.prod = true;
+ // A sibling module's artifacts, such as its jar and test-jar, name the module as their project; the
+ // assembler merges them into its component.
+ Node node = new Node(id, artifact.getGroupId(), artifact.getArtifactId(),
+ type == null ? "" : type, classifier == null ? "" : classifier, artifact.getBaseVersion(), internal ? gav : "");
+ node.prod = isProd(scope);
+ nodes.put(id, node);
// Maven wrote each accepted node's resolved file back onto the node; a reactor module reports its
// own dirs through its `project` record instead of a `file` record.
@@ -446,7 +441,7 @@ private String visit(
}
for (DependencyNode child : edges.get(dn)) {
- String childId = visit(child, edges, passingScopes, reactorGavs, unresolved, opts, nodes, visited);
+ String childId = visit(child, edges, passingScopes, reactorGavs, unresolved, opts, nodes);
if (childId != null) node.children.add(childId);
}
return id;
@@ -476,17 +471,6 @@ private static boolean isProd(String scope) {
return scope.equals("compile") || scope.equals("runtime") || scope.equals("system");
}
- private static Node upsert(
- Map nodes, String id, String groupId, String artifactId, String type, String classifier, String version,
- String project) {
- Node node = nodes.get(id);
- if (node == null) {
- node = new Node(id, groupId, artifactId, type, classifier, version, project);
- nodes.put(id, node);
- }
- return node;
- }
-
// ---- emission ----
// Shaped like Gradle's runtime and test classpaths. An edge from a prod node onto a dev one, such as
diff --git a/src/commands/manifest/scripts/maven-extension/src/main/java/tech/coana/socket/SocketSupport.java b/src/commands/manifest/scripts/maven-extension/src/main/java/tech/coana/socket/SocketSupport.java
index e14b981af..12d68a11c 100644
--- a/src/commands/manifest/scripts/maven-extension/src/main/java/tech/coana/socket/SocketSupport.java
+++ b/src/commands/manifest/scripts/maven-extension/src/main/java/tech/coana/socket/SocketSupport.java
@@ -38,11 +38,6 @@ public static String coordId(String groupId, String artifactId, String type, Str
return sb.toString();
}
- /** Bare {@code groupId:artifactId:version} id used for reactor (internal) module components. */
- public static String bareId(String groupId, String artifactId, String version) {
- return coordId(groupId, artifactId, null, null, version);
- }
-
/**
* Translate a config-name glob to a case-sensitive regex. Supports {@code *}, {@code ?}, and
* {@code [...]} character classes: enumerations ({@code [cC]}), ranges ({@code [a-z]}), and
diff --git a/src/commands/manifest/scripts/test/maven-compat/assert-records.py b/src/commands/manifest/scripts/test/maven-compat/assert-records.py
index 66e8e374f..1275559c0 100755
--- a/src/commands/manifest/scripts/test/maven-compat/assert-records.py
+++ b/src/commands/manifest/scripts/test/maven-compat/assert-records.py
@@ -6,7 +6,7 @@
import sys
rows = [l.rstrip('\n').split('\t') for l in open(sys.argv[1]) if l.strip()]
tool = None
-roots, root_projects, nodes, files, direct, edges = {}, {}, {}, {}, {}, {}
+roots, root_projects, nodes, projects, files, direct, edges = {}, {}, {}, {}, {}, {}, {}
for r in rows:
if r[0] == 'meta': tool = r[1]
elif r[0] == 'root':
@@ -16,6 +16,8 @@
elif r[0] == 'node':
nodes.setdefault(r[2], set()).add(r[1]) # coordId -> {rootId}
if r[8] == '1': direct.setdefault(r[2], set()).add(r[1]) # coordId -> {rootId where direct}
+ # coordId to the build projects its rows resolve it to.
+ projects.setdefault(r[2], set()).add(r[9] if len(r) > 9 else '')
elif r[0] == 'file': files.setdefault(r[2], set()).add(r[3]) # coordId -> {path}
elif r[0] == 'edge':
# (parent, child) to the roots that hold the edge.
@@ -27,17 +29,9 @@
# orphaned component. What remains here is Maven-specific: which coordinate lands in which root,
# and jar materialization.
-def coord(prefix, fields=None):
- """The one emitted coordId starting with prefix, or None. Keeps assertions version-agnostic.
-
- fields pins the count of colon-separated fields. Without it a prefix that stops before the
- type, as the bare-id lookup below does, would also match the typed form it is meant to rule
- out: 'demo:lib:' is a prefix of both 'demo:lib:1.0' and 'demo:lib:jar:1.0'.
- """
- hits = sorted(
- c for c in set(nodes) | set(files)
- if c.startswith(prefix) and (fields is None or c.count(':') + 1 == fields)
- )
+def coord(prefix):
+ """The one emitted coordId starting with prefix, or None. Keeps assertions version-agnostic."""
+ hits = sorted(c for c in set(nodes) | set(files) if c.startswith(prefix))
if len(hits) > 1:
errors.append(f"expected one coordinate for {prefix!r}, got {hits}")
return hits[0] if hits else None
@@ -45,8 +39,8 @@ def coord(prefix, fields=None):
ext = coord('demo.ext:tool:jar:')
harness = coord('demo.ext:harness:jar:')
harness_core = coord('demo.ext:harness-core:jar:')
-# Internal module: bare groupId:artifactId:version, no type field.
-lib = coord('demo:lib:', fields=3)
+# Sibling module demo:lib: app reaches its jar through mid and declares its test-jar.
+lib_jar, lib_tests = coord('demo:lib:jar:'), coord('demo:lib:test-jar:')
if tool != 'maven': errors.append(f"meta tool {tool!r} != 'maven'")
@@ -63,13 +57,23 @@ def has_jar(cid): return any(p.endswith('.jar') for p in files.get(cid, ()))
if not harness_core: errors.append("missing transitive test dep demo.ext:harness-core")
elif in_prod(harness_core): errors.append("transitive test dep demo.ext:harness-core wrongly in a prod root")
-if not lib: errors.append("internal module demo:lib not emitted by its bare id")
-elif not in_prod(lib): errors.append("internal module demo:lib not in app's prod root")
-elif not direct.get(lib): errors.append("internal module demo:lib not marked direct")
-
def edge_roots(parent, child):
return edges.get((parent, child), set())
+def direct_in(cid, project): return any(root_projects.get(rid) == project for rid in direct.get(cid, ()))
+
+if 'demo:lib:1.0' in nodes: errors.append("sibling demo:lib emitted under its bare id")
+elif not lib_jar or not lib_tests: errors.append("sibling demo:lib's jar or test-jar missing")
+elif projects.get(lib_jar, set()) | projects.get(lib_tests, set()) != {'demo:lib:1.0'}:
+ errors.append("sibling demo:lib's artifacts do not name demo:lib:1.0 as their project")
+elif not any(roots.get(rid) and root_projects.get(rid) == 'demo:app:1.0' for rid in nodes.get(lib_jar, ())):
+ errors.append("sibling demo:lib's jar not in app's prod root")
+elif not any(root_projects.get(rid) == 'demo:app:1.0' for rid in edge_roots(coord('demo:mid:jar:'), lib_jar)):
+ errors.append("edge demo:mid -> demo:lib's jar missing from app")
+elif in_prod(lib_tests): errors.append("sibling demo:lib's test-jar wrongly in a prod root")
+elif direct_in(lib_jar, 'demo:app:1.0'): errors.append("sibling demo:lib's jar wrongly direct in app")
+elif not direct_in(lib_tests, 'demo:app:1.0'): errors.append("sibling demo:lib's test-jar not direct in app")
+
def edge_pair(parent, child):
"""Both coordinates, or None after reporting the missing ones."""
found = (coord(parent), coord(child))
@@ -119,4 +123,4 @@ def edge_pair(parent, child):
print("FAIL:")
for e in errors: print(" -", e)
sys.exit(1)
-print(f"PASS: tool=maven; {ext} prod+jar; harness/harness-core dev; internal demo:lib (bare id, direct); demo.ext:shared prod; edges onto kept dependencies")
+print(f"PASS: tool=maven; {ext} prod+jar; harness/harness-core dev; sibling demo:lib jar prod, test-jar direct; demo.ext:shared prod; edges onto kept dependencies")
diff --git a/src/commands/manifest/scripts/test/maven-compat/project/app/pom.xml b/src/commands/manifest/scripts/test/maven-compat/project/app/pom.xml
index 557f55716..5c54ecb76 100644
--- a/src/commands/manifest/scripts/test/maven-compat/project/app/pom.xml
+++ b/src/commands/manifest/scripts/test/maven-compat/project/app/pom.xml
@@ -20,9 +20,9 @@
-
+ libdep. -->
demo
mid
diff --git a/src/commands/manifest/scripts/test/maven-compat/smoke-test-repo-inheritance.sh b/src/commands/manifest/scripts/test/maven-compat/smoke-test-repo-inheritance.sh
index d3b9776a4..2ac369689 100755
--- a/src/commands/manifest/scripts/test/maven-compat/smoke-test-repo-inheritance.sh
+++ b/src/commands/manifest/scripts/test/maven-compat/smoke-test-repo-inheritance.sh
@@ -42,16 +42,22 @@ echo "+ $("$MVN" -v 2>/dev/null | head -1) (repo inheritance)"
python3 - "$RECORDS" <<'PY'
import sys
rows = [l.rstrip('\n').split('\t') for l in open(sys.argv[1]) if l.strip()]
-roots, nodes, files, edges, failures = {}, {}, {}, set(), []
+roots, nodes, projects, files, edges, failures = {}, {}, {}, {}, set(), []
for r in rows:
if r[0] == 'root': roots[r[1]] = r[2] # rootId -> projectKey
- elif r[0] == 'node': nodes.setdefault(r[2], set()).add(r[1]) # coordId -> {rootId}
+ elif r[0] == 'node':
+ # coordId to the roots that hold it.
+ nodes.setdefault(r[2], set()).add(r[1])
+ # coordId to the build project it resolves to, if any.
+ if len(r) > 9 and r[9]: projects[r[2]] = r[9]
elif r[0] == 'file': files.setdefault(r[2], set()).add(r[3]) # coordId -> {path}
elif r[0] == 'edge': edges.add((r[1], r[2], r[3])) # (rootId, parent, child)
elif r[0] == 'failure': failures.append(r[1:])
WIDGET = 'demo.scoped:widget:jar:1.0'
LIBA = 'demo:liba:1.0'
+# liba's jar, which names liba as its project.
+LIBA_JAR = 'demo:liba:jar:1.0'
LIBB = 'demo:libb:1.0'
errors = []
@@ -70,16 +76,19 @@ for project_key in (LIBA, LIBB):
errors.append(f"{WIDGET} missing from {project_key}'s graph")
# The point of the fixture: libb reaches widget only through the reactor module liba.
-if not any(rid in roots_for(LIBB) and p == LIBA and c == WIDGET for rid, p, c in edges):
- errors.append(f"no {LIBA} -> {WIDGET} edge in libb's root")
+if not any(rid in roots_for(LIBB) and p == LIBA_JAR and c == WIDGET for rid, p, c in edges):
+ errors.append(f"no {LIBA_JAR} -> {WIDGET} edge in libb's root")
jars = [p for p in files.get(WIDGET, ()) if p.endswith('.jar')]
if not jars:
errors.append(f"{WIDGET} jar not materialized: {files.get(WIDGET)}")
# A reactor sibling reports its dirs through its `project` record, never a `file` record.
-if files.get(LIBA):
- errors.append(f"reactor module {LIBA} should have no file records, got {files[LIBA]}")
+if projects.get(LIBA_JAR) != LIBA:
+ errors.append(f"{LIBA_JAR} does not name {LIBA} as its project")
+liba_files = {p for c, ps in files.items() if c == LIBA_JAR or projects.get(c) == LIBA for p in ps}
+if liba_files:
+ errors.append(f"reactor module {LIBA} should have no file records, got {sorted(liba_files)}")
if errors:
print("FAIL:")
diff --git a/src/commands/manifest/scripts/test/maven-compat/smoke-test.sh b/src/commands/manifest/scripts/test/maven-compat/smoke-test.sh
index 7628e07d3..f2560e094 100755
--- a/src/commands/manifest/scripts/test/maven-compat/smoke-test.sh
+++ b/src/commands/manifest/scripts/test/maven-compat/smoke-test.sh
@@ -4,15 +4,15 @@
# tested separately in `nx test utils`). Guards, across the supported Maven range, that the extension:
# - emits the external prod dep demo.ext:tool (in a prod root) and the test dep demo.ext:harness +
# its transitive demo.ext:harness-core (only in a non-prod root -> the assembler's dev flag);
-# - emits the internal reactor module demo:lib by its bare groupId:artifactId:version id (so the
-# inter-module edge lines up with its `project` record);
+# - emits a sibling module's jar and test-jar under their own coordinates, each naming the module
+# as its project (the assembler merges them into the module's component);
# - marks a node prod by the scope Maven kept it with, also one whose scope dependencyManagement
# sets under a test parent;
# - records every resolved edge, pointing at the node Maven kept: onto a direct dependency, onto a
# mediated version, and from a prod node onto a provided one;
# - its records assemble into facts with no orphaned components;
-# - keeps a dependency only a sibling module's test-jar brings (mid excludes demo.ext:libdep from
-# lib, and app reaches lib's jar through mid before lib's test-jar);
+# - keeps a dependency only a sibling module's test-jar brings under that test-jar, not its jar
+# (mid excludes demo.ext:libdep from lib);
# - materializes resolved external jars under -Dsocket.withFiles;
# - scopes that materialization to -Dsocket.populateFilesFor (a newline-delimited GAV file).
#
@@ -71,9 +71,14 @@ python3 - "$RECORDS" <<'PY'
import sys
rows = [l.rstrip('\n').split('\t') for l in open(sys.argv[1]) if l.strip()]
app = {r[1] for r in rows if r[0] == 'root' and r[2] == 'demo:app:1.0'}
-if not any(r[0] == 'node' and r[1] in app and r[2].startswith('demo.ext:libdep:') for r in rows):
- print("FAIL: demo.ext:libdep missing from app"); sys.exit(1)
-print("PASS: demo.ext:libdep in app through lib's test-jar")
+def libdep_edge(parent):
+ return any(r[0] == 'edge' and r[1] in app and r[2].startswith(parent)
+ and r[3].startswith('demo.ext:libdep:') for r in rows)
+if not libdep_edge('demo:lib:test-jar:'):
+ print("FAIL: no demo:lib test-jar -> demo.ext:libdep edge in app"); sys.exit(1)
+if libdep_edge('demo:lib:jar:'):
+ print("FAIL: demo:lib jar -> demo.ext:libdep edge in app, though mid excludes it"); sys.exit(1)
+print("PASS: demo.ext:libdep in app through lib's test-jar only")
PY
assemble_records "$RECORDS"
diff --git a/test/maven-compat-smoke-assertions.test.mts b/test/maven-compat-smoke-assertions.test.mts
index 6a956b025..dcbbbccb6 100644
--- a/test/maven-compat-smoke-assertions.test.mts
+++ b/test/maven-compat-smoke-assertions.test.mts
@@ -1,13 +1,10 @@
/**
* Unit tests for the maven-compat fixture's record assertions.
*
- * The fixture proves the Maven extension emits internal reactor modules under
- * their bare groupId:artifactId:version id, distinct from the typed
- * groupId:artifactId:type:version form used for external artifacts. The lookup
- * that checks this has to reject the typed form, or a regression that stopped
- * emitting the bare id would still pass. The fixture also checks that the
- * extension records every resolved edge and marks a node prod by the scope
- * Maven kept it with.
+ * The fixture proves the Maven extension emits a sibling module's jar and
+ * test-jar under their own coordinates, each naming the module as its project,
+ * that it records every resolved edge, and that it marks a node prod by the
+ * scope Maven kept it with.
* The fixture itself needs Maven and a JDK, so these run its assertions over
* synthetic records instead.
*
@@ -38,11 +35,14 @@ function rootRow(
return ['root', rootId, projectKey, '', options.prod ? '1' : '0'].join('\t')
}
-/** A `node` row: root id in field 2, coordinate in field 3, directness in field 9. */
+/**
+ * A `node` row: root id in field 2, coordinate in field 3, directness in field
+ * 9, the build project it resolves to in field 10.
+ */
function nodeRow(
rootId: string,
coordId: string,
- options: { direct: boolean },
+ options: { direct: boolean; project: string },
): string {
return [
'node',
@@ -54,6 +54,7 @@ function nodeRow(
'',
'',
options.direct ? '1' : '0',
+ options.project,
].join('\t')
}
@@ -79,6 +80,15 @@ const MED_IO = 'demo.ext:med-io:jar:1.0'
const MED_UTIL = 'demo.ext:med-util:jar:1.0'
const CONTAINER_LIB = 'demo.ext:container-lib:jar:1.0'
const CONTAINER_API = 'demo.ext:container-api:jar:1.0'
+const MID_JAR = 'demo:mid:jar:1.0'
+// The reactor module each sibling artifact's coordinate resolves to, by artifactId.
+const SIBLING_PROJECTS: Record = {
+ __proto__: null,
+ lib: 'demo:lib:1.0',
+ mid: 'demo:mid:1.0',
+} as unknown as Record
+const LIB_JAR = 'demo:lib:jar:1.0'
+const LIB_TESTS = 'demo:lib:test-jar:tests:1.0'
const MGD_TEST = 'demo.ext:mgd-test:jar:1.0'
const MANAGED = 'demo.ext:managed:jar:1.0'
@@ -87,6 +97,7 @@ const DEV_NODES = new Set([
CONTAINER_API,
HARNESS,
HARNESS_CORE,
+ LIB_TESTS,
MGD_TEST,
])
@@ -104,6 +115,7 @@ const EDGES = {
harnessCore: { module: 'app', parent: HARNESS, child: HARNESS_CORE },
medIoUtil: { module: 'mid', parent: MED_IO, child: MED_UTIL },
mgdTestManaged: { module: 'app', parent: MGD_TEST, child: MANAGED },
+ midLib: { module: 'app', parent: MID_JAR, child: LIB_JAR },
} satisfies Record
function rootIdOf(module: string, prodRoot: boolean): string {
@@ -112,24 +124,28 @@ function rootIdOf(module: string, prodRoot: boolean): string {
type RecordsOptions = {
dev?: string[]
- internalModuleCoord?: string
+ extraNodes?: string[]
+ libProject?: string
omitEdges?: Edge[]
omitNodes?: string[]
prod?: string[]
+ toggleDirect?: string[]
}
/**
* Records in the extension's root layout: per module, a compile root with the
* nodes Maven kept with a prod scope and a test root with the whole
- * resolution. `dev`, `prod`, `omitEdges` and `omitNodes` alter it into outputs the
- * assertions must reject.
+ * resolution. `dev`, `extraNodes`, `libProject`, `omitEdges`, `omitNodes`,
+ * `prod` and `toggleDirect` alter it into outputs the assertions must reject.
*/
function buildRecords({
dev = [],
- internalModuleCoord = 'demo:lib:1.0',
+ extraNodes = [],
+ libProject = 'demo:lib:1.0',
omitEdges = [],
omitNodes = [],
prod = [],
+ toggleDirect = [],
}: RecordsOptions = {}): string {
// Coordinate and directness of each module's nodes.
const modules: Array<[string, Array<[string, boolean]>]> = [
@@ -148,7 +164,10 @@ function buildRecords({
[CONTAINER_LIB, true],
[MGD_TEST, true],
[MANAGED, false],
- [internalModuleCoord, true],
+ [MID_JAR, true],
+ [LIB_JAR, false],
+ [LIB_TESTS, true],
+ ...extraNodes.map(coord => [coord, true] as [string, boolean]),
],
],
[
@@ -156,6 +175,7 @@ function buildRecords({
[
[MED_UTIL, true],
[MED_IO, true],
+ [LIB_JAR, true],
],
],
]
@@ -170,7 +190,15 @@ function buildRecords({
rows.push(rootRow(rootId, `demo:${module}:1.0`, { prod: prodRoot }))
for (const { 0: coord, 1: direct } of nodes) {
if (inRoot(coord)) {
- rows.push(nodeRow(rootId, coord, { direct }))
+ const project = coord.startsWith('demo:lib:')
+ ? libProject
+ : (SIBLING_PROJECTS[coord.split(':')[1] ?? ''] ?? '')
+ rows.push(
+ nodeRow(rootId, coord, {
+ direct: direct !== toggleDirect.includes(coord),
+ project,
+ }),
+ )
}
}
for (const edge of Object.values(EDGES)) {
@@ -224,16 +252,50 @@ describe('maven-compat assert-records.py', () => {
it.for([
{
- // 'demo:lib:' is a prefix of 'demo:lib:jar:1.0', so a lookup that matched
- // on the prefix alone would report bare-id coverage it does not have.
- name: 'an internal module emitted only under a typed id',
- options: { internalModuleCoord: 'demo:lib:jar:1.0' },
- message: 'internal module demo:lib not emitted by its bare id',
+ name: 'a sibling emitted under its bare id',
+ options: { extraNodes: ['demo:lib:1.0'] },
+ message: 'sibling demo:lib emitted under its bare id',
+ },
+ {
+ name: "a missing edge onto the sibling's jar",
+ options: { omitEdges: [EDGES.midLib] },
+ message: "edge demo:mid -> demo:lib's jar missing from app",
+ },
+ {
+ name: 'a missing sibling jar',
+ options: { omitNodes: [LIB_JAR] },
+ message: "sibling demo:lib's jar or test-jar missing",
+ },
+ {
+ name: 'a missing sibling test-jar',
+ options: { omitNodes: [LIB_TESTS] },
+ message: "sibling demo:lib's jar or test-jar missing",
+ },
+ {
+ name: 'sibling artifacts that do not name their project',
+ options: { libProject: '' },
+ message:
+ "sibling demo:lib's artifacts do not name demo:lib:1.0 as their project",
+ },
+ {
+ name: 'a sibling jar left dev',
+ options: { dev: [LIB_JAR] },
+ message: "sibling demo:lib's jar not in app's prod root",
+ },
+ {
+ name: 'a sibling test-jar in a prod root',
+ options: { prod: [LIB_TESTS] },
+ message: "sibling demo:lib's test-jar wrongly in a prod root",
+ },
+ {
+ name: 'a sibling jar marked direct',
+ options: { toggleDirect: [LIB_JAR] },
+ message: "sibling demo:lib's jar wrongly direct in app",
},
{
- name: 'an internal module that is missing entirely',
- options: { internalModuleCoord: 'demo:unrelated:1.0' },
- message: 'internal module demo:lib not emitted by its bare id',
+ name: 'a sibling test-jar not marked direct',
+ options: { toggleDirect: [LIB_TESTS] },
+ message: "sibling demo:lib's test-jar not direct in app",
},
{
name: 'a compile-scoped node kept under a test parent left dev',