diff --git a/project-keeper-maven-plugin/src/test/java/com/exasol/projectkeeper/plugin/MvnProjectWithProjectKeeperPluginWriter.java b/project-keeper-maven-plugin/src/test/java/com/exasol/projectkeeper/plugin/MvnProjectWithProjectKeeperPluginWriter.java index 9b5b8205..11953af5 100644 --- a/project-keeper-maven-plugin/src/test/java/com/exasol/projectkeeper/plugin/MvnProjectWithProjectKeeperPluginWriter.java +++ b/project-keeper-maven-plugin/src/test/java/com/exasol/projectkeeper/plugin/MvnProjectWithProjectKeeperPluginWriter.java @@ -6,6 +6,7 @@ import org.apache.maven.model.*; import org.apache.maven.model.io.xpp3.MavenXpp3Writer; +import org.codehaus.plexus.util.xml.Xpp3Dom; public class MvnProjectWithProjectKeeperPluginWriter { public static final String PROJECT_ARTIFACT_ID = "my-test-project"; @@ -42,6 +43,19 @@ public MvnProjectWithProjectKeeperPluginWriter addDependency(final String groupI return this; } + public MvnProjectWithProjectKeeperPluginWriter setArtifactFinalName(final String finalName) { + final Plugin plugin = new Plugin(); + plugin.setGroupId("org.apache.maven.plugins"); + plugin.setArtifactId("maven-assembly-plugin"); + final Xpp3Dom configuration = new Xpp3Dom("configuration"); + final Xpp3Dom finalNameElement = new Xpp3Dom("finalName"); + finalNameElement.setValue(finalName); + configuration.addChild(finalNameElement); + plugin.setConfiguration(configuration); + this.model.getBuild().addPlugin(plugin); + return this; + } + private void addProjectKeeperPlugin(final String version) { final Plugin projectKeeperPlugin = new Plugin(); projectKeeperPlugin.setGroupId("com.exasol"); diff --git a/project-keeper-maven-plugin/src/test/java/com/exasol/projectkeeper/plugin/ProjectKeeperMojoIT.java b/project-keeper-maven-plugin/src/test/java/com/exasol/projectkeeper/plugin/ProjectKeeperMojoIT.java index 66afb394..c80ba521 100644 --- a/project-keeper-maven-plugin/src/test/java/com/exasol/projectkeeper/plugin/ProjectKeeperMojoIT.java +++ b/project-keeper-maven-plugin/src/test/java/com/exasol/projectkeeper/plugin/ProjectKeeperMojoIT.java @@ -23,6 +23,7 @@ import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; +import org.hamcrest.Matcher; import org.junit.jupiter.api.*; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; @@ -50,8 +51,9 @@ void beforeEach(final TestInfo test) throws IOException, GitAPIException { Git.init().setDirectory(this.projectDir.toFile()).call().close(); new MvnProjectWithProjectKeeperPluginWriter(CURRENT_VERSION) // .addDependency("org.slf4j", "slf4j-api", ORIGINAL_SLF4J_VERSION) // + .setArtifactFinalName("dummy-${project.version}") // .writeAsPomToProject(this.projectDir); - LOG.info(() -> "Running test " + test.getDisplayName() + "..."); + LOG.info(() -> "Running test " + test.getDisplayName() + " using project " + this.projectDir + "..."); verifier = mavenIntegrationTestEnvironment.getVerifier(this.projectDir); } @@ -89,15 +91,19 @@ void testJacocoAgentIsExtracted() throws VerificationException, IOException { " - udf_coverage\n"); verifier.executeGoal("project-keeper:fix"); verifier.executeGoal("package"); - assertThat(this.projectDir.resolve(Path.of("target", "jacoco-agent", "org.jacoco.agent-runtime.jar")).toFile(), - anExistingFile()); + assertThat(projectDir.resolve("target/jacoco-agent/org.jacoco.agent-runtime.jar").toFile(), anExistingFile()); } @Test void testUpgradeDependencies() throws VerificationException, IOException { writeProjectKeeperConfig("sources:\n" + // " - type: maven\n" + // - " path: pom.xml\n"); + " path: pom.xml\n" + // + " modules:\n" + // + " - jar_artifact\n"); + final Path userGuidePath = projectDir.resolve("user_guide.md"); + writeFile(userGuidePath, "artifact reference: dummy-0.1.0.jar"); + verifier.executeGoal("project-keeper:fix"); assertThat("original version", readPom().getVersion(), equalTo("0.1.0")); @@ -113,8 +119,10 @@ void testUpgradeDependencies() throws VerificationException, IOException { final String updatedSlf4jVersion = updatedPom.getDependencies().get(0).getVersion(); assertThat("updated SLF4J version", updatedSlf4jVersion, allOf(not(equalTo(ORIGINAL_SLF4J_VERSION)), not(startsWith("1.")), startsWith("2."))); - final String changesContent = Files.readString(projectDir.resolve(ChangesFile.getPathForVersion(newVersion))); - assertThat(changesContent, allOf(startsWith("blah"))); + assertContent(userGuidePath, equalTo("artifact reference: dummy-0.1.1.jar\n")); + assertContent(ChangesFile.getPathForVersion(newVersion), + allOf(startsWith("# My Test Project 0.1.1, released 2024-??-??"), + containsString("* Added `org.slf4j:slf4j-api:"))); } private void updateReleaseDate(final String changeLogVersion, final String newReleaseDate) { @@ -150,6 +158,18 @@ void testSkip(final String phase) throws IOException, VerificationException { } private void writeProjectKeeperConfig(final String content) throws IOException { - Files.writeString(this.projectDir.resolve(".project-keeper.yml"), content); + writeFile(this.projectDir.resolve(".project-keeper.yml"), content); + } + + private void writeFile(final Path path, final String content) throws IOException { + Files.writeString(path, content); + } + + private void assertContent(Path path, final Matcher contentMatcher) throws IOException { + if (!path.isAbsolute()) { + path = projectDir.resolve(path); + } + final String changesContent = Files.readString(path); + assertThat(changesContent, contentMatcher); } } diff --git a/project-keeper/src/main/java/com/exasol/projectkeeper/ProjectKeeper.java b/project-keeper/src/main/java/com/exasol/projectkeeper/ProjectKeeper.java index 1e457768..6f9f1cdd 100644 --- a/project-keeper/src/main/java/com/exasol/projectkeeper/ProjectKeeper.java +++ b/project-keeper/src/main/java/com/exasol/projectkeeper/ProjectKeeper.java @@ -314,6 +314,7 @@ private Provision getValidationProvision() { */ public boolean updateDependencies() { final Provision provision = getValidationProvision(); - return DependencyUpdater.create(this, logger, projectDir, provision.projectVersion()).updateDependencies(); + return DependencyUpdater.create(this, config, logger, projectDir, provision.projectVersion()) + .updateDependencies(); } } diff --git a/project-keeper/src/main/java/com/exasol/projectkeeper/dependencyupdate/DependencyUpdater.java b/project-keeper/src/main/java/com/exasol/projectkeeper/dependencyupdate/DependencyUpdater.java index 293a7475..7c6d2940 100644 --- a/project-keeper/src/main/java/com/exasol/projectkeeper/dependencyupdate/DependencyUpdater.java +++ b/project-keeper/src/main/java/com/exasol/projectkeeper/dependencyupdate/DependencyUpdater.java @@ -2,14 +2,12 @@ import java.nio.file.Path; import java.time.Duration; -import java.time.Instant; -import java.util.List; import com.exasol.errorreporting.ExaError; import com.exasol.projectkeeper.Logger; import com.exasol.projectkeeper.ProjectKeeper; +import com.exasol.projectkeeper.shared.config.ProjectKeeperConfig; import com.exasol.projectkeeper.sources.analyze.generic.MavenProcessBuilder; -import com.exasol.projectkeeper.sources.analyze.generic.SimpleProcess; /** * This class runs the dependency update process. @@ -34,15 +32,16 @@ public class DependencyUpdater { * Create a new instance. * * @param projectKeeper project keeper reference + * @param config * @param logger the logger to which we should write log messages * @param projectDir the project directory * @param currentProjectVersion the project's current version * @return a new dependency updater */ - public static DependencyUpdater create(final ProjectKeeper projectKeeper, final Logger logger, - final Path projectDir, final String currentProjectVersion) { + public static DependencyUpdater create(final ProjectKeeper projectKeeper, ProjectKeeperConfig config, + final Logger logger, final Path projectDir, final String currentProjectVersion) { return new DependencyUpdater(projectKeeper, logger, projectDir, - new ProjectVersionIncrementor(logger, projectDir, currentProjectVersion)); + new ProjectVersionIncrementor(config, logger, projectDir, currentProjectVersion)); } /** @@ -79,11 +78,8 @@ private void updateDependencyVersions() { } private void runMaven(final String mavenGoal) { - final List command = MavenProcessBuilder.create().addArgument("--batch-mode").addArgument(mavenGoal) - .build(); - final Instant start = Instant.now(); - SimpleProcess.start(projectDir, command).waitUntilFinished(MAVEN_COMMAND_TIMEOUT); - logger.info("Running maven goal " + mavenGoal + " took " + Duration.between(start, Instant.now())); + MavenProcessBuilder.create().addArgument(mavenGoal).workingDir(projectDir).startSimpleProcess() + .waitUntilFinished(MAVEN_COMMAND_TIMEOUT); } private void runProjectKeeperFix() { diff --git a/project-keeper/src/main/java/com/exasol/projectkeeper/dependencyupdate/ProjectVersionIncrementor.java b/project-keeper/src/main/java/com/exasol/projectkeeper/dependencyupdate/ProjectVersionIncrementor.java index 7a07464a..27d0209a 100644 --- a/project-keeper/src/main/java/com/exasol/projectkeeper/dependencyupdate/ProjectVersionIncrementor.java +++ b/project-keeper/src/main/java/com/exasol/projectkeeper/dependencyupdate/ProjectVersionIncrementor.java @@ -1,5 +1,7 @@ package com.exasol.projectkeeper.dependencyupdate; +import static com.exasol.projectkeeper.shared.config.ProjectKeeperModule.JAR_ARTIFACT; + import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; @@ -15,24 +17,29 @@ import com.exasol.errorreporting.ExaError; import com.exasol.projectkeeper.Logger; +import com.exasol.projectkeeper.shared.config.ProjectKeeperConfig; +import com.exasol.projectkeeper.sources.analyze.generic.MavenProcessBuilder; import com.exasol.projectkeeper.validators.changesfile.ChangesFile; import com.exasol.projectkeeper.validators.changesfile.ChangesFileIO; import com.vdurmont.semver4j.Semver; class ProjectVersionIncrementor { private static final ZoneId UTC_ZONE = ZoneId.of("UTC"); + private final ProjectKeeperConfig config; private final String currentProjectVersion; private final ChangesFileIO changesFileIO; private final Clock clock; private final Path projectDir; private final Logger logger; - ProjectVersionIncrementor(final Logger logger, final Path projectDir, final String currentProjectVersion) { - this(logger, projectDir, currentProjectVersion, new ChangesFileIO(), Clock.systemUTC()); + ProjectVersionIncrementor(final ProjectKeeperConfig config, final Logger logger, final Path projectDir, + final String currentProjectVersion) { + this(config, logger, projectDir, currentProjectVersion, new ChangesFileIO(), Clock.systemUTC()); } - ProjectVersionIncrementor(final Logger logger, final Path projectDir, final String currentProjectVersion, - final ChangesFileIO changesFileIO, final Clock clock) { + ProjectVersionIncrementor(final ProjectKeeperConfig config, final Logger logger, final Path projectDir, + final String currentProjectVersion, final ChangesFileIO changesFileIO, final Clock clock) { + this.config = config; this.logger = logger; this.projectDir = projectDir; this.changesFileIO = changesFileIO; @@ -68,17 +75,35 @@ private LocalDate today() { } void incrementProjectVersion() { - final Path path = getPomPath(); - final Model pom = readPom(path); + + final Model pom = readPom(); if (!this.currentProjectVersion.equals(pom.getVersion())) { throw new IllegalStateException(ExaError.messageBuilder("E-PK-CORE-174").message( "Inconsistent project version {{version in pom file}} found in pom {{pom file path}}, expected {{expected version}}", - pom.getVersion(), path, currentProjectVersion).toString()); + pom.getVersion(), pom.getPomFile(), currentProjectVersion).ticketMitigation().toString()); } + incrementVersion(pom); + if (usesReferenceCheckerPlugin()) { + updateReferences(); + } + } + + private boolean usesReferenceCheckerPlugin() { + return config.getSources().stream().anyMatch(source -> source.getModules().contains(JAR_ARTIFACT)); + } + + private void updateReferences() { + logger.info("Unify artifact references"); + MavenProcessBuilder.create().addArgument("artifact-reference-checker:unify").workingDir(projectDir) + .startSimpleProcess().waitUntilFinished(Duration.ofSeconds(30)); + } + + private void incrementVersion(final Model pom) { final String nextVersion = getIncrementedVersion(currentProjectVersion); - logger.info("Incrementing version from " + currentProjectVersion + " to " + nextVersion + " in POM " + path); + logger.info("Incrementing version from " + currentProjectVersion + " to " + nextVersion + " in POM " + + pom.getPomFile()); pom.setVersion(nextVersion); - writePom(path, pom); + writePom(pom); } static String getIncrementedVersion(final String version) { @@ -86,7 +111,8 @@ static String getIncrementedVersion(final String version) { return current.nextPatch().toString(); } - private Model readPom(final Path path) { + private Model readPom() { + final Path path = getPomPath(); try { return new MavenXpp3Reader().read(Files.newBufferedReader(path)); } catch (IOException | XmlPullParserException exception) { @@ -95,9 +121,10 @@ private Model readPom(final Path path) { } } - private void writePom(final Path path, final Model pom) { + private void writePom(final Model pom) { + final Path path = getPomPath(); try { - new MavenXpp3Writer().write(Files.newOutputStream(getPomPath()), pom); + new MavenXpp3Writer().write(Files.newOutputStream(path), pom); } catch (final IOException exception) { throw new UncheckedIOException(ExaError.messageBuilder("E-PK-CORE-173") .message("Failed to write pom {{pom file path}}", path).toString(), exception); diff --git a/project-keeper/src/test/java/com/exasol/projectkeeper/JavaProjectCrawlerRunnerIT.java b/project-keeper/src/test/java/com/exasol/projectkeeper/JavaProjectCrawlerRunnerIT.java index 0d378c26..56619d8b 100644 --- a/project-keeper/src/test/java/com/exasol/projectkeeper/JavaProjectCrawlerRunnerIT.java +++ b/project-keeper/src/test/java/com/exasol/projectkeeper/JavaProjectCrawlerRunnerIT.java @@ -2,8 +2,9 @@ import static com.exasol.projectkeeper.shared.dependencies.BaseDependency.Type.COMPILE; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.*; import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.FileWriter; import java.io.IOException; @@ -44,8 +45,7 @@ void testGetDependencyChanges(@TempDir final Path tempDir) throws GitAPIExceptio Git.init().setDirectory(tempDir.toFile()).call().close(); final Path pomFile = tempDir.resolve("pom.xml"); writePomFile(pomFile); - final MavenProjectCrawlResult result = new JavaProjectCrawlerRunner(testMavenRepo, - TestEnvBuilder.CURRENT_VERSION).crawlProject(pomFile); + final MavenProjectCrawlResult result = crawlProject(pomFile); final CrawledMavenProject mavenProject = result.getCrawledProjects() .get(pomFile.toAbsolutePath().toString().replace("\\", "/")); final ProjectDependency expectedDependency = ProjectDependency.builder() // @@ -63,6 +63,26 @@ void testGetDependencyChanges(@TempDir final Path tempDir) throws GitAPIExceptio ); } + MavenProjectCrawlResult crawlProject(final Path... pomFiles) { + return new JavaProjectCrawlerRunner(testMavenRepo, TestEnvBuilder.CURRENT_VERSION).crawlProject(pomFiles); + } + + @Test + void testGetDependencyChangesFailsForEmptyPomList() throws GitAPIException, IOException { + final IllegalStateException exception = assertThrows(IllegalStateException.class, () -> crawlProject()); + assertThat(exception.getMessage(), containsString( + "E-PK-MPC-64: Property 'projectsToCrawl' is not defined or empty. Specify property with least one pom file.")); + } + + @Test + void testGetDependencyChangesFailsForMissingPom() throws GitAPIException, IOException { + final Path missingPomFile = Path.of("missing-pom-file"); + final IllegalStateException exception = assertThrows(IllegalStateException.class, + () -> this.crawlProject(missingPomFile)); + assertThat(exception.getMessage(), allOf(containsString("[FATAL] Non-readable POM"), + containsString(missingPomFile + " (No such file or directory)"))); + } + private void writePomFile(final Path pomFile) throws IOException { final TestMavenModel model = new TestMavenModel(); model.addDependency(DEPENDENCY_ID, DEPENDENCY_GROUP, "", DEPENDENCY_VERSION); @@ -70,4 +90,4 @@ private void writePomFile(final Path pomFile) throws IOException { new MavenXpp3Writer().write(fileWriter, model); } } -} \ No newline at end of file +}