Skip to content

Commit a176bfd

Browse files
authored
Merge pull request #544 from jonesbusy/featuer/extract-from-jdkVersions
Extract for info from Jenkinsfile and support different layout
2 parents 0af4c03 + ec2fd6d commit a176bfd

11 files changed

Lines changed: 495 additions & 116 deletions

File tree

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

Lines changed: 165 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package io.jenkins.tools.pluginmodernizer.core.extractor;
22

33
import io.jenkins.tools.pluginmodernizer.core.model.JDK;
4+
import io.jenkins.tools.pluginmodernizer.core.model.Platform;
5+
import io.jenkins.tools.pluginmodernizer.core.model.PlatformConfig;
6+
import java.util.Collections;
47
import java.util.HashMap;
8+
import java.util.LinkedList;
59
import java.util.List;
610
import java.util.Map;
711
import java.util.stream.Stream;
@@ -13,7 +17,7 @@
1317
import org.slf4j.LoggerFactory;
1418

1519
/**
16-
* Visitor for a Jenkinsfile
20+
* Visitor for a Jenkinsfile to accumulate @see PluginMetadata.
1721
*/
1822
public class JenkinsfileVisitor extends GroovyIsoVisitor<PluginMetadata> {
1923

@@ -22,6 +26,9 @@ public class JenkinsfileVisitor extends GroovyIsoVisitor<PluginMetadata> {
2226
*/
2327
public static final Logger LOG = LoggerFactory.getLogger(JenkinsfileVisitor.class);
2428

29+
/**
30+
* Keep track of variables if there are defined on top level and not directly on the method invocation.
31+
*/
2532
private final Map<String, Object> variableMap = new HashMap<>();
2633

2734
@Override
@@ -36,67 +43,198 @@ public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations v
3643
return variableDeclarations;
3744
}
3845

46+
@Override
47+
public J visitMapEntry(G.MapEntry mapEntry, PluginMetadata pluginMetadata) {
48+
super.visitMapEntry(mapEntry, pluginMetadata);
49+
J.MethodInvocation method = getCursor().firstEnclosing(J.MethodInvocation.class);
50+
if (method == null) {
51+
return mapEntry;
52+
}
53+
if (method.getSimpleName().equals("buildPlugin")) {
54+
if ("useContainerAgent".equals(mapEntry.getKey().toString())) {
55+
if (mapEntry.getValue() instanceof J.Literal literal) {
56+
pluginMetadata.setUseContainerAgent(Boolean.valueOf(literal.getValueSource()));
57+
} else if (mapEntry.getValue() instanceof J.Identifier) {
58+
Expression resolvedArg = resolveVariable(mapEntry.getValue());
59+
if (resolvedArg instanceof J.Literal literal) {
60+
pluginMetadata.setUseContainerAgent(Boolean.valueOf(literal.getValueSource()));
61+
}
62+
}
63+
}
64+
if ("forkCount".equals(mapEntry.getKey().toString())) {
65+
if (mapEntry.getValue() instanceof J.Literal literal) {
66+
pluginMetadata.setForkCount(literal.getValue().toString());
67+
} else if (mapEntry.getValue() instanceof J.Identifier) {
68+
Expression resolvedArg = resolveVariable(mapEntry.getValue());
69+
if (resolvedArg instanceof J.Literal literal) {
70+
pluginMetadata.setForkCount(literal.getValue().toString());
71+
}
72+
}
73+
}
74+
}
75+
return mapEntry;
76+
}
77+
3978
@Override
4079
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, PluginMetadata pluginMetadata) {
4180
LOG.debug("Visiting method invocation {}", method);
4281
method = super.visitMethodInvocation(method, pluginMetadata);
4382
if ("buildPlugin".equals(method.getSimpleName())) {
4483
List<Expression> args = method.getArguments();
4584

46-
List<Integer> jdkVersions =
47-
args.stream().flatMap(this::extractJdkVersions).distinct().toList();
85+
// Empty args means Java 8 in Windows and Linux
86+
if (args.size() == 1 && args.get(0) instanceof J.Empty) {
87+
pluginMetadata.addPlatform(new PlatformConfig(Platform.LINUX, JDK.JAVA_8, null, true));
88+
pluginMetadata.addPlatform(new PlatformConfig(Platform.WINDOWS, JDK.JAVA_8, null, true));
89+
return method;
90+
}
4891

49-
LOG.info("JDK versions found: {}", jdkVersions);
92+
List<PlatformConfig> platforms = new LinkedList<>();
93+
for (Expression expression : args) {
94+
platforms.addAll(extractPlatforms(expression));
95+
}
96+
// Filter platforms (Remove implicit if there is at least one explicit)
97+
if (platforms.stream().anyMatch(pc -> !pc.implicit())) {
98+
platforms.removeIf(PlatformConfig::implicit);
99+
}
100+
// If all platform are unknown ensure each platform on the list is present with LINUX and WINDOWS
101+
if (platforms.stream().allMatch(pc -> pc.name() == Platform.UNKNOWN)) {
102+
List<PlatformConfig> newPlatforms = new LinkedList<>();
103+
for (PlatformConfig pc : platforms) {
104+
newPlatforms.add(new PlatformConfig(Platform.LINUX, pc.jdk(), null, false));
105+
newPlatforms.add(new PlatformConfig(Platform.WINDOWS, pc.jdk(), null, false));
106+
}
107+
platforms = newPlatforms;
108+
}
109+
// If there is a platform without JDK ensure all all JDK are using the same platform
110+
if (platforms.stream().anyMatch(pc -> pc.jdk() == null)) {
111+
List<PlatformConfig> newPlatforms = new LinkedList<>();
112+
for (PlatformConfig pc : platforms) {
113+
if (!pc.name().equals(Platform.UNKNOWN)) {
114+
if (platforms.stream().allMatch(p -> p.jdk() == null)) {
115+
newPlatforms.add(new PlatformConfig(pc.name(), JDK.JAVA_8, null, false));
116+
continue;
117+
}
118+
for (PlatformConfig pc2 : platforms) {
119+
if (pc2.jdk() != null) {
120+
newPlatforms.add(new PlatformConfig(pc.name(), pc2.jdk(), null, false));
121+
}
122+
}
123+
}
124+
}
125+
platforms = newPlatforms;
126+
}
50127

51-
jdkVersions.forEach(jdkVersion -> pluginMetadata.addJdk(JDK.get(jdkVersion)));
128+
LOG.info("Platform: {}", platforms);
129+
pluginMetadata.setPlatforms(platforms);
52130
}
53131

54132
return method;
55133
}
56134

57-
private Stream<Integer> extractJdkVersions(Expression arg) {
135+
private List<PlatformConfig> extractPlatforms(Expression arg) {
58136
if (arg instanceof G.MapEntry) {
59-
return Stream.of(arg)
137+
138+
// Get 'configurations' stream
139+
Stream<G.MapEntry> configurations = Stream.of(arg)
60140
.map(G.MapEntry.class::cast)
61-
.filter(entry -> "configurations".equals(((J.Literal) entry.getKey()).getValue()))
141+
.filter(entry -> "configurations".equals(((J.Literal) entry.getKey()).getValue()));
142+
143+
// List of platform config from 'configurations' parameter
144+
List<PlatformConfig> platformFromConfigs = configurations
62145
.map(entry -> resolveConfigurations(entry.getValue()))
63146
.filter(value -> value instanceof G.ListLiteral)
64147
.flatMap(value -> ((G.ListLiteral) value).getElements().stream())
65148
.filter(expression -> expression instanceof G.MapLiteral)
66-
.flatMap(expression -> ((G.MapLiteral) expression).getElements().stream())
67-
.filter(mapExpr -> mapExpr instanceof G.MapEntry)
149+
.map(expression -> (G.MapLiteral) expression)
150+
.map(JenkinsfileVisitor::toPlatformEntry)
151+
.toList();
152+
153+
// Cannot be combinated
154+
if (!platformFromConfigs.isEmpty()) {
155+
return platformFromConfigs;
156+
}
157+
158+
// List of JDK versions from 'jdkVersions' parameter
159+
List<Integer> jdkVersions = Stream.of(arg)
68160
.map(G.MapEntry.class::cast)
69-
.filter(mapEntry -> "jdk".equals(((J.Literal) mapEntry.getKey()).getValue()))
70-
.map(mapEntry -> Integer.parseInt(
71-
((J.Literal) mapEntry.getValue()).getValue().toString()));
72-
} else {
161+
.filter(entry -> "jdkVersions".equals(((J.Literal) entry.getKey()).getValue()))
162+
.map(entry -> resolveConfigurations(entry.getValue()))
163+
.filter(value -> value instanceof G.ListLiteral)
164+
.map(value -> (G.ListLiteral) value)
165+
.flatMap(value -> value.getElements().stream())
166+
.map(expression ->
167+
Integer.parseInt(((J.Literal) expression).getValue().toString()))
168+
.toList();
169+
170+
// List of platforms from 'platforms' parameter
171+
List<String> platforms = Stream.of(arg)
172+
.map(G.MapEntry.class::cast)
173+
.filter(entry -> "platforms".equals(((J.Literal) entry.getKey()).getValue()))
174+
.map(entry -> resolveConfigurations(entry.getValue()))
175+
.filter(value -> value instanceof G.ListLiteral)
176+
.map(value -> (G.ListLiteral) value)
177+
.flatMap(value -> value.getElements().stream())
178+
.map(expression -> expression instanceof J.Literal ? expression.toString() : null)
179+
.toList();
180+
181+
// Combine all JDK versions with all platforms
182+
List<PlatformConfig> platformFromJdkVersions = new LinkedList<>();
183+
for (Integer jdk : jdkVersions) {
184+
platformFromJdkVersions.add(new PlatformConfig(Platform.UNKNOWN, JDK.get(jdk), null, true));
185+
}
186+
for (String platform : platforms) {
187+
platformFromJdkVersions.add(new PlatformConfig(Platform.fromPlatform(platform), null, null, true));
188+
}
189+
190+
return platformFromJdkVersions;
191+
192+
} else if (arg instanceof J.Identifier) {
73193
Expression resolvedArg = resolveVariable(arg);
74194
return Stream.of(resolvedArg)
75195
.filter(resolved -> resolved instanceof G.MapLiteral)
76196
.flatMap(resolved -> ((G.MapLiteral) resolved).getElements().stream())
77-
.filter(entry -> entry instanceof G.MapEntry)
78-
.map(G.MapEntry.class::cast)
79197
.filter(entry -> "configurations".equals(((J.Literal) entry.getKey()).getValue()))
80198
.map(entry -> resolveConfigurations(entry.getValue()))
81199
.filter(value -> value instanceof G.ListLiteral)
82200
.flatMap(value -> ((G.ListLiteral) value).getElements().stream())
83201
.filter(expression -> expression instanceof G.MapLiteral)
84-
.flatMap(expression -> ((G.MapLiteral) expression).getElements().stream())
85-
.filter(mapExpr -> mapExpr instanceof G.MapEntry)
86-
.map(G.MapEntry.class::cast)
87-
.filter(mapEntry -> "jdk".equals(((J.Literal) mapEntry.getKey()).getValue()))
88-
.map(mapEntry -> Integer.parseInt(
89-
((J.Literal) mapEntry.getValue()).getValue().toString()));
202+
.map(expression -> (G.MapLiteral) expression)
203+
.map(JenkinsfileVisitor::toPlatformEntry)
204+
.toList();
90205
}
206+
return Collections.emptyList();
91207
}
92208

93-
private Expression resolveVariable(Expression expression) {
94-
if (expression instanceof J.Identifier) {
95-
String variableName = ((J.Identifier) expression).getSimpleName();
96-
if (variableMap.containsKey(variableName)) {
97-
return (Expression) variableMap.get(variableName);
209+
/**
210+
* Return if the map entry is a platform entry.
211+
* @param mapLiteral The map entry
212+
* @return The platform config
213+
*/
214+
private static PlatformConfig toPlatformEntry(G.MapLiteral mapLiteral) {
215+
Stream<G.MapEntry> entries = mapLiteral.getElements().stream();
216+
List<G.MapEntry> list = entries.toList();
217+
Integer jdk = null;
218+
String platform = null;
219+
for (G.MapEntry entry : list) {
220+
if (entry.getKey() instanceof J.Literal key) {
221+
if ("jdk".equals(key.getValue())) {
222+
jdk = Integer.parseInt(entry.getValue().toString());
223+
}
224+
if ("platform".equals(key.getValue())) {
225+
platform = entry.getValue().toString();
226+
}
98227
}
99228
}
229+
230+
return new PlatformConfig(Platform.fromPlatform(platform), JDK.get(jdk), null, false);
231+
}
232+
233+
private Expression resolveVariable(Expression expression) {
234+
String variableName = ((J.Identifier) expression).getSimpleName();
235+
if (variableMap.containsKey(variableName)) {
236+
return (Expression) variableMap.get(variableName);
237+
}
100238
return expression;
101239
}
102240

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

Lines changed: 74 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,25 @@
33
import io.jenkins.tools.pluginmodernizer.core.impl.CacheManager;
44
import io.jenkins.tools.pluginmodernizer.core.model.CacheEntry;
55
import io.jenkins.tools.pluginmodernizer.core.model.JDK;
6+
import io.jenkins.tools.pluginmodernizer.core.model.Platform;
7+
import io.jenkins.tools.pluginmodernizer.core.model.PlatformConfig;
68
import io.jenkins.tools.pluginmodernizer.core.model.Plugin;
79
import io.jenkins.tools.pluginmodernizer.core.model.PreconditionError;
8-
import java.io.Serial;
9-
import java.io.Serializable;
1010
import java.nio.file.Path;
1111
import java.util.ArrayList;
1212
import java.util.Collection;
1313
import java.util.Collections;
1414
import java.util.HashMap;
1515
import java.util.HashSet;
16+
import java.util.LinkedList;
1617
import java.util.List;
1718
import java.util.Map;
1819
import java.util.Set;
1920

2021
/**
2122
* Metadata of a plugin extracted from its POM file or code
2223
*/
23-
public class PluginMetadata extends CacheEntry<PluginMetadata> implements Serializable {
24-
25-
@Serial
26-
private static final long serialVersionUID = 1L;
24+
public class PluginMetadata extends CacheEntry<PluginMetadata> {
2725

2826
/**
2927
* Name of the plugin
@@ -46,9 +44,19 @@ public class PluginMetadata extends CacheEntry<PluginMetadata> implements Serial
4644
private List<ArchetypeCommonFile> commonFiles;
4745

4846
/**
49-
* JDK versions supported by the plugin
47+
* List of platforms extracted from Jenkinsfile
48+
*/
49+
private List<PlatformConfig> platforms;
50+
51+
/**
52+
* Use container agent for build extracted from Jenkinsfile
5053
*/
51-
private Set<JDK> jdkVersions;
54+
private Boolean useContainerAgent;
55+
56+
/**
57+
* forkCount extracted from Jenkinsfile
58+
*/
59+
private String forkCount;
5260

5361
/**
5462
* Jenkins version required by the plugin
@@ -173,21 +181,71 @@ public void setCommonFiles(List<ArchetypeCommonFile> commonFiles) {
173181
}
174182

175183
public Set<JDK> getJdks() {
176-
if (jdkVersions == null) {
177-
jdkVersions = new HashSet<>();
184+
if (platforms == null) {
185+
platforms = new LinkedList<>();
178186
}
179-
return jdkVersions;
187+
return platforms.stream().map(PlatformConfig::jdk).collect(HashSet::new, Set::add, Set::addAll);
180188
}
181189

182-
public void addJdk(JDK jdk) {
183-
if (jdkVersions == null) {
184-
jdkVersions = new HashSet<>();
190+
public Set<Platform> getPlatforms() {
191+
if (platforms == null) {
192+
platforms = new LinkedList<>();
185193
}
186-
jdkVersions.add(jdk);
194+
return platforms.stream().map(PlatformConfig::name).collect(HashSet::new, Set::add, Set::addAll);
187195
}
188196

197+
/**
198+
* Set the JDK versions without platform information
199+
* @param jdkVersions The JDK versions
200+
*/
189201
public void setJdks(Set<JDK> jdkVersions) {
190-
this.jdkVersions = jdkVersions;
202+
if (platforms == null) {
203+
platforms = new ArrayList<>();
204+
}
205+
platforms.addAll(jdkVersions.stream()
206+
.map(jdk -> new PlatformConfig(Platform.UNKNOWN, jdk, null, true))
207+
.toList());
208+
}
209+
210+
public void setPlatforms(List<PlatformConfig> platforms) {
211+
this.platforms = platforms;
212+
}
213+
214+
public void addPlatform(PlatformConfig platform) {
215+
if (platforms == null) {
216+
platforms = new ArrayList<>();
217+
}
218+
platforms.add(platform);
219+
}
220+
221+
public void addPlatform(Platform platform, JDK jdk, String jenkins) {
222+
if (platforms == null) {
223+
platforms = new ArrayList<>();
224+
}
225+
platforms.add(new PlatformConfig(platform, jdk, jenkins, false));
226+
}
227+
228+
public void addError(PreconditionError error) {
229+
if (errors == null) {
230+
errors = new HashSet<>();
231+
}
232+
errors.add(error);
233+
}
234+
235+
public Boolean isUseContainerAgent() {
236+
return useContainerAgent;
237+
}
238+
239+
public void setUseContainerAgent(Boolean useContainerAgent) {
240+
this.useContainerAgent = useContainerAgent;
241+
}
242+
243+
public String getForkCount() {
244+
return forkCount;
245+
}
246+
247+
public void setForkCount(String forkCount) {
248+
this.forkCount = forkCount;
191249
}
192250

193251
/**

0 commit comments

Comments
 (0)