Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for parsing Groovy sources (incl. Jenkinsfiles) #662

Closed
simonzn opened this issue Nov 21, 2023 · 4 comments · Fixed by #663
Closed

Add support for parsing Groovy sources (incl. Jenkinsfiles) #662

simonzn opened this issue Nov 21, 2023 · 4 comments · Fixed by #663
Labels
enhancement New feature or request

Comments

@simonzn
Copy link
Contributor

simonzn commented Nov 21, 2023

What problem are you trying to solve?

We use Maven plugins for all CI tasks and would also like to run rewrite recipes for updating Jenkinsfiles through this plugin.

Describe the solution you'd like

The GroovyParser is already able to parse Jenkinsfiles, and I have tested it successfully with our pipelines. We would like the Maven plugin to parse Jenkinsfiles as Groovy sources by default instead of Quarks.

Currently the name must be "Jenkinsfile":

    @Override
    public boolean accept(Path path) {
        return path.toString().endsWith(".groovy") ||
               path.toFile().getName().equals("Jenkinsfile");
    }

We have two pipelines in each repository, "Jenkinsfile" for building the project and "Jenkinsfile_Release" for releasing it. It is quite common to have some suffix for Jenkinsfiles, so we would like the GroovyParser to accept Jenkinsfile* (or maybe even *Jenkinsfile* to support prefixes as well - although we don't use them).

Have you considered any alternatives or workarounds?

Currently we execute text recipes on Jenkinsfiles by passing -Drewrite.plainTextMasks="**/Jenkinsfile*,... (otherwise they are only added as Quarks). This works for us for now, but may become limiting. Adding the GroovyParser would also mean we could use text recipes without modifying the plainTextMasks.

@simonzn simonzn added the enhancement New feature or request label Nov 21, 2023
@timtebeek
Copy link
Contributor

Thanks for the reminder/suggestion @simonzn ! I've added a first commit to parse any file that starts with Jenkinsfile as Groovy in openrewrite/rewrite@7ed7222.

The logic for which parsers to use in the rewrite-maven-plugin is here.

JavaParser javaParser = javaParserBuilder.build();
List<Path> javaPaths = new ArrayList<>();
JsonParser jsonParser = new JsonParser();
List<Path> jsonPaths = new ArrayList<>();
XmlParser xmlParser = new XmlParser();
List<Path> xmlPaths = new ArrayList<>();
YamlParser yamlParser = new YamlParser();
List<Path> yamlPaths = new ArrayList<>();
PropertiesParser propertiesParser = new PropertiesParser();
List<Path> propertiesPaths = new ArrayList<>();
ProtoParser protoParser = new ProtoParser();
List<Path> protoPaths = new ArrayList<>();
PythonParser pythonParser = PythonParser.builder().build();
List<Path> pythonPaths = new ArrayList<>();
KotlinParser kotlinParser = KotlinParser.builder().build();
List<Path> kotlinPaths = new ArrayList<>();
HclParser hclParser = HclParser.builder().build();
List<Path> hclPaths = new ArrayList<>();
PlainTextParser plainTextParser = new PlainTextParser();
QuarkParser quarkParser = new QuarkParser();
resources.forEach(path -> {
// See https://github.com/quarkusio/quarkus/blob/main/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/resteasy-reactive-codestart/java/src/main/java/org/acme/%7Bresource.class-name%7D.tpl.qute.java
// for an example of why we don't want qute files be parsed as java
if (javaParser.accept(path) && !path.endsWith(".qute.java")) {
javaPaths.add(path);
} else if (jsonParser.accept(path)) {
jsonPaths.add(path);
} else if (xmlParser.accept(path)) {
xmlPaths.add(path);
} else if (yamlParser.accept(path)) {
yamlPaths.add(path);
} else if (propertiesParser.accept(path)) {
propertiesPaths.add(path);
} else if (protoParser.accept(path)) {
protoPaths.add(path);
} else if (pythonParser.accept(path)) {
pythonPaths.add(path);
} else if (kotlinParser.accept(path)) {
kotlinPaths.add(path);
} else if (hclParser.accept(path)) {
hclPaths.add(path);
} else if (quarkParser.accept(path)) {
quarkPaths.add(path);
}
});
if (!javaPaths.isEmpty()) {
sourceFiles = Stream.concat(sourceFiles, (Stream<S>) javaParser.parse(javaPaths, baseDir, ctx));
alreadyParsed.addAll(javaPaths);
}
if (!jsonPaths.isEmpty()) {
sourceFiles = Stream.concat(sourceFiles, (Stream<S>) jsonParser.parse(jsonPaths, baseDir, ctx));
alreadyParsed.addAll(jsonPaths);
}
if (!xmlPaths.isEmpty()) {
sourceFiles = Stream.concat(sourceFiles, (Stream<S>) xmlParser.parse(xmlPaths, baseDir, ctx));
alreadyParsed.addAll(xmlPaths);
}
if (!yamlPaths.isEmpty()) {
sourceFiles = Stream.concat(sourceFiles, (Stream<S>) yamlParser.parse(yamlPaths, baseDir, ctx));
alreadyParsed.addAll(yamlPaths);
}
if (!propertiesPaths.isEmpty()) {
sourceFiles = Stream.concat(sourceFiles, (Stream<S>) propertiesParser.parse(propertiesPaths, baseDir, ctx));
alreadyParsed.addAll(propertiesPaths);
}
if (!protoPaths.isEmpty()) {
sourceFiles = Stream.concat(sourceFiles, (Stream<S>) protoParser.parse(protoPaths, baseDir, ctx));
alreadyParsed.addAll(protoPaths);
}
if (!pythonPaths.isEmpty()) {
sourceFiles = Stream.concat(sourceFiles, (Stream<S>) pythonParser.parse(pythonPaths, baseDir, ctx));
alreadyParsed.addAll(pythonPaths);
}
if (!kotlinPaths.isEmpty()) {
sourceFiles = Stream.concat(sourceFiles, (Stream<S>) kotlinParser.parse(kotlinPaths, baseDir, ctx));
alreadyParsed.addAll(kotlinPaths);
}
if (!hclPaths.isEmpty()) {
sourceFiles = Stream.concat(sourceFiles, (Stream<S>) hclParser.parse(hclPaths, baseDir, ctx));
alreadyParsed.addAll(hclPaths);
}
if (!plainTextPaths.isEmpty()) {
sourceFiles = Stream.concat(sourceFiles, (Stream<S>) plainTextParser.parse(plainTextPaths, baseDir, ctx));
alreadyParsed.addAll(plainTextPaths);
}
if (!quarkPaths.isEmpty()) {
sourceFiles = Stream.concat(sourceFiles, (Stream<S>) quarkParser.parse(quarkPaths, baseDir, ctx));
alreadyParsed.addAll(quarkPaths);
}
return sourceFiles;

Would you be open to adding the GroovyParser in there as well? Even a draft PR would be fine to get this going.

@simonzn
Copy link
Contributor Author

simonzn commented Nov 21, 2023

Thanks for your swift reply @timtebeek ! I meant to do that, but then I found #641 and realized there might be more to it.

I can absolutely extend the ResourceParser. That should be sufficient for our use case, but probably not for rewriting actual Groovy projects.

simonzn added a commit to simonzn/rewrite-maven-plugin that referenced this issue Nov 21, 2023
timtebeek pushed a commit that referenced this issue Nov 21, 2023
@timtebeek
Copy link
Contributor

Until the next release you can try out this change using our snapshot versions. Let me know how that works for you! :)

@simonzn
Copy link
Contributor Author

simonzn commented Nov 22, 2023

I tested the snapshots with our Jenkinsfile recipes, everything works as expected now :-) Thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

2 participants