Skip to content

Commit

Permalink
Merge pull request #604 from jonesbusy/feature/java-file-visitor
Browse files Browse the repository at this point in the history
Add a Java ISO visitor for metadata collection
  • Loading branch information
jonesbusy authored Jan 11, 2025
2 parents b0bc748 + 4c6672a commit d800e48
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 11 deletions.
11 changes: 11 additions & 0 deletions plugin-modernizer-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,17 @@
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<!-- Testcontainers and docker-fixtures to check if package exists -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.20.4</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.test</groupId>
<artifactId>docker-fixtures</artifactId>
<version>200.v22a_e8766731c</version>
</dependency>
<!-- SSH slave migration from 1.12 to latest -->
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.jenkins.tools.pluginmodernizer.core.extractor;

import org.openrewrite.java.JavaIsoVisitor;
import org.openrewrite.java.tree.J;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* A visitor to extract metadata from Java files.
*/
public class JavaFileVisitor extends JavaIsoVisitor<PluginMetadata> {

/**
* LOGGER.
*/
private static final Logger LOG = LoggerFactory.getLogger(JavaFileVisitor.class);

@Override
public J.Import visitImport(J.Import _import, PluginMetadata pluginMetadata) {
_import = super.visitImport(_import, pluginMetadata);
// Rather a naive approach, but let's assume we can detect testcontainers usage by the package name
if (_import.getPackageName().startsWith("org.testcontainers.containers")) {
LOG.info("Found testcontainers import: {}. Plugin is using container tests", _import.getPackageName());
pluginMetadata.setUseContainerTests(true);
}
if (_import.getPackageName().startsWith("org.jenkinsci.test.acceptance.docker")) {
LOG.info("Found docker-fixtures import: {}. Plugin is using container tests", _import.getPackageName());
pluginMetadata.setUseContainerTests(true);
}
return _import;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package io.jenkins.tools.pluginmodernizer.core.extractor;

import io.jenkins.tools.pluginmodernizer.core.utils.JsonUtils;
import static io.jenkins.tools.pluginmodernizer.core.utils.JsonUtils.fromJson;
import static io.jenkins.tools.pluginmodernizer.core.utils.JsonUtils.merge;
import static io.jenkins.tools.pluginmodernizer.core.utils.JsonUtils.toJson;

import org.openrewrite.ExecutionContext;
import org.openrewrite.Tree;
import org.openrewrite.TreeVisitor;
Expand All @@ -22,22 +25,24 @@ public Tree visit(Tree tree, ExecutionContext ctx) {

PluginMetadata mergedMetadata = ctx.getMessage("mergedMetadata", new PluginMetadata());
PluginMetadata commonMetadata = ctx.getMessage("commonMetadata", new PluginMetadata());
PluginMetadata pluginMetadata = ctx.getMessage("pomMetadata", new PluginMetadata());
PluginMetadata pomMetadata = ctx.getMessage("pomMetadata", new PluginMetadata());
PluginMetadata javaMetadata = ctx.getMessage("javaMetadata", new PluginMetadata());
PluginMetadata jenkinsFileMetadata = ctx.getMessage("jenkinsFileMetadata", new PluginMetadata());

// Merge the metadata
PluginMetadata merged = JsonUtils.fromJson(
JsonUtils.merge(pluginMetadata.toJson(), jenkinsFileMetadata.toJson()), PluginMetadata.class);
merged = JsonUtils.fromJson(JsonUtils.merge(commonMetadata.toJson(), merged.toJson()), PluginMetadata.class);
merged = JsonUtils.fromJson(JsonUtils.merge(mergedMetadata.toJson(), merged.toJson()), PluginMetadata.class);
PluginMetadata merged =
fromJson(merge(pomMetadata.toJson(), jenkinsFileMetadata.toJson()), PluginMetadata.class);
merged = fromJson(merge(commonMetadata.toJson(), merged.toJson()), PluginMetadata.class);
merged = fromJson(merge(javaMetadata.toJson(), merged.toJson()), PluginMetadata.class);
merged = fromJson(merge(mergedMetadata.toJson(), merged.toJson()), PluginMetadata.class);

LOG.debug("Merged metadata: {}", JsonUtils.toJson(merged));
LOG.debug("Merged metadata: {}", toJson(merged));

// Write the metadata to a file for later use by the plugin modernizer.
merged.save();
LOG.debug("Plugin metadata written to {}", merged.getRelativePath());
ctx.putMessage("mergedMetadata", merged);
LOG.debug(JsonUtils.toJson(merged));
LOG.debug(toJson(merged));

return tree;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ else if (PathUtils.matchesGlob(sourceFile.getSourcePath(), "**/pom.xml")) {
executionContext.putMessage("pomMetadata", pomMetadata); // Is there better than context messaging ?
return tree;
}
// Extract metadata from java file
else if (PathUtils.matchesGlob(sourceFile.getSourcePath(), "**/*.java")) {
LOG.debug("Visiting Java file {}", sourceFile.getSourcePath());
PluginMetadata javaMetadata = new JavaFileVisitor().reduce(tree, commonMetadata);
LOG.debug("Java metadata: {}", JsonUtils.toJson(javaMetadata));
executionContext.putMessage("javaMetadata", javaMetadata); // Is there better than context messaging ?
return tree;
}

// Just add the common
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
Expand Down Expand Up @@ -53,6 +54,11 @@ public class PluginMetadata extends CacheEntry<PluginMetadata> {
*/
private Boolean useContainerAgent;

/**
* If the plugin is using container tests
*/
private Boolean useContainerTests;

/**
* forkCount extracted from Jenkinsfile
*/
Expand Down Expand Up @@ -240,6 +246,14 @@ public void setUseContainerAgent(Boolean useContainerAgent) {
this.useContainerAgent = useContainerAgent;
}

public Boolean isUseContainerTests() {
return Objects.requireNonNullElse(useContainerTests, false);
}

public void setUseContainerTests(Boolean useContainerTests) {
this.useContainerTests = useContainerTests;
}

public String getForkCount() {
return forkCount;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import io.jenkins.tools.pluginmodernizer.core.model.JDK;
import io.jenkins.tools.pluginmodernizer.core.model.Platform;
import io.jenkins.tools.pluginmodernizer.core.recipes.DeclarativeRecipesTest;
import io.jenkins.tools.pluginmodernizer.core.recipes.FetchMetadata;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
Expand All @@ -19,6 +20,7 @@
import org.intellij.lang.annotations.Language;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openrewrite.java.JavaParser;
import org.openrewrite.test.RewriteTest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -40,6 +42,7 @@ public class FetchMetadataTest implements RewriteTest {
EXPECTED_METADATA.setBomArtifactId("bom-2.414.x");
EXPECTED_METADATA.setBomVersion("2950.va_633b_f42f759");
EXPECTED_METADATA.setUseContainerAgent(null);
EXPECTED_METADATA.setUseContainerTests(null);
EXPECTED_METADATA.setForkCount(null);
Map<String, String> properties = new LinkedHashMap<>();
properties.put("revision", "1.8.1");
Expand Down Expand Up @@ -295,9 +298,15 @@ class FooBar {}
}

@Test
void testWithManyCommonFiles() throws Exception {
void testWithManyCommonFilesAndTestContainers() throws Exception {
rewriteRun(
recipeSpec -> recipeSpec.recipe(new FetchMetadata()),
spec -> {
var parser = JavaParser.fromJavaVersion().logCompilationWarningsAndErrors(true);
DeclarativeRecipesTest.collectRewriteTestDependencies().stream()
.filter(entry -> entry.getFileName().toString().contains("testcontainers"))
.forEach(parser::addClasspathEntry);
spec.recipe(new FetchMetadata()).parser(parser);
},
pomXml(POM_XML),
// language=groovy
groovy(
Expand All @@ -314,6 +323,7 @@ void testWithManyCommonFiles() throws Exception {
java(
"""
package com.uppercase.camelcase;
import org.testcontainers.containers.GenericContainer;
class FooBar {}
"""),
// language=yaml
Expand Down Expand Up @@ -356,7 +366,8 @@ class FooBar {}
// Check rest
Set<JDK> jdkVersion = pluginMetadata.getJdks();
assertEquals(2, jdkVersion.size());
assertTrue(pluginMetadata.isUseContainerAgent());
assertTrue(pluginMetadata.isUseContainerAgent(), "Should use container agent");
assertTrue(pluginMetadata.isUseContainerTests(), "Should use container tests");
assertEquals(EXPECTED_METADATA.getParentVersion(), pluginMetadata.getParentVersion());
assertEquals(EXPECTED_METADATA.getPluginName(), pluginMetadata.getPluginName());
assertEquals(EXPECTED_METADATA.getJenkinsVersion(), pluginMetadata.getJenkinsVersion());
Expand All @@ -365,6 +376,31 @@ class FooBar {}
assertEquals(EXPECTED_METADATA.getFlags(), pluginMetadata.getFlags());
}

@Test
void testWithDockerFixtures() throws Exception {
rewriteRun(
spec -> {
var parser = JavaParser.fromJavaVersion().logCompilationWarningsAndErrors(true);
DeclarativeRecipesTest.collectRewriteTestDependencies().stream()
.filter(entry -> entry.getFileName().toString().contains("docker-fixtures"))
.forEach(parser::addClasspathEntry);
spec.recipe(new FetchMetadata()).parser(parser);
},
// language=java
java(
"""
package com.uppercase.camelcase;
import org.jenkinsci.test.acceptance.docker.DockerClassRule;
class FooBar {}
"""));

PluginMetadata pluginMetadata = new PluginMetadata().refresh();
assertNotNull(pluginMetadata, "Plugin metadata was not written by the recipe");

// Check use container test
assertTrue(pluginMetadata.isUseContainerTests(), "Should use container tests");
}

@Test
void testWithJenkinsfileOnly() throws Exception {
rewriteRun(
Expand Down Expand Up @@ -398,6 +434,8 @@ void testWithJenkinsfileOnly() throws Exception {
assertEquals(2, platforms.size());
assertTrue(platforms.contains(Platform.WINDOWS));
assertTrue(platforms.contains(Platform.LINUX));

assertFalse(pluginMetadata.isUseContainerTests());
}

@Test
Expand Down

0 comments on commit d800e48

Please sign in to comment.