Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#571: Fix auto-dependency update for multi-maven projects #574

Merged
merged 7 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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();
}
}
Loading