Skip to content

Commit a34ab5f

Browse files
authored
Merge pull request #549 from axonivy/validate-multiple-versions-10
XIVY-10541 Validate that only one project-build-plugin version is in the reactor
2 parents e846790 + fb21178 commit a34ab5f

File tree

4 files changed

+156
-0
lines changed

4 files changed

+156
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package ch.ivyteam.ivy.maven.validate;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.HashMap;
6+
import java.util.LinkedHashSet;
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.Optional;
10+
import java.util.Set;
11+
import java.util.stream.Collectors;
12+
13+
import org.apache.maven.execution.MavenSession;
14+
import org.apache.maven.model.Plugin;
15+
import org.apache.maven.plugin.AbstractMojo;
16+
import org.apache.maven.plugin.MojoExecutionException;
17+
import org.apache.maven.plugin.MojoFailureException;
18+
import org.apache.maven.plugins.annotations.Mojo;
19+
import org.apache.maven.plugins.annotations.Parameter;
20+
import org.apache.maven.project.MavenProject;
21+
22+
/**
23+
* Validates that only one version of the project-build-plugin is active in one maven reactor.
24+
*
25+
* @since 10.0.17
26+
*/
27+
@Mojo(name = ValidateMojo.GOAL, requiresProject = true)
28+
public class ValidateMojo extends AbstractMojo {
29+
30+
public static final String GOAL = "validate";
31+
protected static final String PLUGIN_GROUPID = "com.axonivy.ivy.ci";
32+
protected static final String PLUGIN_ARTIFACTID = "project-build-plugin";
33+
34+
@Parameter(defaultValue = "${session}", readonly = true, required = true)
35+
private MavenSession session;
36+
37+
@Override
38+
public void execute() throws MojoExecutionException, MojoFailureException {
39+
validateConsistentPluginVersion(session.getAllProjects());
40+
}
41+
42+
void validateConsistentPluginVersion(List<MavenProject> projects) throws MojoExecutionException {
43+
var versionToProjectsMap = new HashMap<String, Set<MavenProject>>();
44+
for (var project : projects) {
45+
findProjectBuildPlugin(project.getBuild().getPlugins()).ifPresent(plugin -> {
46+
var version = plugin.getVersion();
47+
getLog().debug(PLUGIN_GROUPID + ":" + plugin.getArtifactId() + ":" + version + " configured in " + project);
48+
var projectSet = versionToProjectsMap.computeIfAbsent(version, v -> new LinkedHashSet<>());
49+
projectSet.add(project);
50+
});
51+
}
52+
if (versionToProjectsMap.size() > 1) {
53+
var versions = new ArrayList<>(versionToProjectsMap.keySet());
54+
Collections.sort(versions);
55+
var error = "Several versions of project-build-plugins are configured " + versions + ":\n";
56+
error += versions.stream().map(v -> versionProjects(versionToProjectsMap, v)).collect(Collectors.joining("\n"));
57+
getLog().error(error);
58+
throw new MojoExecutionException("All project-build-plugins configured in one reactor must use the same version");
59+
}
60+
}
61+
62+
private Optional<Plugin> findProjectBuildPlugin(List<Plugin> plugins) {
63+
return plugins.stream()
64+
.filter(p -> PLUGIN_GROUPID.equals(p.getGroupId()) && PLUGIN_ARTIFACTID.equals(p.getArtifactId()))
65+
.filter(p -> p.getVersion() != null) // Skip plug-ins that do not have a version
66+
.findFirst();
67+
}
68+
69+
private String versionProjects(Map<String, Set<MavenProject>> versionToProjectsMap, String version) {
70+
return version + " -> [" +
71+
versionToProjectsMap.get(version).stream()
72+
.map(p -> p.getArtifactId())
73+
.collect(Collectors.joining(", ")) +
74+
"]";
75+
}
76+
}

src/main/resources/META-INF/plexus/components.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<configuration>
1111
<phases>
1212
<clean>com.axonivy.ivy.ci:project-build-plugin:maven-dependency-cleanup</clean>
13+
<validate>com.axonivy.ivy.ci:project-build-plugin:validate</validate>
1314
<initialize>com.axonivy.ivy.ci:project-build-plugin:installEngine</initialize>
1415
<process-resources>
1516
com.axonivy.ivy.ci:project-build-plugin:ivy-resources-properties,
@@ -38,6 +39,7 @@
3839
</implementation>
3940
<configuration>
4041
<phases>
42+
<validate>com.axonivy.ivy.ci:project-build-plugin:validate</validate>
4143
<initialize>com.axonivy.ivy.ci:project-build-plugin:installEngine</initialize>
4244
<process-resources>
4345
com.axonivy.ivy.ci:project-build-plugin:ivy-resources-properties,

src/site/apt/lifecycle.apt.vm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ iar Lifecycle
66
<<phase>> | <<default executions>>
77
*--------*---------*
88
clean | ${project.groupId}:${project.artifactId}:{{{./maven-dependency-cleanup-mojo.html}maven-dependency-cleanup}}
9+
*--------*---------*
10+
validate | ${project.groupId}:${project.artifactId}:{{{./validate-mojo.html}validate}}
911
*--------*---------*
1012
initialize | ${project.groupId}:${project.artifactId}:{{{./installEngine-mojo.html}installEngine}}
1113
*--------*---------*
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package ch.ivyteam.ivy.maven.validate;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
5+
6+
import java.io.File;
7+
import java.util.List;
8+
9+
import org.apache.maven.model.Plugin;
10+
import org.apache.maven.plugin.MojoExecutionException;
11+
import org.apache.maven.project.MavenProject;
12+
import org.junit.Rule;
13+
import org.junit.Test;
14+
15+
import ch.ivyteam.ivy.maven.ProjectMojoRule;
16+
import ch.ivyteam.ivy.maven.log.LogCollector;
17+
18+
19+
public class TestValidateMojo {
20+
private ValidateMojo mojo;
21+
22+
@Rule
23+
public ProjectMojoRule<ValidateMojo> rule = new ProjectMojoRule<ValidateMojo>(
24+
new File("src/test/resources/base"), ValidateMojo.GOAL) {
25+
@Override
26+
protected void before() throws Throwable {
27+
super.before();
28+
TestValidateMojo.this.mojo = getMojo();
29+
}
30+
};
31+
32+
@Test
33+
public void samePluginVersions() throws Exception {
34+
var log = new LogCollector();
35+
rule.getMojo().setLog(log);
36+
var p1 = createMavenProject("project1", "10.0.0");
37+
var p2 = createMavenProject("project2", "10.0.0");
38+
mojo.validateConsistentPluginVersion(List.of(p1, p2));
39+
assertThat(log.getDebug()).hasSize(2);
40+
assertThat(log.getDebug().get(0).toString())
41+
.contains("com.axonivy.ivy.ci:project-build-plugin:10.0.0 configured in MavenProject: group:project1:10.0.0-SNAPSHOT");
42+
assertThat(log.getDebug().get(1).toString())
43+
.contains("com.axonivy.ivy.ci:project-build-plugin:10.0.0 configured in MavenProject: group:project2:10.0.0-SNAPSHOT");
44+
assertThat(log.getErrors()).isEmpty();
45+
}
46+
47+
@Test
48+
public void differentPluginVersions() throws Exception {
49+
var log = new LogCollector();
50+
rule.getMojo().setLog(log);
51+
var p1 = createMavenProject("project1", "10.0.0");
52+
var p2 = createMavenProject("project2", "10.0.1");
53+
assertThatThrownBy(() -> mojo.validateConsistentPluginVersion(List.of(p1, p2)))
54+
.isInstanceOf(MojoExecutionException.class);
55+
assertThat(log.getErrors()).hasSize(1);
56+
assertThat(log.getErrors().get(0).toString())
57+
.isEqualTo("""
58+
Several versions of project-build-plugins are configured [10.0.0, 10.0.1]:
59+
10.0.0 -> [project1]
60+
10.0.1 -> [project2]""");
61+
}
62+
63+
private MavenProject createMavenProject(String projectId, String version) {
64+
var project = new MavenProject();
65+
project.setGroupId("group");
66+
project.setArtifactId(projectId);
67+
project.setVersion("10.0.0-SNAPSHOT");
68+
project.setFile(new File("src/test/resources/" + projectId));
69+
var plugin = new Plugin();
70+
plugin.setGroupId(ValidateMojo.PLUGIN_GROUPID);
71+
plugin.setArtifactId(ValidateMojo.PLUGIN_ARTIFACTID);
72+
plugin.setVersion(version);
73+
project.getBuild().getPlugins().add(plugin);
74+
return project;
75+
}
76+
}

0 commit comments

Comments
 (0)