Skip to content

Commit

Permalink
#571: Fix auto-dependency update for multi-maven projects (#574)
Browse files Browse the repository at this point in the history
* #571: Increment version in correct pom file

* #571: Update revision property if available

* Update finding revision node

* Fix version pinning for jgit

* Fix unifying references

* Fix release date
  • Loading branch information
kaklakariada authored May 10, 2024
1 parent cd53d20 commit 50ca28c
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 24 deletions.
1 change: 1 addition & 0 deletions doc/changes/changes_4.3.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This release fixes vulnerability CVE-2024-31573 in `org.xmlunit:xmlunit-core:jar

## Bugfixes

* #571: Fixed failing version increment during dependency update
* #567: Increased timeout for installing go-licenses

## Dependency Updates
Expand Down
6 changes: 3 additions & 3 deletions parent-pom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<!-- Upgrading to 6.8.0.202311291450-r causes java.lang.NoClassDefFoundError: org/eclipse/jgit/internal/JGitText in ShutdownHook-->
<!-- Upgrading causes java.lang.NoClassDefFoundError: org/eclipse/jgit/internal/JGitText in ShutdownHook-->
<!-- Will be fixed in jgit 6.10.0, see https://github.com/eclipse-jgit/jgit/issues/36 -->
<version>6.7.0.202309050840-r</version>
</dependency>
Expand Down Expand Up @@ -292,8 +292,8 @@
<excludes>
<!-- Dependencies use SLF4J 1.7 so we can't upgrade to 2 -->
<exclude>org.slf4j:slf4j-jdk14:jar:*:*</exclude>
<!-- Upgrading to 6.8.0.202311291450-r causes java.lang.NoClassDefFoundError: org/eclipse/jgit/internal/JGitText in ShutdownHook-->
<exclude>org.eclipse.jgit:org.eclipse.jgit:jar:*:6.8.0.202311291450-r</exclude>
<!-- Upgrading to 6.9.0.202403050737-r causes java.lang.NoClassDefFoundError: org/eclipse/jgit/internal/JGitText in ShutdownHook-->
<exclude>org.eclipse.jgit:org.eclipse.jgit:jar:*:*</exclude>
</excludes>
</configuration>
</plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
import java.time.*;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import com.exasol.errorreporting.ExaError;
import com.exasol.projectkeeper.Logger;
import com.exasol.projectkeeper.shared.config.ProjectKeeperConfig;
import com.exasol.projectkeeper.shared.config.*;
import com.exasol.projectkeeper.sources.analyze.generic.*;
import com.exasol.projectkeeper.validators.changesfile.ChangesFile;
import com.exasol.projectkeeper.validators.changesfile.ChangesFileIO;
Expand Down Expand Up @@ -88,9 +89,7 @@ private LocalDate today() {
String incrementProjectVersion() {
final String nextVersion = getIncrementedVersion(currentProjectVersion);
updatePomVersion(nextVersion);
if (usesReferenceCheckerPlugin()) {
updateReferences();
}
sourcesUsingReferenceCheckerPlugin().forEach(this::updateReferences);
return nextVersion;
}

Expand All @@ -102,22 +101,23 @@ private void updatePomVersion(final String nextVersion) {
xmlFileIO.write(pom, path);
}

private boolean usesReferenceCheckerPlugin() {
return config.getSources().stream().anyMatch(source -> source.getModules().contains(JAR_ARTIFACT));
private Stream<Source> sourcesUsingReferenceCheckerPlugin() {
return config.getSources().stream().filter(source -> source.getModules().contains(JAR_ARTIFACT));
}

private void updateReferences() {
logger.info("Unify artifact references");
private void updateReferences(final Source source) {
final Path moduleDir = projectDir.resolve(source.getPath()).getParent();
logger.info("Unify artifact references in dir " + moduleDir + "...");
final ShellCommand command = MavenProcessBuilder.create().addArgument("artifact-reference-checker:unify")
.workingDir(projectDir).timeout(Duration.ofSeconds(30)).buildCommand();
.workingDir(moduleDir).timeout(Duration.ofSeconds(30)).buildCommand();
commandExecutor.execute(command);
}

private void incrementVersion(final Path path, final Document pom, final String nextVersion) {
final Optional<Node> versionNode = findVersionNode(pom);
if (versionNode.isEmpty()) {
logger.warn(ExaError.messageBuilder("W-PK-CORE-196")
.message("No version node found in pom file {{pom file path}}.", path)
.message("No version element found in pom file {{pom file path}}.", path)
.mitigation("Please update the version to {{next version}} manually.", nextVersion).toString());
return;
}
Expand All @@ -130,7 +130,13 @@ private void incrementVersion(final Path path, final Document pom, final String
}

private Optional<Node> findVersionNode(final Document pom) {
return xmlFileIO.runXPath(pom, "/project/version");
final Optional<Node> versionNode = xmlFileIO.runXPath(pom, "/project/version");
if (versionNode.isEmpty() || versionNode.get().getTextContent().equals("${revision}")) {
final Optional<Node> revisionElement = xmlFileIO.runXPath(pom, "/project/properties/revision");
logger.info("Version element missing or refers to ${revision}, use revision property " + revisionElement);
return revisionElement;
}
return versionNode;
}

static String getIncrementedVersion(final String version) {
Expand All @@ -139,6 +145,9 @@ static String getIncrementedVersion(final String version) {
}

private Path getPomPath() {
if (config.getVersionConfig() instanceof final VersionFromSource versionFromSource) {
return versionFromSource.getPathToPom();
}
return projectDir.resolve("pom.xml");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.*;

import java.nio.file.Path;
import java.time.*;
import java.util.*;

import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
Expand Down Expand Up @@ -71,7 +71,7 @@ void incrementProjectVersionFailsForInconsistentVersionInPom() {
final IllegalStateException exception = assertThrows(IllegalStateException.class,
testee::incrementProjectVersion);
assertThat(exception.getMessage(),
startsWith("E-PK-CORE-174: Inconsistent project version '1.2.2' found in pom '" + POM_PATH
Matchers.startsWith("E-PK-CORE-174: Inconsistent project version '1.2.2' found in pom '" + POM_PATH
+ "', expected '1.2.3'."));
}

Expand All @@ -80,12 +80,16 @@ void incrementProjectVersionLogsWarningForMissingVersionElement() {
simulatePomVersion(null);
final ProjectVersionIncrementor testee = testee(configWithoutJarArtifact());
assertDoesNotThrow(testee::incrementProjectVersion);
verify(loggerMock).warn("W-PK-CORE-196: No version node found in pom file '" + POM_PATH
verify(loggerMock).warn("W-PK-CORE-196: No version element found in pom file '" + POM_PATH
+ "'. Please update the version to '1.2.4' manually.");
}

private void simulatePomVersion(final String version) {
when(xmlDocumentIOMock.read(POM_PATH)).thenReturn(pomModel);
simulatePomVersion(POM_PATH, version);
}

private void simulatePomVersion(final Path pomPath, final String version) {
when(xmlDocumentIOMock.read(pomPath)).thenReturn(pomModel);
if (version != null) {
when(versionNode.getTextContent()).thenReturn(version);
when(xmlDocumentIOMock.runXPath(same(pomModel), eq("/project/version")))
Expand All @@ -105,9 +109,67 @@ void incrementProjectVersion(final String currentVersion, final String expectedN
verifyPomVersionUpdated(expectedNextVersion);
}

@Test
void incrementProjectVersionInNonDefaultPom() {
final String currentVersion = "1.2.3";
final String expectedNextVersion = "1.2.4";
final Path subModulePom = Path.of("module/pom.xml");
simulatePomVersion(subModulePom, currentVersion);
final String newVersion = testee(configWithVersionFromSource(subModulePom), currentVersion)
.incrementProjectVersion();
assertThat(newVersion, equalTo(expectedNextVersion));
verifyPomVersionUpdated(subModulePom, expectedNextVersion);
}

@Test
void incrementProjectVersionInRevisionProperty() {
final String currentVersion = "1.2.3";
final String expectedNextVersion = "1.2.4";
simulatePomRevisionProperty(currentVersion);
final String newVersion = testee(configWithoutJarArtifact(), currentVersion).incrementProjectVersion();
assertThat(newVersion, equalTo(expectedNextVersion));
verifyPomVersionUpdated(expectedNextVersion);
}

@Test
void incrementProjectVersionLogsWarningForMissingRevisionPropertyElement() {
simulatePomRevisionProperty(null);
final ProjectVersionIncrementor testee = testee(configWithoutJarArtifact());
assertDoesNotThrow(testee::incrementProjectVersion);
verify(loggerMock).warn("W-PK-CORE-196: No version element found in pom file '" + POM_PATH
+ "'. Please update the version to '1.2.4' manually.");
}

private void simulatePomRevisionProperty(final String version) {
when(xmlDocumentIOMock.read(POM_PATH)).thenReturn(pomModel);
final Node projectVersionNode = createNode("${revision}");
if (version != null) {
when(versionNode.getTextContent()).thenReturn(version);
when(xmlDocumentIOMock.runXPath(same(pomModel), eq("/project/version")))
.thenReturn(Optional.of(projectVersionNode));
when(xmlDocumentIOMock.runXPath(same(pomModel), eq("/project/properties/revision")))
.thenReturn(Optional.of(versionNode));
} else {
when(xmlDocumentIOMock.runXPath(same(pomModel), eq("/project/version")))
.thenReturn(Optional.of(projectVersionNode));
when(xmlDocumentIOMock.runXPath(same(pomModel), eq("/project/properties/revision")))
.thenReturn(Optional.empty());
}
}

private Node createNode(final String textContent) {
final Node revisionNode = mock(Node.class);
when(revisionNode.getTextContent()).thenReturn(textContent);
return revisionNode;
}

private void verifyPomVersionUpdated(final String expectedNextVersion) {
verifyPomVersionUpdated(POM_PATH, expectedNextVersion);
}

private void verifyPomVersionUpdated(final Path pomPath, final String expectedNextVersion) {
verify(versionNode).setTextContent(expectedNextVersion);
verify(xmlDocumentIOMock).write(same(pomModel), eq(POM_PATH));
verify(xmlDocumentIOMock).write(same(pomModel), eq(pomPath));
}

@Test
Expand All @@ -122,8 +184,8 @@ void incrementProjectVersionWithJarArtifactUpdatesReferences() {
private void assertMavenExecuted(final String... mavenArguments) {
final ShellCommand command = getExecutedCommand();
assertThat(command.workingDir().get(), equalTo(PROJECT_DIR));
assertThat(command.commandline(),
contains(startsWith("mvn"), equalTo("--batch-mode"), equalTo("artifact-reference-checker:unify")));
assertThat(command.commandline(), contains(Matchers.startsWith("mvn"), equalTo("--batch-mode"),
equalTo("artifact-reference-checker:unify")));
}

private ShellCommand getExecutedCommand() {
Expand All @@ -146,11 +208,17 @@ private ProjectVersionIncrementor testee(final ProjectKeeperConfig config, final
}

private ProjectKeeperConfig configWithJarArtifact() {
return ProjectKeeperConfig.builder()
.sources(List.of(Source.builder().modules(Set.of(ProjectKeeperModule.JAR_ARTIFACT)).build())).build();
return ProjectKeeperConfig.builder().sources(List.of(
Source.builder().path(Path.of("pom.xml")).modules(Set.of(ProjectKeeperModule.JAR_ARTIFACT)).build()))
.build();
}

private ProjectKeeperConfig configWithoutJarArtifact() {
return ProjectKeeperConfig.builder().sources(List.of(Source.builder().modules(Set.of()).build())).build();
}

private ProjectKeeperConfig configWithVersionFromSource(final Path pom) {
return ProjectKeeperConfig.builder().sources(List.of(Source.builder().build()))
.versionConfig(new VersionFromSource(pom)).build();
}
}

0 comments on commit 50ca28c

Please sign in to comment.