From 5dacba85099be02e6252cc166e30bc359cca7871 Mon Sep 17 00:00:00 2001 From: Valentin Delaye Date: Fri, 3 Jan 2025 12:50:53 +0100 Subject: [PATCH] Add recipe for IndexJelly and to replace a test constructor on outdated plugins --- plugin-modernizer-cli/pom.xml | 11 +- plugin-modernizer-core/pom.xml | 91 +++++-- .../core/recipes/EnsureIndexJelly.java | 159 ++++++++++++ .../ReplaceRemovedSSHLauncherConstructor.java | 71 ++++++ .../resources/META-INF/rewrite/recipes.yml | 27 ++ .../core/recipes/DeclarativeRecipesTest.java | 74 +++++- .../core/recipes/EnsureIndexJellyTest.java | 237 ++++++++++++++++++ ...laceRemovedSSHLauncherConstructorTest.java | 69 +++++ 8 files changed, 707 insertions(+), 32 deletions(-) create mode 100644 plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/EnsureIndexJelly.java create mode 100644 plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/code/ReplaceRemovedSSHLauncherConstructor.java create mode 100644 plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/EnsureIndexJellyTest.java create mode 100644 plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/code/ReplaceRemovedSSHLauncherConstructorTest.java diff --git a/plugin-modernizer-cli/pom.xml b/plugin-modernizer-cli/pom.xml index 24db2817..7b91df32 100644 --- a/plugin-modernizer-cli/pom.xml +++ b/plugin-modernizer-cli/pom.xml @@ -32,8 +32,17 @@ io.jenkins.plugin-modernizer plugin-modernizer-core ${changelist} - + + + io.jenkins.plugins + * + + + org.jenkins-ci.plugins + * + org.openrewrite * diff --git a/plugin-modernizer-core/pom.xml b/plugin-modernizer-core/pom.xml index 2cb2dabe..cdf0f89f 100644 --- a/plugin-modernizer-core/pom.xml +++ b/plugin-modernizer-core/pom.xml @@ -10,6 +10,19 @@ plugin-modernizer-core Plugin Modernizer Core + + + + + io.jenkins.tools.bom + bom-2.479.x + 3875.v1df09947cde6 + pom + import + + + + com.fasterxml.jackson.dataformat @@ -160,6 +173,7 @@ jjwt-impl runtime + ch.qos.logback logback-classic @@ -171,26 +185,6 @@ 0.0.12 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 rewrite-test @@ -202,6 +196,7 @@ 2.1.7 test + @@ -239,15 +234,44 @@ 3.8.1 - copy-dependencies + copy - copy-dependencies + copy validate - ${project.build.directory}/openrewrite-classpath - - javax.servlet,jakarta.servlet,org.kohsuke.stapler + ${project.build.directory}/openrewrite-jars + + + + + + org.kohsuke.stapler + stapler + 1928.v9115fe47607f + + + jakarta.servlet + jakarta.servlet-api + 6.1.0 + + + javax.servlet + javax.servlet-api + 4.0.1 + + + + org.jenkins-ci.plugins + ssh-slaves + 1.12 + + + org.jenkins-ci.plugins + ssh-slaves + 3.1021.va_cc11b_de26a_e + + @@ -315,4 +339,21 @@ + + + + + recipes-dependencies + + true + + + + org.jenkins-ci.plugins + ssh-slaves + + + + + diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/EnsureIndexJelly.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/EnsureIndexJelly.java new file mode 100644 index 00000000..34412f81 --- /dev/null +++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/EnsureIndexJelly.java @@ -0,0 +1,159 @@ +package io.jenkins.tools.pluginmodernizer.core.recipes; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import io.jenkins.tools.pluginmodernizer.core.extractor.ArchetypeCommonFile; +import io.jenkins.tools.pluginmodernizer.core.extractor.PluginMetadata; +import io.jenkins.tools.pluginmodernizer.core.extractor.PomResolutionVisitor; +import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import org.intellij.lang.annotations.Language; +import org.openrewrite.Cursor; +import org.openrewrite.ExecutionContext; +import org.openrewrite.ScanningRecipe; +import org.openrewrite.SourceFile; +import org.openrewrite.Tree; +import org.openrewrite.TreeVisitor; +import org.openrewrite.maven.MavenIsoVisitor; +import org.openrewrite.text.PlainText; +import org.openrewrite.xml.tree.Xml; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Ensure `index.jelly` exists + */ +public class EnsureIndexJelly extends ScanningRecipe { + + /** + * Jelly file + */ + @Language("xml") + public static final String JELLY_FILE = + """ + +
+ DESCRIPTION +
+ """; + + /** + * LOGGER. + */ + private static final Logger LOG = LoggerFactory.getLogger(EnsureIndexJelly.class); + + @Override + public String getDisplayName() { + return "Create `index.jelly` if it doesn't exist"; + } + + @Override + public String getDescription() { + return "Jenkins tooling [requires](https://github.com/jenkinsci/maven-hpi-plugin/pull/302) " + + "`src/main/resources/index.jelly` exists with a description."; + } + + @Override + public ShouldCreate getInitialValue(ExecutionContext ctx) { + return new ShouldCreate(); + } + + @Override + @SuppressFBWarnings("NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE") + public TreeVisitor getScanner(ShouldCreate shouldCreate) { + PluginMetadata metadata = new PluginMetadata(); + return new TreeVisitor<>() { + @Override + public Tree visit(Tree tree, ExecutionContext ctx) { + SourceFile sourceFile = (SourceFile) tree; + // We visit a jelly + if (sourceFile.getSourcePath().endsWith(ArchetypeCommonFile.INDEX_JELLY.getPath())) { + LOG.info("Found 1 index.jelly a Will not replace it"); + shouldCreate.jelliesPath.add(sourceFile.getSourcePath()); + return tree; + } + // We visit a pom + if (sourceFile.getSourcePath().endsWith(ArchetypeCommonFile.POM.getPath())) { + new PomResolutionVisitor().reduce(sourceFile, metadata); + if (metadata.getJenkinsVersion() == null) { + LOG.info("Skipping pom {} as it is not a Jenkins plugin", sourceFile.getSourcePath()); + return tree; + } + Path jellyPath = sourceFile + .getSourcePath() + .resolve("..") + .resolve(ArchetypeCommonFile.INDEX_JELLY.getPath()) + .normalize(); + Xml.Document pom = (Xml.Document) sourceFile; + DescriptionVisitor descriptionVisitor = new DescriptionVisitor(); + descriptionVisitor.visitNonNull(pom, ctx); + if (!descriptionVisitor.description.isEmpty()) { + shouldCreate.plugins.put(jellyPath, descriptionVisitor.description); + } else if (!descriptionVisitor.artifactId.isEmpty()) { + shouldCreate.plugins.put(jellyPath, descriptionVisitor.artifactId); + } + LOG.debug(shouldCreate.toString()); + } + return tree; + } + }; + } + + /** + * Visitor to extract the metadata from the POM file. + */ + private static class DescriptionVisitor extends MavenIsoVisitor { + private String artifactId = ""; + private String description = ""; + + @Override + public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { + Cursor parent = getCursor().getParentOrThrow(); + if (!(parent.getValue() instanceof Xml.Tag)) { + return super.visitTag(tag, ctx); + } + Xml.Tag parentTag = parent.getValue(); + if (!parentTag.getName().equals("project")) { + return super.visitTag(tag, ctx); + } + if ("description".equals(tag.getName())) { + description = tag.getValue().orElse(""); + } else if ("artifactId".equals(tag.getName()) && !isManagedDependencyTag() && !isDependencyTag()) { + artifactId = + tag.getValue().orElseThrow(() -> new IllegalStateException("Expected to find an artifact id")); + } + return super.visitTag(tag, ctx); + } + } + + /** + * Accumulator to know if the file should be created or not and with which description. + */ + public static class ShouldCreate { + private Map plugins = new HashMap<>(); + private List jelliesPath = new LinkedList<>(); + } + + @Override + public Collection generate(ShouldCreate shouldCreate, ExecutionContext ctx) { + if (shouldCreate.plugins.isEmpty()) { + return Collections.emptyList(); + } + List generated = new LinkedList<>(); + for (Map.Entry plugin : shouldCreate.plugins.entrySet()) { + if (shouldCreate.jelliesPath.contains(plugin.getKey())) { + continue; + } + LOG.info("Creating index.jelly at " + plugin.getKey() + " with description " + plugin.getValue()); + generated.add(PlainText.builder() + .sourcePath(plugin.getKey()) + .text(JELLY_FILE.replace("DESCRIPTION", plugin.getValue())) + .build()); + } + return generated; + } +} diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/code/ReplaceRemovedSSHLauncherConstructor.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/code/ReplaceRemovedSSHLauncherConstructor.java new file mode 100644 index 00000000..ae12ab38 --- /dev/null +++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/code/ReplaceRemovedSSHLauncherConstructor.java @@ -0,0 +1,71 @@ +package io.jenkins.tools.pluginmodernizer.core.recipes.code; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.NlsRewrite; +import org.openrewrite.Preconditions; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.JavaParser; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.search.IsLikelyTest; +import org.openrewrite.java.tree.J; + +/** + * A recipe that update the bom version to latest available. + */ +public class ReplaceRemovedSSHLauncherConstructor extends Recipe { + + @Override + public @NlsRewrite.DisplayName String getDisplayName() { + return "Replace a remove SSHLauncher constructor"; + } + + @Override + public @NlsRewrite.Description String getDescription() { + return "Replace a remove SSHLauncher constructor."; + } + + @Override + public TreeVisitor getVisitor() { + // Only run on test files + return Preconditions.check(new IsLikelyTest(), new UseDataBoundConstructor()); + } + + /** + * Visitor that replace the removed SSHLauncher removed constructor by the new one. + */ + public static class UseDataBoundConstructor extends JavaIsoVisitor { + + // We will replace by the @DataBoundConstructor + JavaTemplate newConstructorTemplate = JavaTemplate.builder( + "new SSHLauncher(#{any(java.lang.String)}, #{any(int)}, null)") + .imports("hudson.plugins.sshslaves.SSHLauncher") + .javaParser(JavaParser.fromJavaVersion().classpath("ssh-slaves")) + .build(); + + @Override + public J.NewClass visitNewClass(J.NewClass newClass, ExecutionContext ctx) { + newClass = super.visitNewClass(newClass, ctx); + if (newClass.getConstructorType() == null) { + return newClass; + } + if (!newClass.getConstructorType() + .getDeclaringType() + .getFullyQualifiedName() + .equals("hudson.plugins.sshslaves.SSHLauncher")) { + return newClass; + } + // Replace removed 6 arguments constructor with 3 arguments constructor + // See https://github.com/jenkinsci/ssh-agents-plugin/commit/f540572d7819bec840605227636de319a192bc84 + if (newClass.getArguments().size() == 6) { + return newConstructorTemplate.apply( + updateCursor(newClass), + newClass.getCoordinates().replace(), + newClass.getArguments().get(0), + newClass.getArguments().get(1)); + } + return newClass; + } + } +} 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 5051418f..12657158 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 @@ -149,6 +149,8 @@ description: Upgrade to the next major parent version (5.X) requiring Jenkins 2. tags: ['dependencies'] recipeList: - io.jenkins.tools.pluginmodernizer.core.recipes.EnsureRelativePath + - io.jenkins.tools.pluginmodernizer.EnsureIndexJelly + - io.jenkins.tools.pluginmodernizer.core.recipes.UpdateScmUrl - org.openrewrite.maven.UpgradeParentVersion: groupId: org.jenkins-ci.plugins artifactId: plugin @@ -399,6 +401,8 @@ description: Upgrade to the latest recommended core version and ensure the BOM m tags: ['developer'] recipeList: - io.jenkins.tools.pluginmodernizer.core.recipes.EnsureRelativePath + - io.jenkins.tools.pluginmodernizer.EnsureIndexJelly + - io.jenkins.tools.pluginmodernizer.core.recipes.UpdateScmUrl - io.jenkins.tools.pluginmodernizer.UpgradeParentVersion - io.jenkins.tools.pluginmodernizer.core.recipes.UpgradeJenkinsVersion: minimumVersion: 2.452.4 @@ -414,6 +418,8 @@ description: Upgrade to latest LTS core version supporting Java 11. tags: ['developer'] recipeList: - io.jenkins.tools.pluginmodernizer.core.recipes.EnsureRelativePath + - io.jenkins.tools.pluginmodernizer.EnsureIndexJelly + - io.jenkins.tools.pluginmodernizer.core.recipes.UpdateScmUrl - io.jenkins.tools.pluginmodernizer.UpgradeParentVersion - io.jenkins.tools.pluginmodernizer.core.recipes.UpgradeJenkinsVersion: minimumVersion: 2.462.3 @@ -421,6 +427,11 @@ recipeList: - io.jenkins.tools.pluginmodernizer.RemoveExtraMavenProperties - io.jenkins.tools.pluginmodernizer.UpgradeBomVersion - io.jenkins.tools.pluginmodernizer.MigrateToJenkinsBaseLineProperty + - org.openrewrite.maven.UpgradeDependencyVersion: # Latest using Java 11 support + groupId: org.jenkins-ci.test + artifactId: docker-fixtures + newVersion: 190.vd6a_e600cb_775 + versionPattern: "\\.v[a-f0-9_]+" --- type: specs.openrewrite.org/v1beta/recipe name: io.jenkins.tools.pluginmodernizer.UpgradeToLatestJava8CoreVersion @@ -429,6 +440,8 @@ description: Upgrade to latest LTS core version supporting Java 8. tags: ['developer'] recipeList: - io.jenkins.tools.pluginmodernizer.core.recipes.EnsureRelativePath + - io.jenkins.tools.pluginmodernizer.EnsureIndexJelly + - io.jenkins.tools.pluginmodernizer.core.recipes.UpdateScmUrl - org.openrewrite.maven.UpgradeParentVersion: groupId: org.jenkins-ci.plugins artifactId: plugin @@ -436,10 +449,16 @@ recipeList: - io.jenkins.tools.pluginmodernizer.core.recipes.UpgradeJenkinsVersion: minimumVersion: 2.346.3 - io.jenkins.tools.pluginmodernizer.RemoveDependencyVersionOverride + - io.jenkins.tools.pluginmodernizer.core.recipes.code.ReplaceRemovedSSHLauncherConstructor - io.jenkins.tools.pluginmodernizer.RemoveExtraMavenProperties - io.jenkins.tools.pluginmodernizer.UpgradeBomVersion - io.jenkins.tools.pluginmodernizer.MigrateToJenkinsBaseLineProperty - org.openrewrite.java.RemoveUnusedImports + - org.openrewrite.maven.UpgradeDependencyVersion: # Latest using Java 8 support + groupId: org.jenkins-ci.test + artifactId: docker-fixtures + newVersion: 170.v2339def98d76 + versionPattern: "\\.v[a-f0-9_]+" --- type: specs.openrewrite.org/v1beta/recipe name: io.jenkins.tools.pluginmodernizer.SetupDependabot @@ -492,3 +511,11 @@ tags: ['condition'] recipeList: - org.openrewrite.jenkins.IsJenkinsPlugin: version: "[2.489,)" # Adapt when LTS +--- +type: specs.openrewrite.org/v1beta/recipe +name: io.jenkins.tools.pluginmodernizer.EnsureIndexJelly +displayName: Create `index.jelly` if it doesn't exist +description: Jenkins tooling [requires](https://github.com/jenkinsci/maven-hpi-plugin/pull/302) `src/main/resources/index.jelly` exists with a description. +tags: ['chore'] +recipeList: + - io.jenkins.tools.pluginmodernizer.core.recipes.EnsureIndexJelly 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 0dc0c2f6..82bbc595 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,7 +1,10 @@ package io.jenkins.tools.pluginmodernizer.core.recipes; import static org.openrewrite.groovy.Assertions.groovy; -import static org.openrewrite.java.Assertions.*; +import static org.openrewrite.java.Assertions.java; +import static org.openrewrite.java.Assertions.mavenProject; +import static org.openrewrite.java.Assertions.srcMainResources; +import static org.openrewrite.java.Assertions.srcTestJava; import static org.openrewrite.maven.Assertions.pomXml; import static org.openrewrite.test.SourceSpecs.text; import static org.openrewrite.yaml.Assertions.yaml; @@ -9,6 +12,7 @@ import io.github.yamlpath.YamlPath; import io.jenkins.tools.pluginmodernizer.core.config.Settings; import io.jenkins.tools.pluginmodernizer.core.extractor.ArchetypeCommonFile; +import io.jenkins.tools.pluginmodernizer.core.recipes.code.ReplaceRemovedSSHLauncherConstructorTest; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -792,6 +796,16 @@ void upgradeToUpgradeToLatestJava11CoreVersion() { "/META-INF/rewrite/recipes.yml", "io.jenkins.tools.pluginmodernizer.UpgradeToLatestJava11CoreVersion"), // language=xml + srcMainResources(text( + null, + """ + +
+ empty +
+ """, + s -> s.path(ArchetypeCommonFile.INDEX_JELLY.getPath().getFileName()))), + // language=xml pomXml( """ @@ -807,6 +821,9 @@ void upgradeToUpgradeToLatestJava11CoreVersion() { 1.0.0-SNAPSHOT hpi Empty Plugin + + scm:git:git://github.com/jenkinsci/empty-plugin.git + 2.440.3 @@ -850,6 +867,9 @@ void upgradeToUpgradeToLatestJava11CoreVersion() { 1.0.0-SNAPSHOT hpi Empty Plugin + + scm:git:https://github.com/jenkinsci/empty-plugin.git + 2.462 @@ -886,9 +906,29 @@ void upgradeToUpgradeToLatestJava11CoreVersion() { @Test void upgradeToUpgradeToLatestJava8CoreVersion() { rewriteRun( - spec -> spec.recipeFromResource( - "/META-INF/rewrite/recipes.yml", - "io.jenkins.tools.pluginmodernizer.UpgradeToLatestJava8CoreVersion"), + spec -> { + var parser = JavaParser.fromJavaVersion().logCompilationWarningsAndErrors(true); + collectRewriteTestDependencies().stream() + .filter(entry -> entry.getFileName().toString().contains("ssh-slaves-1.12")) + .forEach(parser::addClasspathEntry); + spec.recipeFromResource( + "/META-INF/rewrite/recipes.yml", + "io.jenkins.tools.pluginmodernizer.UpgradeToLatestJava8CoreVersion") + .parser(parser); + }, + // language=java + srcTestJava(java( + ReplaceRemovedSSHLauncherConstructorTest.BEFORE, + ReplaceRemovedSSHLauncherConstructorTest.AFTER)), + srcMainResources(text( + null, + """ + +
+ empty +
+ """, + s -> s.path(ArchetypeCommonFile.INDEX_JELLY.getPath().getFileName()))), // language=xml pomXml( """ @@ -906,6 +946,9 @@ void upgradeToUpgradeToLatestJava8CoreVersion() { 1.0.0-SNAPSHOT hpi Empty Plugin + + scm:git:git://github.com/jenkinsci/empty-plugin.git + 2.303.3 @@ -949,6 +992,9 @@ void upgradeToUpgradeToLatestJava8CoreVersion() { 1.0.0-SNAPSHOT hpi Empty Plugin + + scm:git:https://github.com/jenkinsci/empty-plugin.git + 2.346 @@ -994,6 +1040,16 @@ void upgradeNextMajorParentVersionTest() { }, mavenProject("test"), // language=xml + srcMainResources(text( + null, + """ + +
+ empty +
+ """, + s -> s.path(ArchetypeCommonFile.INDEX_JELLY.getPath().getFileName()))), + // language=xml pomXml( """ @@ -1009,6 +1065,9 @@ void upgradeNextMajorParentVersionTest() { 1.0.0-SNAPSHOT hpi Empty Plugin + + scm:git:https://github.com/jenkinsci/empty-plugin.git + 11 2.440.3 @@ -1045,6 +1104,9 @@ void upgradeNextMajorParentVersionTest() { 1.0.0-SNAPSHOT hpi Empty Plugin + + scm:git:https://github.com/jenkinsci/empty-plugin.git + 2.479.1 @@ -2253,9 +2315,9 @@ void shouldAddSecurityScan() { * * @return List of Path */ - private List collectRewriteTestDependencies() { + public static List collectRewriteTestDependencies() { try { - List entries = Files.list(Path.of("target/openrewrite-classpath")) + List entries = Files.list(Path.of("target/openrewrite-jars")) .filter(p -> p.toString().endsWith(".jar")) .toList(); LOG.debug("Collected rewrite test dependencies: {}", entries); diff --git a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/EnsureIndexJellyTest.java b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/EnsureIndexJellyTest.java new file mode 100644 index 00000000..5fe7a62a --- /dev/null +++ b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/EnsureIndexJellyTest.java @@ -0,0 +1,237 @@ +package io.jenkins.tools.pluginmodernizer.core.recipes; + +import static org.openrewrite.java.Assertions.mavenProject; +import static org.openrewrite.java.Assertions.srcMainResources; +import static org.openrewrite.maven.Assertions.pomXml; +import static org.openrewrite.test.SourceSpecs.text; + +import io.jenkins.tools.pluginmodernizer.core.extractor.ArchetypeCommonFile; +import org.junit.jupiter.api.Test; +import org.openrewrite.test.RewriteTest; + +/** + * Test for {@link EnsureIndexJelly}. + */ +public class EnsureIndexJellyTest implements RewriteTest { + + @Test + void shouldNotReplaceJellyFile() { + rewriteRun(spec -> spec.recipe(new EnsureIndexJelly()), text("jelly", sourceSpecs -> { + sourceSpecs.path(ArchetypeCommonFile.INDEX_JELLY.getPath()); + })); + } + + @Test + void createFromDescription() { + rewriteRun( + spec -> spec.recipe(new EnsureIndexJelly()), + // language=xml + pomXml( + """ + + + org.jenkins-ci.plugins + plugin + 4.88 + + empty + The empty plugin + 1.0.0-SNAPSHOT + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + + """), + text( + null, + """ + +
+ The empty plugin +
+ """, + s -> s.path(ArchetypeCommonFile.INDEX_JELLY.getPath()))); + } + + @Test + void createNoCreateIfNotAPlugin() { + rewriteRun( + spec -> spec.recipe(new EnsureIndexJelly()), + // language=xml + pomXml( + """ + + not-plugin + Not a plugin + org.example + 1.0.0-SNAPSHOT + + """)); + } + + @Test + void createFromArtifactIdEmptyDescription() { + rewriteRun( + spec -> spec.recipe(new EnsureIndexJelly()), + // language=xml + pomXml( + """ + + + org.jenkins-ci.plugins + plugin + 4.88 + + empty + + 1.0.0-SNAPSHOT + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + + """), + text( + null, + """ + +
+ empty +
+ """, + s -> s.path(ArchetypeCommonFile.INDEX_JELLY.getPath()))); + } + + @Test + void createFromArtifactIdNoDescription() { + rewriteRun( + spec -> spec.recipe(new EnsureIndexJelly()), + // language=xml + pomXml( + """ + + + org.jenkins-ci.plugins + plugin + 4.88 + + empty + 1.0.0-SNAPSHOT + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + + """), + text( + null, + """ + +
+ empty +
+ """, + s -> s.path("src/main/resources/index.jelly"))); + } + + @Test + void shouldCreateMultipleNestedIndexJellies() { + rewriteRun( + spec -> spec.recipe(new EnsureIndexJelly()), + mavenProject( + "parent", + // language=xml + pomXml( + """ + + org.example + my-root + 0.1 + pom + + plugin + other-plugin + not-a-plugin + + + """), + mavenProject( + "plugin", + pomXml( + """ + + + org.jenkins-ci.plugins + plugin + 4.86 + + plugin + 1.0.0-SNAPSHOT + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + + """), + srcMainResources(text( + null, + """ + +
+ plugin +
+ """, + s -> s.path(ArchetypeCommonFile.INDEX_JELLY + .getPath() + .getFileName() + .toString())))), + mavenProject( + "other-plugin", + pomXml( + """ + + + org.jenkins-ci.plugins + plugin + 4.88 + + other-plugin + 1.0.0-SNAPSHOT + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + + """), + srcMainResources(text( + null, + """ + +
+ other-plugin +
+ """, + s -> s.path("index.jelly")))), + mavenProject( + "non-plugin", + pomXml( + """ + + org.example + not-a-plugin + 1.0.0-SNAPSHOT + + """)))); + } +} diff --git a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/code/ReplaceRemovedSSHLauncherConstructorTest.java b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/code/ReplaceRemovedSSHLauncherConstructorTest.java new file mode 100644 index 00000000..0394ba9d --- /dev/null +++ b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/code/ReplaceRemovedSSHLauncherConstructorTest.java @@ -0,0 +1,69 @@ +package io.jenkins.tools.pluginmodernizer.core.recipes.code; + +import static org.openrewrite.java.Assertions.java; +import static org.openrewrite.java.Assertions.srcTestJava; + +import io.jenkins.tools.pluginmodernizer.core.recipes.DeclarativeRecipesTest; +import org.intellij.lang.annotations.Language; +import org.junit.jupiter.api.Test; +import org.openrewrite.java.JavaParser; +import org.openrewrite.test.RewriteTest; + +/** + * Test for {@link ReplaceRemovedSSHLauncherConstructor} + */ +public class ReplaceRemovedSSHLauncherConstructorTest implements RewriteTest { + + @Language("java") + public static final String BEFORE = + """ + import hudson.plugins.sshslaves.SSHLauncher; + + public class Foo { + public void foo() { + SSHLauncher launcher = new SSHLauncher("127.0.0.1", 22, "username", "password", "privatekey", "jvmOptions"); + } + } + """; + + @Language("java") + public static final String AFTER = + """ + import hudson.plugins.sshslaves.SSHLauncher; + + public class Foo { + public void foo() { + SSHLauncher launcher = new SSHLauncher("127.0.0.1", 22, null); + } + } + """; + + @Test + void replaceConstructor() { + rewriteRun( + spec -> { + var parser = JavaParser.fromJavaVersion().logCompilationWarningsAndErrors(true); + DeclarativeRecipesTest.collectRewriteTestDependencies().stream() + .filter(entry -> entry.getFileName().toString().contains("ssh-slaves-1.12")) + .forEach(parser::addClasspathEntry); + spec.recipe(new ReplaceRemovedSSHLauncherConstructor()).parser(parser); + }, + // language=java + srcTestJava(java(BEFORE, AFTER))); + } + + @Test + void keepConstructor() { + rewriteRun( + spec -> { + var parser = JavaParser.fromJavaVersion().logCompilationWarningsAndErrors(true); + DeclarativeRecipesTest.collectRewriteTestDependencies().stream() + .filter(entry -> + entry.getFileName().toString().contains("ssh-slaves-3.1021.va_cc11b_de26a_e")) + .forEach(parser::addClasspathEntry); + spec.recipe(new ReplaceRemovedSSHLauncherConstructor()).parser(parser); + }, + // language=java + srcTestJava(java(AFTER))); + } +}