Skip to content

Commit a8da6e6

Browse files
committed
Copy metadata instead of moving it and store it as a marker for further recipes
1 parent 563d078 commit a8da6e6

11 files changed

Lines changed: 196 additions & 95 deletions

File tree

plugin-modernizer-cli/pom.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@
4949
<artifactId>maven-invoker</artifactId>
5050
<version>3.3.0</version>
5151
</dependency>
52+
<dependency>
53+
<groupId>org.openrewrite</groupId>
54+
<artifactId>rewrite-core</artifactId>
55+
</dependency>
5256
<dependency>
5357
<groupId>org.slf4j</groupId>
5458
<artifactId>jcl-over-slf4j</artifactId>
@@ -61,12 +65,12 @@
6165
<groupId>org.slf4j</groupId>
6266
<artifactId>slf4j-api</artifactId>
6367
</dependency>
68+
<!-- Test dependencies -->
6469
<dependency>
6570
<groupId>io.github.sparsick.testcontainers.gitserver</groupId>
6671
<artifactId>testcontainers-gitserver</artifactId>
6772
<scope>test</scope>
6873
</dependency>
69-
<!-- Test dependencies -->
7074
<dependency>
7175
<groupId>org.apache.maven</groupId>
7276
<artifactId>apache-maven</artifactId>

plugin-modernizer-cli/src/test/java/io/jenkins/tools/pluginmodernizer/cli/CommandLineITCase.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,8 @@ public void testBuildMetadata(PluginMetadata expectedMetadata, WireMockRuntimeIn
263263
.resolve(CacheManager.PLUGIN_METADATA_CACHE_KEY),
264264
PluginMetadata.class);
265265

266-
// Metadata should be still present on target folder (it should be copied to be reused by recipes not aware of the
266+
// Metadata should be still present on target folder (it should be copied to be reused by recipes not aware
267+
// of the
267268
// cache or external storage)
268269
assertTrue(Files.exists(cachePath
269270
.resolve("jenkins-plugin-modernizer-cli")

plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/extractor/MetadataCollector.java

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,23 @@
33
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
44
import io.jenkins.tools.pluginmodernizer.core.model.JDK;
55
import io.jenkins.tools.pluginmodernizer.core.utils.JsonUtils;
6-
import java.util.ArrayList;
76
import java.util.Arrays;
87
import java.util.HashMap;
9-
import java.util.HashSet;
8+
import java.util.LinkedHashSet;
9+
import java.util.LinkedList;
1010
import java.util.List;
1111
import java.util.Map;
1212
import java.util.Optional;
1313
import java.util.Set;
1414
import java.util.stream.Collectors;
1515
import java.util.stream.Stream;
16-
import org.openrewrite.ExecutionContext;
17-
import org.openrewrite.FindSourceFiles;
18-
import org.openrewrite.Preconditions;
19-
import org.openrewrite.ScanningRecipe;
20-
import org.openrewrite.SourceFile;
21-
import org.openrewrite.Tree;
22-
import org.openrewrite.TreeVisitor;
16+
import org.openrewrite.*;
2317
import org.openrewrite.groovy.GroovyIsoVisitor;
2418
import org.openrewrite.groovy.tree.G;
2519
import org.openrewrite.java.tree.Expression;
2620
import org.openrewrite.java.tree.J;
2721
import org.openrewrite.marker.Markers;
22+
import org.openrewrite.marker.SearchResult;
2823
import org.openrewrite.maven.MavenIsoVisitor;
2924
import org.openrewrite.maven.tree.MavenResolutionResult;
3025
import org.openrewrite.maven.tree.Parent;
@@ -44,6 +39,27 @@ public class MetadataCollector extends ScanningRecipe<MetadataCollector.Metadata
4439
*/
4540
private static final Logger LOG = LoggerFactory.getLogger(MetadataCollector.class);
4641

42+
public MetadataCollector() {}
43+
44+
public MetadataCollector(boolean force, boolean search) {
45+
this.force = force;
46+
this.search = search;
47+
}
48+
49+
@Option(
50+
displayName = "Force collection of metadata. Default to false",
51+
required = false,
52+
description = "Force the collection of metadata. If false will reuse the existing metadata if any.",
53+
example = "true")
54+
boolean force = false;
55+
56+
@Option(
57+
displayName = "Search for metadata Default to false",
58+
required = false,
59+
description = "Search for metadata. If true will search for metadata.",
60+
example = "true")
61+
boolean search = false;
62+
4763
@Override
4864
public String getDisplayName() {
4965
return "Plugin metadata extractor";
@@ -58,12 +74,12 @@ public String getDescription() {
5874
* Accumulator to store metadata.
5975
*/
6076
public static class MetadataAccumulator {
61-
private final List<ArchetypeCommonFile> commonFiles = new ArrayList<>();
62-
private final Set<MetadataFlag> flags = new HashSet<>();
63-
private final Set<JDK> jdkVersions = new HashSet<>();
77+
private final List<ArchetypeCommonFile> commonFiles = new LinkedList<>();
78+
private final Set<MetadataFlag> flags = new LinkedHashSet<>();
79+
private final Set<JDK> jdkVersions = new LinkedHashSet<>();
6480

6581
public List<ArchetypeCommonFile> getCommonFiles() {
66-
return commonFiles;
82+
return commonFiles.stream().sorted().collect(Collectors.toList());
6783
}
6884

6985
public Set<JDK> getJdkVersions() {
@@ -82,7 +98,7 @@ public Set<MetadataFlag> getFlags() {
8298
return flags;
8399
}
84100

85-
public void addFlags(List<MetadataFlag> flags) {
101+
public void addFlags(Set<MetadataFlag> flags) {
86102
this.flags.addAll(flags);
87103
}
88104
}
@@ -211,6 +227,21 @@ public TreeVisitor<?, ExecutionContext> getVisitor(MetadataAccumulator acc) {
211227
@Override
212228
public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) {
213229

230+
final PluginMetadata pluginMetadata = new PluginMetadata();
231+
232+
if (!force) {
233+
// Check if metadata already exists
234+
if (pluginMetadata.exists()) {
235+
PluginMetadata refreshedMetadata = pluginMetadata.refresh();
236+
LOG.info("Metadata already exists, skipping metadata extraction");
237+
LOG.info("Metadata: {}", JsonUtils.toJson(refreshedMetadata));
238+
if (search) {
239+
return SearchResult.found(document, JsonUtils.toJson(refreshedMetadata));
240+
}
241+
return document.withMarkers(document.getMarkers().add(refreshedMetadata));
242+
}
243+
}
244+
214245
// Ensure maven resolution result is present
215246
Markers markers = document.getMarkers();
216247
Optional<MavenResolutionResult> mavenResolutionResult = markers.findFirst(MavenResolutionResult.class);
@@ -236,7 +267,6 @@ public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) {
236267
properties.remove("basedir");
237268

238269
// Construct the plugin metadata
239-
PluginMetadata pluginMetadata = new PluginMetadata();
240270
pluginMetadata.setPluginName(pom.getName());
241271
Parent parent = pom.getParent();
242272
if (parent != null) {
@@ -259,8 +289,10 @@ public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) {
259289
pluginMetadata.save();
260290
LOG.debug("Plugin metadata written to {}", pluginMetadata.getRelativePath());
261291
LOG.debug(JsonUtils.toJson(pluginMetadata));
262-
263-
return document;
292+
if (search) {
293+
return SearchResult.found(document, JsonUtils.toJson(pluginMetadata));
294+
}
295+
return document.withMarkers(document.getMarkers().add(pluginMetadata));
264296
}
265297
};
266298
}
@@ -273,7 +305,7 @@ private static class TagExtractor extends MavenIsoVisitor<ExecutionContext> {
273305
/**
274306
* Detected flag
275307
*/
276-
private final List<MetadataFlag> flags = new ArrayList<>();
308+
private final Set<MetadataFlag> flags = new LinkedHashSet<>();
277309

278310
/**
279311
* Convert an OpenRewrite XML tag to a metadata XML tag.
@@ -311,7 +343,7 @@ public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) {
311343
* Get the flags for this visitor.
312344
* @return flags for this visitor
313345
*/
314-
public List<MetadataFlag> getFlags() {
346+
public Set<MetadataFlag> getFlags() {
315347
return flags;
316348
}
317349
}

plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/extractor/PluginMetadata.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,17 @@
77
import io.jenkins.tools.pluginmodernizer.core.model.PreconditionError;
88
import java.io.Serializable;
99
import java.nio.file.Path;
10-
import java.util.Collections;
11-
import java.util.HashSet;
12-
import java.util.List;
13-
import java.util.Map;
14-
import java.util.Set;
10+
import java.util.*;
11+
import org.openrewrite.marker.Marker;
1512

1613
/**
1714
* Metadata of a plugin extracted from its POM file or code
1815
*/
19-
public class PluginMetadata extends CacheEntry<PluginMetadata> implements Serializable {
16+
public class PluginMetadata extends CacheEntry<PluginMetadata> implements Serializable, Marker {
17+
18+
private static final long serialVersionUID = 1L;
19+
20+
private transient UUID id;
2021

2122
/**
2223
* Name of the plugin
@@ -207,4 +208,15 @@ public Map<String, String> getProperties() {
207208
public void setProperties(Map<String, String> properties) {
208209
this.properties = properties;
209210
}
211+
212+
@Override
213+
public UUID getId() {
214+
return id;
215+
}
216+
217+
@Override
218+
public PluginMetadata withId(UUID id) {
219+
this.id = id;
220+
return this;
221+
}
210222
}

plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/model/CacheEntry.java

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ public final CacheManager getCacheManager() {
7878
return cacheManager;
7979
}
8080

81+
/**
82+
* Check if the object exists in the cache
83+
* @return True if the object exists
84+
*/
85+
public final boolean exists() {
86+
return cacheManager.get(Path.of(path), key, clazz) != null;
87+
}
88+
8189
/**
8290
* Return a copy of this object refreshed from the cache
8391
* @return The refreshed object
@@ -108,12 +116,27 @@ public final T copy(CacheManager newCacheManager, Path newPath, String newKey) {
108116
}
109117

110118
private T move(CacheManager newCacheManager, Path newPath, String newKey, boolean copy) {
111-
LOG.debug(
112-
"Moving object from {} to {}",
113-
cacheManager.getLocation().resolve(path).resolve(key),
114-
newCacheManager.getLocation().resolve(newPath).resolve(newKey));
119+
if (copy) {
120+
LOG.debug(
121+
"Copying object from {} to {}",
122+
cacheManager.getLocation().resolve(path).resolve(key),
123+
newCacheManager.getLocation().resolve(newPath).resolve(newKey));
124+
} else {
125+
LOG.debug(
126+
"Moving object from {} to {}",
127+
cacheManager.getLocation().resolve(path).resolve(key),
128+
newCacheManager.getLocation().resolve(newPath).resolve(newKey));
129+
}
130+
115131
// Copy transient fields
116132
T refreshedObject = refresh();
133+
if (refreshedObject == null) {
134+
LOG.warn(
135+
"Object does not exist in source cache at {}",
136+
cacheManager.getLocation().resolve(path).resolve(key));
137+
LOG.warn(JsonUtils.toJson(this));
138+
return null;
139+
}
117140
refreshedObject.setPath(newPath);
118141
refreshedObject.setKey(newKey);
119142
refreshedObject.setCacheManager(newCacheManager);

plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/model/Plugin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ public void copyMetadata(CacheManager cacheManager) {
738738
CacheManager.PLUGIN_METADATA_CACHE_KEY,
739739
new PluginMetadata(pluginCacheManager)));
740740
LOG.debug(
741-
"Moved plugin {} metadata to cache: {}",
741+
"Copied plugin {} metadata to cache: {}",
742742
getName(),
743743
getMetadata().getLocation().toAbsolutePath());
744744
}

plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/IsUsingBom.java

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package io.jenkins.tools.pluginmodernizer.core.recipes;
22

3+
import io.jenkins.tools.pluginmodernizer.core.extractor.PluginMetadata;
34
import java.util.Optional;
45
import org.openrewrite.*;
56
import org.openrewrite.marker.Markers;
67
import org.openrewrite.marker.SearchResult;
7-
import org.openrewrite.maven.tree.MavenResolutionResult;
8-
import org.openrewrite.maven.tree.Pom;
9-
import org.openrewrite.maven.tree.ResolvedPom;
108
import org.openrewrite.xml.XmlVisitor;
119
import org.openrewrite.xml.tree.Xml;
1210

@@ -31,22 +29,14 @@ public TreeVisitor<?, ExecutionContext> getVisitor() {
3129
@Override
3230
public Xml visitDocument(Xml.Document document, ExecutionContext ctx) {
3331

34-
// Ensure maven resolution result is present
32+
// Ensure PluginMetadata is present
3533
Markers markers = document.getMarkers();
36-
Optional<MavenResolutionResult> mavenResolutionResult = markers.findFirst(MavenResolutionResult.class);
37-
if (mavenResolutionResult.isEmpty()) {
34+
Optional<PluginMetadata> pluginMetadata = markers.findFirst(PluginMetadata.class);
35+
if (pluginMetadata.isEmpty()) {
3836
return document;
3937
}
40-
// Get the pom
41-
MavenResolutionResult resolutionResult = mavenResolutionResult.get();
42-
ResolvedPom resolvedPom = resolutionResult.getPom();
43-
Pom pom = resolvedPom.getRequested();
4438

45-
// Check if the project is using Jenkins bom
46-
boolean isUsingBom = pom.getDependencyManagement().stream()
47-
.anyMatch(dependency -> dependency.getGroupId().equals("io.jenkins.tools.bom"));
48-
49-
if (isUsingBom) {
39+
if (pluginMetadata.get().getBomVersion() != null) {
5040
return SearchResult.found(document, "Project is using Jenkins bom");
5141
}
5242

plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/utils/JsonUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public static String toJson(Object object) {
4545
*/
4646
public static void toJsonFile(Object object, Path path) {
4747
try {
48-
LOG.trace("Writing JSON file to {}", path);
48+
LOG.debug("Writing JSON file to {}", path);
4949
FileUtils.writeStringToFile(path.toFile(), gson.toJson(object), StandardCharsets.UTF_8);
5050
} catch (IOException e) {
5151
throw new ModernizerException("Unable to write JSON file due to IO error", e);

plugin-modernizer-core/src/main/resources/META-INF/rewrite/recipes.yml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ displayName: Fetch metadata
55
description: Extracts metadata from a Jenkins plugin
66
tags: ['extractor']
77
recipeList:
8-
- io.jenkins.tools.pluginmodernizer.core.extractor.MetadataCollector
8+
- io.jenkins.tools.pluginmodernizer.core.extractor.MetadataCollector:
9+
force: true
10+
search: false
911
---
1012
type: specs.openrewrite.org/v1beta/recipe
1113
name: io.jenkins.tools.pluginmodernizer.AddPluginsBom
1214
displayName: Add plugins BOM
1315
description: Add the Jenkins BOM to the dependenciesManagement section of the pom.xml.
1416
tags: ['chore', 'dependencies']
17+
preconditions:
18+
- io.jenkins.tools.pluginmodernizer.SearchMetadata
1519
recipeList:
1620
- org.openrewrite.jenkins.AddPluginsBom
1721
- io.jenkins.tools.pluginmodernizer.UpgradeBomVersion
@@ -355,6 +359,16 @@ recipeList:
355359
- org.openrewrite.jenkins.AddJellyXmlDeclaration
356360
---
357361
type: specs.openrewrite.org/v1beta/recipe
362+
name: io.jenkins.tools.pluginmodernizer.conditions.SearchMetadata
363+
displayName: Search for metadata and make it available for other recipes
364+
description: Search for metadata and make it available for other recipes
365+
tags: ['condition']
366+
recipeList:
367+
- io.jenkins.tools.pluginmodernizer.core.extractor.MetadataCollector:
368+
force: false
369+
search: true
370+
---
371+
type: specs.openrewrite.org/v1beta/recipe
358372
name: io.jenkins.tools.pluginmodernizer.conditions.IsUsingRecommendCoreVersion
359373
displayName: Check if the plugin is using the recommended core version
360374
description: Check if the plugin is using the recommended core version
@@ -380,3 +394,13 @@ tags: ['condition']
380394
recipeList:
381395
- org.openrewrite.jenkins.IsJenkinsPlugin:
382396
version: "[2.489,)" # Adapt when LTS
397+
---
398+
type: specs.openrewrite.org/v1beta/recipe
399+
name: io.jenkins.tools.pluginmodernizer.conditions.IsUsingBom
400+
displayName: Check if a plugin is using a BOM
401+
description: Check if a plugin is using a BOM
402+
tags: ['condition']
403+
preconditions:
404+
- io.jenkins.tools.pluginmodernizer.conditions.SearchMetadata
405+
recipeList:
406+
- io.jenkins.tools.pluginmodernizer.core.recipes.IsUsingBom

0 commit comments

Comments
 (0)