aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHÃ¥kon Hallingstad <hakon.hallingstad@gmail.com>2022-11-15 10:36:05 +0100
committerGitHub <noreply@github.com>2022-11-15 10:36:05 +0100
commit5698a43566d6f7ab93fbb8b5a1d1fd64e89c372b (patch)
tree5e62f0511155653de159dca9d0f1e6570cca60c7
parent4a531ae198d2616c03fb5df237a95e29b5352af5 (diff)
parent1d090a4db78d683a31df3cd7a2998b49fb2000ef (diff)
Merge pull request #24862 from vespa-engine/hakonhall/support-super-pom-with-dependency-enforcer
Support super-pom with dependency enforcer
-rw-r--r--maven-plugins/pom.xml1
-rw-r--r--vespa-dependencies-enforcer/pom.xml1
-rw-r--r--vespa-enforcer-extensions/src/main/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjects.java69
-rw-r--r--vespa-enforcer-extensions/src/test/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjectsTest.java4
4 files changed, 60 insertions, 15 deletions
diff --git a/maven-plugins/pom.xml b/maven-plugins/pom.xml
index d71e1a0f068..f12731ba9da 100644
--- a/maven-plugins/pom.xml
+++ b/maven-plugins/pom.xml
@@ -48,6 +48,7 @@
<configuration>
<rules>
<enforceDependencies implementation="com.yahoo.vespa.maven.plugin.enforcer.EnforceDependenciesAllProjects">
+ <rootProjectId>com.yahoo.vespa:maven-plugins</rootProjectId>
<specFile>allowed-maven-dependencies.txt</specFile>
<ignored>
<i>com.yahoo.vespa:*:*</i>
diff --git a/vespa-dependencies-enforcer/pom.xml b/vespa-dependencies-enforcer/pom.xml
index a0e6dc19ccb..768e5708ee5 100644
--- a/vespa-dependencies-enforcer/pom.xml
+++ b/vespa-dependencies-enforcer/pom.xml
@@ -39,6 +39,7 @@
<configuration>
<rules>
<enforceDependencies implementation="com.yahoo.vespa.maven.plugin.enforcer.EnforceDependenciesAllProjects">
+ <rootProjectId>com.yahoo.vespa:vespa</rootProjectId>
<specFile>allowed-maven-dependencies.txt</specFile>
<ignored>
<i>ai.vespa:*:*</i>
diff --git a/vespa-enforcer-extensions/src/main/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjects.java b/vespa-enforcer-extensions/src/main/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjects.java
index 82c705c4611..f569ce6550f 100644
--- a/vespa-enforcer-extensions/src/main/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjects.java
+++ b/vespa-enforcer-extensions/src/main/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjects.java
@@ -21,8 +21,11 @@ import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
@@ -40,6 +43,7 @@ public class EnforceDependenciesAllProjects implements EnforcerRule {
private static final String NON_TEST_HEADER = "#[non-test]";
private static final String TEST_ONLY_HEADER = "#[test-only]";
+ private String rootProjectId;
private String specFile;
private List<String> ignored = List.of();
private List<String> testUtilProjects = List.of();
@@ -47,7 +51,7 @@ public class EnforceDependenciesAllProjects implements EnforcerRule {
@Override
public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException {
Log log = helper.getLog();
- Dependencies deps = getDependenciesOfAllProjects(helper, ignored, testUtilProjects);
+ Dependencies deps = getDependenciesOfAllProjects(helper, ignored, testUtilProjects, rootProjectId);
log.info("Found %d unique dependencies (%d non-test, %d test only)".formatted(
deps.nonTest().size() + deps.testOnly().size(), deps.nonTest().size(), deps.testOnly().size()));
Path specFile = resolveSpecFile(helper, this.specFile);
@@ -61,6 +65,8 @@ public class EnforceDependenciesAllProjects implements EnforcerRule {
}
// Config injection for rule configuration. Method names must match config XML elements.
+ @SuppressWarnings("unused") public void setRootProjectId(String l) { this.rootProjectId = l; }
+ @SuppressWarnings("unused") public String getRootProjectId() { return rootProjectId; }
@SuppressWarnings("unused") public void setSpecFile(String f) { this.specFile = f; }
@SuppressWarnings("unused") public String getSpecFile() { return specFile; }
@SuppressWarnings("unused") public void setIgnored(List<String> l) { this.ignored = l; }
@@ -107,7 +113,7 @@ public class EnforceDependenciesAllProjects implements EnforcerRule {
throw new EnforcerRuleException(
errorMsg.append("Maven dependency validation failed. ")
.append("If this change was intentional, update the dependency spec by running:\n")
- .append("$ mvn validate -D").append(WRITE_SPEC_PROP).append(" -pl ").append(moduleName)
+ .append("$ mvn validate -D").append(WRITE_SPEC_PROP).append(" -pl :").append(moduleName)
.append(" -f ").append(aggregatorPomRoot).append("\n").toString());
}
}
@@ -129,7 +135,7 @@ public class EnforceDependenciesAllProjects implements EnforcerRule {
}
private static Dependencies getDependenciesOfAllProjects(EnforcerRuleHelper helper, List<String> ignored,
- List<String> testUtilProjects)
+ List<String> testUtilProjects, String rootProjectId)
throws EnforcerRuleException {
try {
Pattern depIgnorePattern = Pattern.compile(
@@ -144,16 +150,12 @@ public class EnforceDependenciesAllProjects implements EnforcerRule {
SortedSet<Dependency> testDeps = new TreeSet<>();
MavenSession session = mavenSession(helper);
var graphBuilder = helper.getComponent(DependencyGraphBuilder.class);
- List<MavenProject> projects = session.getAllProjects();
- if (projects.size() == 1) {
- throw new EnforcerRuleException(
- "Only a single Maven module detected. Enforcer must be executed from root of aggregator pom.");
- }
+ List<MavenProject> projects = getAllProjects(session, rootProjectId);
for (MavenProject project : projects) {
var req = new DefaultProjectBuildingRequest(session.getProjectBuildingRequest());
req.setProject(project);
DependencyNode root = graphBuilder.buildDependencyGraph(req, null);
- String projectId = "%s:%s".formatted(project.getGroupId(), project.getArtifactId());
+ String projectId = projectIdOf(project);
boolean overrideToTest = projectIgnorePattern.matcher(projectId).matches();
if (overrideToTest) helper.getLog().info("Treating dependencies of '%s' as 'test'".formatted(projectId));
addDependenciesRecursive(root, nonTestDeps, testDeps, depIgnorePattern, overrideToTest);
@@ -165,6 +167,50 @@ public class EnforceDependenciesAllProjects implements EnforcerRule {
}
}
+ private static String projectIdOf(MavenProject project) { return "%s:%s".formatted(project.getGroupId(), project.getArtifactId()); }
+
+ /** Only return the projects we'd like to enforce dependencies for: the root project, its modules, their modules, etc. */
+ private static List<MavenProject> getAllProjects(MavenSession session, String rootProjectId) throws EnforcerRuleException {
+ if (rootProjectId == null) throw new EnforcerRuleException("Missing required <rootProjectId> in <enforceDependencies> in pom.xml");
+
+ List<MavenProject> allProjects = session.getAllProjects();
+ if (allProjects.size() == 1) {
+ throw new EnforcerRuleException(
+ "Only a single Maven module detected. Enforcer must be executed from root of aggregator pom.");
+ }
+ MavenProject rootProject = allProjects
+ .stream()
+ .filter(project -> rootProjectId.equals(projectIdOf(project)))
+ .findAny()
+ .orElseThrow(() -> new EnforcerRuleException("Root project not found: " + rootProjectId));
+
+ Map<Path, MavenProject> projectsByBaseDir = allProjects
+ .stream()
+ .collect(Collectors.toMap(project -> project.getBasedir().toPath().normalize(), project -> project));
+
+ var projects = new ArrayList<MavenProject>();
+
+ var pendingProjects = new ArrayDeque<MavenProject>();
+ pendingProjects.add(rootProject);
+
+ while (!pendingProjects.isEmpty()) {
+ MavenProject project = pendingProjects.pop();
+ projects.add(project);
+
+ for (var module : project.getModules()) {
+ // Assumption: The module is a relative path to a project base directory.
+ Path moduleBaseDir = project.getBasedir().toPath().resolve(module).normalize();
+ MavenProject moduleProject = projectsByBaseDir.get(moduleBaseDir);
+ if (moduleProject == null)
+ throw new EnforcerRuleException("Failed to find module '" + module + "' in project " + project.getBasedir());
+ pendingProjects.add(moduleProject);
+ }
+ }
+
+ projects.sort(Comparator.comparing(EnforceDependenciesAllProjects::projectIdOf));
+ return projects;
+ }
+
private static void addDependenciesRecursive(
DependencyNode node, Set<Dependency> nonTestDeps, Set<Dependency> testDeps, Pattern ignored,
boolean overrideToTest) {
@@ -188,10 +234,7 @@ public class EnforceDependenciesAllProjects implements EnforcerRule {
return Paths.get(mavenProject(helper).getBasedir() + File.separator + specFile).normalize();
}
- private static String projectName(EnforcerRuleHelper helper) {
- MavenProject p = mavenProject(helper);
- return p.getModules().isEmpty() ? p.getName() : ".";
- }
+ private static String projectName(EnforcerRuleHelper helper) { return mavenProject(helper).getArtifactId(); }
private static Path aggregatorPomRoot(EnforcerRuleHelper helper) {
return mavenSession(helper).getRequest().getPom().toPath();
diff --git a/vespa-enforcer-extensions/src/test/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjectsTest.java b/vespa-enforcer-extensions/src/test/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjectsTest.java
index 6e47aad0d06..59062cbd61c 100644
--- a/vespa-enforcer-extensions/src/test/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjectsTest.java
+++ b/vespa-enforcer-extensions/src/test/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjectsTest.java
@@ -60,7 +60,7 @@ class EnforceDependenciesAllProjectsTest {
Forbidden non-test dependencies:
- com.example:foobar:3.4.5
Maven dependency validation failed. If this change was intentional, update the dependency spec by running:
- $ mvn validate -DdependencyEnforcer.writeSpec -pl my-dep-enforcer -f /vespa-src/pom.xml
+ $ mvn validate -DdependencyEnforcer.writeSpec -pl :my-dep-enforcer -f /vespa-src/pom.xml
""";
assertEquals(expectedErrorMessage, exception.getMessage());
}
@@ -83,7 +83,7 @@ class EnforceDependenciesAllProjectsTest {
Removed test-only dependencies:
- com.example:testbar:2.3.4
Maven dependency validation failed. If this change was intentional, update the dependency spec by running:
- $ mvn validate -DdependencyEnforcer.writeSpec -pl my-dep-enforcer -f /vespa-src/pom.xml
+ $ mvn validate -DdependencyEnforcer.writeSpec -pl :my-dep-enforcer -f /vespa-src/pom.xml
""";
assertEquals(expectedErrorMessage, exception.getMessage());
}