diff --git a/plugin-modernizer-core/pom.xml b/plugin-modernizer-core/pom.xml
index c34e4136..d318f466 100644
--- a/plugin-modernizer-core/pom.xml
+++ b/plugin-modernizer-core/pom.xml
@@ -165,6 +165,27 @@
logback-classic
test
+
+ jakarta.servlet
+ jakarta.servlet-api
+ 6.1.0
+ test
+
+
+ javax.servlet
+ javax.servlet-api
+ 4.0.1
+ test
+
+
+
+
+ org.kohsuke.stapler
+ stapler
+ 1928.v9115fe47607f
+ test
+
+
org.openrewrite
@@ -177,6 +198,7 @@
2.1.7
test
+
@@ -206,6 +228,27 @@
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 3.8.1
+
+
+ copy-dependencies
+
+ copy-dependencies
+
+ validate
+
+ ${project.build.directory}/openrewrite-classpath
+
+ javax.servlet,jakarta.servlet,org.kohsuke.stapler
+
+
+
+
gg.jte
jte-maven-plugin
diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/config/Settings.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/config/Settings.java
index 93d5b092..a3dee333 100644
--- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/config/Settings.java
+++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/config/Settings.java
@@ -192,6 +192,10 @@ private static Path getDefaultMavenLocalRepo() {
return readProperty("jenkins.parent.version", "versions.properties");
}
+ public static @Nullable String getBomVersion() {
+ return readProperty("bom.version", "versions.properties");
+ }
+
private static @Nullable URL getUpdateCenterUrl() throws MalformedURLException {
String url = System.getenv("JENKINS_UC");
if (url != null) {
diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/extractor/MetadataVisitor.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/extractor/MetadataVisitor.java
index a8bb0adf..8f053590 100644
--- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/extractor/MetadataVisitor.java
+++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/extractor/MetadataVisitor.java
@@ -66,7 +66,7 @@ public Tree visit(Tree tree, ExecutionContext executionContext) {
// Extract metadata from POM
else if (PathUtils.matchesGlob(sourceFile.getSourcePath(), "**/pom.xml")) {
LOG.debug("Visiting POM {}", sourceFile.getSourcePath());
- PluginMetadata pomMetadata = new PomVisitor().reduce(tree, pluginMetadata);
+ PluginMetadata pomMetadata = new PomResolutionVisitor().reduce(tree, pluginMetadata);
LOG.debug("POM metadata: {}", JsonUtils.toJson(pomMetadata));
executionContext.putMessage("pomMetadata", pomMetadata); // Is there better than context messaging ?
return tree;
diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/extractor/PomVisitor.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/extractor/PomResolutionVisitor.java
similarity index 82%
rename from plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/extractor/PomVisitor.java
rename to plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/extractor/PomResolutionVisitor.java
index 5bf913cf..7cd68908 100644
--- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/extractor/PomVisitor.java
+++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/extractor/PomResolutionVisitor.java
@@ -12,13 +12,24 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class PomVisitor extends MavenIsoVisitor {
+/**
+ * A pom visitor that accumulate PluginMetadata using maven resolution result.
+ * Maven resolution might not get updated if the tree is modified by other visitor
+ * So it's best used in preconditons recipes to avoid side effect
+ * An other implementation of this visitor could be extraction from the tree instead of maven resolution result
+ */
+public class PomResolutionVisitor extends MavenIsoVisitor {
- private static final Logger LOG = LoggerFactory.getLogger(PomVisitor.class);
+ /**
+ * LOGGER.
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(PomResolutionVisitor.class);
@Override
public Xml.Document visitDocument(Xml.Document document, PluginMetadata pluginMetadata) {
+ document = super.visitDocument(document, pluginMetadata);
+
Markers markers = getCursor().firstEnclosingOrThrow(Xml.Document.class).getMarkers();
// Ensure maven resolution result is present
diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/IsMissingBom.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/IsMissingBom.java
index 62b5e77b..ea01e9b2 100644
--- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/IsMissingBom.java
+++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/IsMissingBom.java
@@ -1,7 +1,7 @@
package io.jenkins.tools.pluginmodernizer.core.recipes;
import io.jenkins.tools.pluginmodernizer.core.extractor.PluginMetadata;
-import io.jenkins.tools.pluginmodernizer.core.extractor.PomVisitor;
+import io.jenkins.tools.pluginmodernizer.core.extractor.PomResolutionVisitor;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
@@ -37,7 +37,7 @@ public TreeVisitor, ExecutionContext> getVisitor() {
@Override
public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) {
- PluginMetadata pluginMetadata = new PomVisitor().reduce(document, new PluginMetadata());
+ PluginMetadata pluginMetadata = new PomResolutionVisitor().reduce(document, new PluginMetadata());
if (pluginMetadata.getBomVersion() == null) {
LOG.info("Project is missing Jenkins BOM");
diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/IsMissingJenkinsBaselineProperty.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/IsMissingJenkinsBaselineProperty.java
index 0b71fd0e..aaf952ea 100644
--- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/IsMissingJenkinsBaselineProperty.java
+++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/IsMissingJenkinsBaselineProperty.java
@@ -1,7 +1,7 @@
package io.jenkins.tools.pluginmodernizer.core.recipes;
import io.jenkins.tools.pluginmodernizer.core.extractor.PluginMetadata;
-import io.jenkins.tools.pluginmodernizer.core.extractor.PomVisitor;
+import io.jenkins.tools.pluginmodernizer.core.extractor.PomResolutionVisitor;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
@@ -37,7 +37,7 @@ public TreeVisitor, ExecutionContext> getVisitor() {
@Override
public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) {
- PluginMetadata pluginMetadata = new PomVisitor().reduce(document, new PluginMetadata());
+ PluginMetadata pluginMetadata = new PomResolutionVisitor().reduce(document, new PluginMetadata());
if (!pluginMetadata.getProperties().containsKey("jenkins.baseline")) {
LOG.info("Project is missing jenkins.baseline property");
diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/IsUsingBom.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/IsUsingBom.java
index 2b3f05a5..589dc684 100644
--- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/IsUsingBom.java
+++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/IsUsingBom.java
@@ -1,7 +1,7 @@
package io.jenkins.tools.pluginmodernizer.core.recipes;
import io.jenkins.tools.pluginmodernizer.core.extractor.PluginMetadata;
-import io.jenkins.tools.pluginmodernizer.core.extractor.PomVisitor;
+import io.jenkins.tools.pluginmodernizer.core.extractor.PomResolutionVisitor;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
@@ -37,7 +37,7 @@ public TreeVisitor, ExecutionContext> getVisitor() {
@Override
public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) {
- PluginMetadata pluginMetadata = new PomVisitor().reduce(document, new PluginMetadata());
+ PluginMetadata pluginMetadata = new PomResolutionVisitor().reduce(document, new PluginMetadata());
if (pluginMetadata.getBomVersion() != null) {
LOG.info("Project is using Jenkins bom at version {}", pluginMetadata.getBomVersion());
diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateToJenkinsBaseLineProperty.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateToJenkinsBaseLineProperty.java
index a611f146..75130a07 100644
--- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateToJenkinsBaseLineProperty.java
+++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateToJenkinsBaseLineProperty.java
@@ -1,31 +1,40 @@
package io.jenkins.tools.pluginmodernizer.core.recipes;
import io.jenkins.tools.pluginmodernizer.core.extractor.PluginMetadata;
-import io.jenkins.tools.pluginmodernizer.core.extractor.PomVisitor;
+import io.jenkins.tools.pluginmodernizer.core.extractor.PomResolutionVisitor;
import io.jenkins.tools.pluginmodernizer.core.visitors.AddBeforePropertyVisitor;
import io.jenkins.tools.pluginmodernizer.core.visitors.AddPropertyCommentVisitor;
import org.jspecify.annotations.Nullable;
import org.openrewrite.*;
import org.openrewrite.Cursor;
import org.openrewrite.maven.AddPropertyVisitor;
+import org.openrewrite.maven.ChangeManagedDependencyGroupIdAndArtifactId;
import org.openrewrite.maven.MavenIsoVisitor;
-import org.openrewrite.xml.ChangeTagValueVisitor;
import org.openrewrite.xml.tree.Xml;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+/**
+ * A recipe to migrate the pom.xml to use the jenkins.baseLine property.
+ * Doesn't upgrade the jenkins version or bom version.
+ * If the plugin is not using the bom or using the weekly baseline, it will skip the update.
+ * This will also fix the bom version if it doesn't match the jenkins.version.
+ */
public class MigrateToJenkinsBaseLineProperty extends Recipe {
+ /**
+ * Logger for the class.
+ */
public static final Logger LOG = LoggerFactory.getLogger(MigrateToJenkinsBaseLineProperty.class);
@Override
public String getDisplayName() {
- return "Migrate to Jenkins baseline property";
+ return "Update the pom.xml to use newly introduced jenkins.baseline property";
}
@Override
public String getDescription() {
- return "Migrate to Jenkins baseline property.";
+ return "Update the pom.xml to use newly introduced jenkins.baseline property.";
}
@Override
@@ -47,8 +56,8 @@ private static class MigrateToJenkinsBaseLinePropertyVisitor extends MavenIsoVis
public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) {
Xml.Document d = super.visitDocument(document, ctx);
- // Skip if not bom or weekly bom
- PluginMetadata pluginMetadata = new PomVisitor().reduce(document, new PluginMetadata());
+ // Skip if not using bom or using weekly baseline
+ PluginMetadata pluginMetadata = new PomResolutionVisitor().reduce(document, new PluginMetadata());
if (pluginMetadata.getBomArtifactId() == null || "bom-weekly".equals(pluginMetadata.getBomArtifactId())) {
LOG.debug("Project is using Jenkins weekly bom or not bom, skipping");
return d;
@@ -58,6 +67,10 @@ public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) {
return document;
}
+ /**
+ * Perform the update.
+ * @param document The document to update.
+ */
private void performUpdate(Xml.Document document) {
Xml.Tag jenkinsVersionTag = document.getRoot()
@@ -71,7 +84,7 @@ private void performUpdate(Xml.Document document) {
// Keep only major and minor and ignore patch version
String jenkinsVersion = jenkinsVersionTag.getValue().get();
- String jenkinsBaseline = jenkinsVersionTag.getValue().get();
+ String jenkinsBaseline = jenkinsVersion;
String jenkinsPatch = null;
// It's a LTS, extract patch
@@ -102,20 +115,31 @@ private void performUpdate(Xml.Document document) {
}
// Change the bom artifact ID
- Xml.Tag artifactIdTag = document.getRoot()
+ Xml.Tag bom = document.getRoot()
.getChild("dependencyManagement")
.flatMap(dm -> dm.getChild("dependencies"))
.flatMap(deps -> deps.getChild("dependency"))
.filter(dep -> dep.getChildValue("groupId")
.map("io.jenkins.tools.bom"::equals)
.orElse(false))
- .flatMap(dep -> dep.getChild("artifactId"))
.orElseThrow();
+ Xml.Tag artifactIdTag = bom.getChild("artifactId").orElseThrow();
+ Xml.Tag version = bom.getChild("version").orElseThrow();
+
LOG.debug("Artifact ID is {}", artifactIdTag.getValue().get());
+ LOG.debug("Version is {}", version.getValue().get());
+ // Change the artifact and perform upgrade
if (!artifactIdTag.getValue().get().equals("bom-${jenkins.baseline}.x")) {
- doAfterVisit(new ChangeTagValueVisitor<>(artifactIdTag, "bom-${jenkins.baseline}.x"));
+ doAfterVisit(new ChangeManagedDependencyGroupIdAndArtifactId(
+ "io.jenkins.tools.bom",
+ artifactIdTag.getValue().get(),
+ "io.jenkins.tools.bom",
+ "bom-${jenkins.baseline}.x",
+ version.getValue().get(),
+ "\\.v[a-f0-9_]+")
+ .getVisitor());
}
}
}
diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/UpdateBom.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/UpdateBom.java
new file mode 100644
index 00000000..5b398f6a
--- /dev/null
+++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/UpdateBom.java
@@ -0,0 +1,26 @@
+package io.jenkins.tools.pluginmodernizer.core.recipes;
+
+import io.jenkins.tools.pluginmodernizer.core.visitors.UpdateBomVersionVisitor;
+import org.openrewrite.*;
+import org.openrewrite.maven.table.MavenMetadataFailures;
+
+/**
+ * A recipe that update the bom version to latest available.
+ */
+public class UpdateBom extends Recipe {
+
+ @Override
+ public @NlsRewrite.DisplayName String getDisplayName() {
+ return "Update bom recipe";
+ }
+
+ @Override
+ public @NlsRewrite.Description String getDescription() {
+ return "Update bom recipe.";
+ }
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return Preconditions.check(new IsUsingBom(), new UpdateBomVersionVisitor(new MavenMetadataFailures(this)));
+ }
+}
diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/UpgradeJenkinsVersion.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/UpgradeJenkinsVersion.java
new file mode 100644
index 00000000..29d6017f
--- /dev/null
+++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/UpgradeJenkinsVersion.java
@@ -0,0 +1,61 @@
+package io.jenkins.tools.pluginmodernizer.core.recipes;
+
+import org.openrewrite.*;
+import org.openrewrite.jenkins.UpgradeVersionProperty;
+import org.openrewrite.maven.MavenIsoVisitor;
+import org.openrewrite.xml.tree.Xml;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A recipe to upgrade the Jenkins version in the pom.xml.
+ * Take care of updating the bom or adding the bom if it's not present.
+ * Not changing anything if the version is already higher than the minimum version.
+ */
+public class UpgradeJenkinsVersion extends Recipe {
+
+ /**
+ * LOGGER.
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(UpgradeJenkinsVersion.class);
+
+ /**
+ * The minimum version.
+ */
+ @Option(displayName = "Version", description = "The version.", example = "2.452.4")
+ String minimumVersion;
+
+ /**
+ * Constructor.
+ * @param minimumVersion The minimum version.
+ */
+ public UpgradeJenkinsVersion(String minimumVersion) {
+ this.minimumVersion = minimumVersion;
+ }
+
+ @Override
+ public String getDisplayName() {
+ return "Upgrade Jenkins version";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Upgrade Jenkins version.";
+ }
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new MavenIsoVisitor<>() {
+
+ @Override
+ public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) {
+
+ // Return another tree with jenkins version updated
+ document = (Xml.Document) new UpgradeVersionProperty("jenkins.version", minimumVersion)
+ .getVisitor()
+ .visitNonNull(document, ctx);
+ return (Xml.Document) new UpdateBom().getVisitor().visitNonNull(document, ctx);
+ }
+ };
+ }
+}
diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/visitors/RemovePropertyCommentVisitor.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/visitors/RemovePropertyCommentVisitor.java
index c737cc42..97be1ef5 100644
--- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/visitors/RemovePropertyCommentVisitor.java
+++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/visitors/RemovePropertyCommentVisitor.java
@@ -7,10 +7,21 @@
import org.openrewrite.xml.tree.Content;
import org.openrewrite.xml.tree.Xml;
+/**
+ * A visitor that remove a comment from a property in a maven pom file.
+ * Only a comment with exact match will be removed inside the properties block.
+ */
public class RemovePropertyCommentVisitor extends MavenIsoVisitor {
- private String comment;
+ /**
+ * The comment to remove.
+ */
+ private final String comment;
+ /**
+ * Constructor of the visitor.
+ * @param comment The comment to remove.
+ */
public RemovePropertyCommentVisitor(String comment) {
this.comment = comment;
}
@@ -20,7 +31,7 @@ public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext executionContext) {
tag = super.visitTag(tag, executionContext);
if (tag.getName().equals("properties")) {
- List contents = new ArrayList<>(tag.getContent());
+ List contents = new ArrayList<>(tag.getContent() != null ? tag.getContent() : List.of());
// Remove the comment if needed
boolean containsComment = contents.stream()
diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/visitors/UpdateBomVersionVisitor.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/visitors/UpdateBomVersionVisitor.java
new file mode 100644
index 00000000..23a2ed87
--- /dev/null
+++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/visitors/UpdateBomVersionVisitor.java
@@ -0,0 +1,109 @@
+package io.jenkins.tools.pluginmodernizer.core.visitors;
+
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.maven.*;
+import org.openrewrite.maven.table.MavenMetadataFailures;
+import org.openrewrite.maven.trait.MavenDependency;
+import org.openrewrite.semver.LatestRelease;
+import org.openrewrite.semver.VersionComparator;
+import org.openrewrite.xml.ChangeTagValueVisitor;
+import org.openrewrite.xml.tree.Xml;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A visitor that updates the BOM version in a maven pom file.
+ */
+public class UpdateBomVersionVisitor extends MavenIsoVisitor {
+
+ /**
+ * LOGGER.
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(UpdateBomVersionVisitor.class);
+
+ private transient MavenMetadataFailures metadataFailures;
+
+ /**
+ * Contructor
+ */
+ public UpdateBomVersionVisitor(MavenMetadataFailures metadataFailures) {
+ this.metadataFailures = metadataFailures;
+ }
+
+ @Override
+ public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) {
+ document = super.visitDocument(document, ctx);
+
+ // Resolve artifact id
+ Xml.Tag bomTag = getBomTag(document);
+ Xml.Tag versionTag = bomTag.getChild("version").orElseThrow();
+ Xml.Tag getProperties = getProperties(document);
+
+ String artifactId =
+ bomTag.getChild("artifactId").orElseThrow().getValue().orElseThrow();
+ String version = bomTag.getChild("version").orElseThrow().getValue().orElseThrow();
+ LOG.debug("Updating bom version from {} to latest.release", version);
+ if (artifactId.equals("bom-${jenkins.baseline}.x")) {
+ artifactId =
+ "bom-" + getProperties.getChildValue("jenkins.baseline").orElseThrow() + ".x";
+ }
+
+ String newBomVersionAvailable = findNewerBomVersion(artifactId, version, ctx);
+ if (newBomVersionAvailable == null) {
+ LOG.debug("No newer version available for {}", artifactId);
+ return document;
+ }
+
+ return (Xml.Document)
+ new ChangeTagValueVisitor<>(versionTag, newBomVersionAvailable).visitNonNull(document, ctx);
+ }
+
+ /**
+ * Find the newer bom version
+ * @param artifactId The artifact id
+ * @param currentVersion The current version
+ * @param ctx The execution context
+ * @return The newer bom version
+ */
+ private String findNewerBomVersion(String artifactId, String currentVersion, ExecutionContext ctx) {
+ VersionComparator latestRelease = new LatestRelease("\\.v[a-f0-9_]+");
+ try {
+ return MavenDependency.findNewerVersion(
+ "io.jenkins.tools.bom",
+ artifactId,
+ currentVersion,
+ getResolutionResult(),
+ metadataFailures,
+ latestRelease,
+ ctx);
+ } catch (MavenDownloadingException e) {
+ LOG.warn("Failed to download metadata for {}", artifactId, e);
+ return null;
+ }
+ }
+
+ /**
+ * Get the bom tag from the document
+ * @param document The document
+ * @return The bom tag
+ */
+ private Xml.Tag getBomTag(Xml.Document document) {
+ return document.getRoot()
+ .getChild("dependencyManagement")
+ .flatMap(dm -> dm.getChild("dependencies"))
+ .flatMap(deps -> deps.getChild("dependency"))
+ .filter(dep -> dep.getChildValue("groupId")
+ .map("io.jenkins.tools.bom"::equals)
+ .orElse(false))
+ .orElseThrow();
+ }
+
+ /**
+ * Get the properties tag from the document
+ * @param document The document
+ * @return The properties tag
+ */
+ private Xml.Tag getProperties(Xml.Document document) {
+ return document.getRoot().getChild("properties").orElseThrow();
+ }
+}
diff --git a/plugin-modernizer-core/src/main/resources/META-INF/rewrite/recipes.yml b/plugin-modernizer-core/src/main/resources/META-INF/rewrite/recipes.yml
index 9e68c72b..bfb4a809 100644
--- a/plugin-modernizer-core/src/main/resources/META-INF/rewrite/recipes.yml
+++ b/plugin-modernizer-core/src/main/resources/META-INF/rewrite/recipes.yml
@@ -61,12 +61,21 @@ recipeList:
groupId: org.jenkins-ci.plugins
artifactId: plugin
newVersion: 5.X
- - org.openrewrite.jenkins.UpgradeVersionProperty:
- key: jenkins.version
+ - io.jenkins.tools.pluginmodernizer.core.recipes.UpgradeJenkinsVersion:
minimumVersion: 2.479.1
- org.openrewrite.java.ChangeType:
oldFullyQualifiedTypeName: org.kohsuke.stapler.StaplerRequest
newFullyQualifiedTypeName: org.kohsuke.stapler.StaplerRequest2
+ - org.openrewrite.java.ChangeMethodName:
+ methodPattern: org.kohsuke.stapler.Stapler getCurrentRequest()
+ newMethodName: getCurrentRequest2
+ - org.openrewrite.java.ChangeMethodName:
+ methodPattern: org.kohsuke.stapler.Stapler getCurrentResponse()
+ newMethodName: getCurrentResponse2
+ - org.openrewrite.java.ChangePackage:
+ oldPackageName: javax.servlet
+ newPackageName: jakarta.servlet
+ recursive: false
- io.jenkins.tools.pluginmodernizer.RemoveDependencyVersionOverride
- org.openrewrite.maven.RemoveProperty: # Set by 5.x parent, ensure it's removed
propertyName: maven.compiler.release
@@ -79,11 +88,7 @@ tags: ['dependencies']
preconditions:
- io.jenkins.tools.pluginmodernizer.core.recipes.IsUsingBom
recipeList:
- - org.openrewrite.maven.UpgradeDependencyVersion:
- groupId: io.jenkins.tools.bom
- artifactId: "bom-*"
- newVersion: latest.release
- versionPattern: "\\.v[a-f0-9_]+"
+ - io.jenkins.tools.pluginmodernizer.core.recipes.UpdateBom
- io.jenkins.tools.pluginmodernizer.RemoveDependencyVersionOverride
---
type: specs.openrewrite.org/v1beta/recipe
@@ -283,11 +288,11 @@ tags: ['developer']
recipeList:
- io.jenkins.tools.pluginmodernizer.MigrateToJenkinsBaseLineProperty
- io.jenkins.tools.pluginmodernizer.UpgradeParentVersion
- - org.openrewrite.jenkins.UpgradeVersionProperty:
- key: jenkins.version
+ - io.jenkins.tools.pluginmodernizer.core.recipes.UpgradeJenkinsVersion:
minimumVersion: 2.452.4
- io.jenkins.tools.pluginmodernizer.RemoveDependencyVersionOverride
- io.jenkins.tools.pluginmodernizer.RemoveExtraMavenProperties
+ - io.jenkins.tools.pluginmodernizer.UpgradeBomVersion
---
type: specs.openrewrite.org/v1beta/recipe
name: io.jenkins.tools.pluginmodernizer.UpgradeToLatestJava11CoreVersion
@@ -297,11 +302,11 @@ tags: ['developer']
recipeList:
- io.jenkins.tools.pluginmodernizer.MigrateToJenkinsBaseLineProperty
- io.jenkins.tools.pluginmodernizer.UpgradeParentVersion
- - org.openrewrite.jenkins.UpgradeVersionProperty:
- key: jenkins.version
+ - io.jenkins.tools.pluginmodernizer.core.recipes.UpgradeJenkinsVersion:
minimumVersion: 2.462.3
- io.jenkins.tools.pluginmodernizer.RemoveDependencyVersionOverride
- io.jenkins.tools.pluginmodernizer.RemoveExtraMavenProperties
+ - io.jenkins.tools.pluginmodernizer.UpgradeBomVersion
---
type: specs.openrewrite.org/v1beta/recipe
name: io.jenkins.tools.pluginmodernizer.UpgradeToJava17
diff --git a/plugin-modernizer-core/src/main/resources/versions.properties b/plugin-modernizer-core/src/main/resources/versions.properties
index 77c00409..2c31b83b 100644
--- a/plugin-modernizer-core/src/main/resources/versions.properties
+++ b/plugin-modernizer-core/src/main/resources/versions.properties
@@ -1,5 +1,6 @@
openrewrite.maven.plugin.version = ${openrewrite.maven.plugin.version}
jenkins.parent.version = 5.4
+bom.version = 3850.vb_c5319efa_e29
remediation.jenkins.minimum.version = 2.440.3
remediation.jenkins.plugin.parent.version = 4.51
remediation.bom.version = 3413.v0d896b_76a_30d
diff --git a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/DeclarativeRecipesTest.java b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/DeclarativeRecipesTest.java
index 09c029ca..46c50a77 100644
--- a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/DeclarativeRecipesTest.java
+++ b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/DeclarativeRecipesTest.java
@@ -1,9 +1,15 @@
package io.jenkins.tools.pluginmodernizer.core.recipes;
+import static org.openrewrite.java.Assertions.java;
import static org.openrewrite.maven.Assertions.pomXml;
import io.jenkins.tools.pluginmodernizer.core.config.Settings;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
import org.junit.jupiter.api.Test;
+import org.openrewrite.java.JavaParser;
import org.openrewrite.test.RewriteTest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -161,7 +167,7 @@ void upgradeToRecommendCoreVersionTestWithBaseline() {
io.jenkins.tools.bom
bom-${jenkins.baseline}.x
- 3435.v238d66a_043fb_
+ %s
pom
import
@@ -180,7 +186,8 @@ void upgradeToRecommendCoreVersionTestWithBaseline() {
- """));
+ """
+ .formatted(Settings.getBomVersion())));
}
@Test
@@ -258,7 +265,7 @@ void upgradeToUpgradeToLatestJava11CoreVersion() {
io.jenkins.tools.bom
bom-${jenkins.baseline}.x
- 3435.v238d66a_043fb_
+ %s
pom
import
@@ -277,15 +284,38 @@ void upgradeToUpgradeToLatestJava11CoreVersion() {
- """));
+ """
+ .formatted(Settings.getBomVersion())));
+ }
+
+ /**
+ * Collect rewrite test dependencies from target/openrewrite-classpath directory
+ * @return List of Path
+ * @throws Exception if an I/O error occurs
+ */
+ private List collectRewriteTestDependencies() {
+ try {
+ List entries = Files.list(Path.of("target/openrewrite-classpath"))
+ .filter(p -> p.toString().endsWith(".jar"))
+ .toList();
+ LOG.debug("Collected rewrite test dependencies: {}", entries);
+ return entries;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
@Test
void upgradeNextMajorParentVersionTest() {
rewriteRun(
- spec -> spec.recipeFromResource(
- "/META-INF/rewrite/recipes.yml",
- "io.jenkins.tools.pluginmodernizer.UpgradeNextMajorParentVersion"),
+ spec -> {
+ var parser = JavaParser.fromJavaVersion().logCompilationWarningsAndErrors(true);
+ collectRewriteTestDependencies().forEach(parser::addClasspathEntry);
+ spec.recipeFromResource(
+ "/META-INF/rewrite/recipes.yml",
+ "io.jenkins.tools.pluginmodernizer.UpgradeNextMajorParentVersion")
+ .parser(parser);
+ },
pomXml(
"""
@@ -352,7 +382,128 @@ void upgradeNextMajorParentVersionTest() {
"""
- .formatted(Settings.getJenkinsParentVersion())));
+ .formatted(Settings.getJenkinsParentVersion())),
+ java(
+ """
+ import javax.servlet.ServletException;
+ import org.kohsuke.stapler.Stapler;
+ import org.kohsuke.stapler.StaplerRequest;
+
+ public class Foo {
+ public void foo() {
+ StaplerRequest req = Stapler.getCurrentRequest();
+ }
+ }
+ """,
+ """
+ import jakarta.servlet.ServletException;
+ import org.kohsuke.stapler.Stapler;
+ import org.kohsuke.stapler.StaplerRequest2;
+
+ public class Foo {
+ public void foo() {
+ StaplerRequest2 req = Stapler.getCurrentRequest2();
+ }
+ }
+ """));
+ }
+
+ @Test
+ void upgradeNextMajorParentVersionTestWithBom() {
+ rewriteRun(
+ spec -> spec.recipeFromResource(
+ "/META-INF/rewrite/recipes.yml",
+ "io.jenkins.tools.pluginmodernizer.UpgradeNextMajorParentVersion"),
+ pomXml(
+ """
+
+
+ 4.0.0
+
+ org.jenkins-ci.plugins
+ plugin
+ 4.87
+
+
+ io.jenkins.plugins
+ empty
+ 1.0.0-SNAPSHOT
+ hpi
+ Empty Plugin
+
+ 2.440.3
+
+
+
+
+ io.jenkins.tools.bom
+ bom-2.440.x
+ 3435.v238d66a_043fb_
+ pom
+ import
+
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+ """,
+ """
+
+
+ 4.0.0
+
+ org.jenkins-ci.plugins
+ plugin
+ %s
+
+
+ io.jenkins.plugins
+ empty
+ 1.0.0-SNAPSHOT
+ hpi
+ Empty Plugin
+
+
+ 2.479
+ ${jenkins.baseline}.1
+
+
+
+
+ io.jenkins.tools.bom
+ bom-${jenkins.baseline}.x
+ %s
+ pom
+ import
+
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+ """
+ .formatted(Settings.getJenkinsParentVersion(), Settings.getBomVersion())));
}
@Test
@@ -378,7 +529,7 @@ void upgradeNextMajorParentVersionTestWithBaseline() {
hpi
Empty Plugin
- 2.462
+ 2.440
${jenkins.baseline}.3
@@ -431,7 +582,7 @@ void upgradeNextMajorParentVersionTestWithBaseline() {
io.jenkins.tools.bom
bom-${jenkins.baseline}.x
- 3435.v238d66a_043fb_
+ %s
pom
import
@@ -451,7 +602,7 @@ void upgradeNextMajorParentVersionTestWithBaseline() {
"""
- .formatted(Settings.getJenkinsParentVersion())));
+ .formatted(Settings.getJenkinsParentVersion(), Settings.getBomVersion())));
}
@Test
diff --git a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateToJenkinsBaseLinePropertyTest.java b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateToJenkinsBaseLinePropertyTest.java
index 8e263230..756243c8 100644
--- a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateToJenkinsBaseLinePropertyTest.java
+++ b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateToJenkinsBaseLinePropertyTest.java
@@ -5,6 +5,9 @@
import org.junit.jupiter.api.Test;
import org.openrewrite.test.RewriteTest;
+/**
+ * Test for {@link MigrateToJenkinsBaseLineProperty}
+ */
public class MigrateToJenkinsBaseLinePropertyTest implements RewriteTest {
@Test
diff --git a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/UpgradeJenkinsVersionTest.java b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/UpgradeJenkinsVersionTest.java
new file mode 100644
index 00000000..69e100ba
--- /dev/null
+++ b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/UpgradeJenkinsVersionTest.java
@@ -0,0 +1,351 @@
+package io.jenkins.tools.pluginmodernizer.core.recipes;
+
+import static org.openrewrite.maven.Assertions.pomXml;
+
+import io.jenkins.tools.pluginmodernizer.core.config.Settings;
+import org.junit.jupiter.api.Test;
+import org.openrewrite.test.RewriteTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test for {@link UpgradeJenkinsVersion}.
+ */
+public class UpgradeJenkinsVersionTest implements RewriteTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(UpgradeJenkinsVersionTest.class);
+
+ @Test
+ void testPerformUpgradeWithoutBom() {
+ rewriteRun(
+ spec -> spec.recipe(new UpgradeJenkinsVersion("2.452.4")),
+ pomXml(
+ """
+
+
+ 4.0.0
+
+ org.jenkins-ci.plugins
+ plugin
+ 4.87
+
+
+ io.jenkins.plugins
+ empty
+ 1.0.0-SNAPSHOT
+ hpi
+ Empty Plugin
+
+ 2.440.3
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+ """,
+ """
+
+
+ 4.0.0
+
+ org.jenkins-ci.plugins
+ plugin
+ 4.87
+
+
+ io.jenkins.plugins
+ empty
+ 1.0.0-SNAPSHOT
+ hpi
+ Empty Plugin
+
+ 2.452.4
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+ """));
+ }
+
+ @Test
+ void testPerformUpgradeWithBaselineWithoutBom() {
+ rewriteRun(
+ spec -> spec.recipe(new UpgradeJenkinsVersion("2.452.4")),
+ pomXml(
+ """
+
+
+ 4.0.0
+
+ org.jenkins-ci.plugins
+ plugin
+ 4.87
+
+
+ io.jenkins.plugins
+ empty
+ 1.0.0-SNAPSHOT
+ hpi
+ Empty Plugin
+
+ 2.440
+ ${jenkins.baseline}.3
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+ """,
+ """
+
+
+ 4.0.0
+
+ org.jenkins-ci.plugins
+ plugin
+ 4.87
+
+
+ io.jenkins.plugins
+ empty
+ 1.0.0-SNAPSHOT
+ hpi
+ Empty Plugin
+
+ 2.452
+ ${jenkins.baseline}.4
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+ """));
+ }
+
+ @Test
+ void testPerformUpgradeWithoutBaselineWithBomAndUpgradeBomIfDoesntExistsForNewJenkinsVersion() {
+ rewriteRun(
+ spec -> spec.recipe(new UpgradeJenkinsVersion("2.452.4")),
+ pomXml(
+ """
+
+
+ 4.0.0
+
+ org.jenkins-ci.plugins
+ plugin
+ 4.87
+
+
+ io.jenkins.plugins
+ empty
+ 1.0.0-SNAPSHOT
+ hpi
+ Empty Plugin
+
+ 2.440.3
+
+
+
+
+ io.jenkins.tools.bom
+ bom-2.440.x
+ 3435.v238d66a_043fb_
+ pom
+ import
+
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+ """,
+ """
+
+
+ 4.0.0
+
+ org.jenkins-ci.plugins
+ plugin
+ 4.87
+
+
+ io.jenkins.plugins
+ empty
+ 1.0.0-SNAPSHOT
+ hpi
+ Empty Plugin
+
+ 2.452.4
+
+
+
+
+ io.jenkins.tools.bom
+ bom-2.452.x
+ %s
+ pom
+ import
+
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+ """
+ .formatted(Settings.getBomVersion())));
+ }
+
+ @Test
+ void testPerformUpgradeWithBaselineWithBomAndUpgradeBomIfDoesntExistsForNewJenkinsVersion() {
+ rewriteRun(
+ spec -> spec.recipe(new UpgradeJenkinsVersion("2.452.4")),
+ pomXml(
+ """
+
+
+ 4.0.0
+
+ org.jenkins-ci.plugins
+ plugin
+ 4.87
+
+
+ io.jenkins.plugins
+ empty
+ 1.0.0-SNAPSHOT
+ hpi
+ Empty Plugin
+
+ 2.440
+ ${jenkins.baseline}.3
+
+
+
+
+ io.jenkins.tools.bom
+ bom-2.440.x
+ 3435.v238d66a_043fb_
+ pom
+ import
+
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+ """,
+ """
+
+
+ 4.0.0
+
+ org.jenkins-ci.plugins
+ plugin
+ 4.87
+
+
+ io.jenkins.plugins
+ empty
+ 1.0.0-SNAPSHOT
+ hpi
+ Empty Plugin
+
+ 2.452
+ ${jenkins.baseline}.4
+
+
+
+
+ io.jenkins.tools.bom
+ bom-${jenkins.baseline}.x
+ %s
+ pom
+ import
+
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+ """
+ .formatted(Settings.getBomVersion())));
+ }
+}
diff --git a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/visitors/AddBeforePropertyTest.java b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/visitors/AddBeforePropertyTest.java
index d37b3e61..856f902b 100644
--- a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/visitors/AddBeforePropertyTest.java
+++ b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/visitors/AddBeforePropertyTest.java
@@ -10,7 +10,7 @@
import org.openrewrite.xml.tree.Xml;
/**
- * A visitor that add a maven property before another property.
+ * Test for {@link AddBeforePropertyVisitor}
*/
public class AddBeforePropertyTest implements RewriteTest {
diff --git a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/visitors/RemovePropertyCommentVisitorTest.java b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/visitors/RemovePropertyCommentVisitorTest.java
index c28c1acf..aa91636d 100644
--- a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/visitors/RemovePropertyCommentVisitorTest.java
+++ b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/visitors/RemovePropertyCommentVisitorTest.java
@@ -10,7 +10,7 @@
import org.openrewrite.xml.tree.Xml;
/**
- * A visitor that remove a property comment.
+ * Test for {@link RemovePropertyCommentVisitor}
*/
public class RemovePropertyCommentVisitorTest implements RewriteTest {
@@ -61,4 +61,86 @@ public Xml.Document visitDocument(Xml.Document x, ExecutionContext ctx) {
"""));
}
+
+ @Test
+ void notChangesIfCommentIsNotMatching() {
+ rewriteRun(
+ spec -> spec.recipe(toRecipe(() -> new MavenIsoVisitor<>() {
+ @Override
+ public Xml.Document visitDocument(Xml.Document x, ExecutionContext ctx) {
+ doAfterVisit(new RemovePropertyCommentVisitor(" Comment 1 "));
+ doAfterVisit(new RemovePropertyCommentVisitor(" Comment 2 "));
+ return super.visitDocument(x, ctx);
+ }
+ })),
+ pomXml(
+ """
+
+
+ 4.0.0
+ io.jenkins.plugins
+ empty
+ 1.0.0-SNAPSHOT
+ hpi
+ Empty Plugin
+
+
+
+ value
+
+ 2.440
+
+
+ """));
+ }
+
+ @Test
+ void noChangesIfEmptyProperties() {
+ rewriteRun(
+ spec -> spec.recipe(toRecipe(() -> new MavenIsoVisitor<>() {
+ @Override
+ public Xml.Document visitDocument(Xml.Document x, ExecutionContext ctx) {
+ doAfterVisit(new RemovePropertyCommentVisitor(" No property here "));
+ return super.visitDocument(x, ctx);
+ }
+ })),
+ pomXml(
+ """
+
+
+ 4.0.0
+ io.jenkins.plugins
+ empty
+ 1.0.0-SNAPSHOT
+ hpi
+ Empty Plugin
+
+
+
+ """));
+ }
+
+ @Test
+ void noChangesIfNoProperties() {
+ rewriteRun(
+ spec -> spec.recipe(toRecipe(() -> new MavenIsoVisitor<>() {
+ @Override
+ public Xml.Document visitDocument(Xml.Document x, ExecutionContext ctx) {
+ doAfterVisit(new RemovePropertyCommentVisitor(" No property here "));
+ return super.visitDocument(x, ctx);
+ }
+ })),
+ pomXml(
+ """
+
+
+ 4.0.0
+ io.jenkins.plugins
+ empty
+ 1.0.0-SNAPSHOT
+ hpi
+ Empty Plugin
+
+ """));
+ }
}