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

Breaking/migrate maven to plugin parameters #55

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

buchananwill
Copy link
Contributor

This PR combines the work I've done yesterday and today on both the Gradle and Maven plugins. The first half is a duplicate of the other pull request which is only the Gradle plugin. I've done this so you can view the entire proposal in context. I don't mind if you want to accept the smaller PR first (or only), and address the Maven aspect separately. However I think it makes more sense to see the changes as a whole, which really comprises three stages:

  1. Add Gradle plugin
  2. Pull the parameters into the core module without breaking the Gradle plugin
  3. Replace the matching parameters from the Maven plugin with the shared class now available from the Core module.

Also, I didn't like the idea of pre-empting the version bump as that's totally your prerogative as repo owner, but it seemed like the safest way to ensure that I wasn't testing stale caches in the dependent modules. I won't be offended if you want to take a different tack or increment differently.

@buchananwill
Copy link
Contributor Author

I did a bit more digging, and the gradle api jar is hosted by Jetbrains, so I replaced the local .env with that, and the build runs now.

@ivangreene
Copy link
Owner

Hi, thanks for updating this. I kind of have a full week so probably won’t get a chance to dig in and run it until this weekend. Will leave some comments when I can

@buchananwill
Copy link
Contributor Author

buchananwill commented Oct 1, 2024 via email

Copy link
Owner

@ivangreene ivangreene left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your patience. I had some time to review this over the weekend. Here are some changes I'd love to see:

  • Build and package the gradle plugin with Maven
  • Align the tests of the two plugins to share more example code from a shared submodule
  • Convert the configuration class into a class that is extended by both the Maven and Gradle plugins, so that the config can be at the top level and we don't have to break the API. This keeps aligned with typescript-generator

import org.gradle.api.tasks.Optional;

@Setter
public class PluginParameters implements Serializable {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can generate the appropriate getters in this way:

Suggested change
public class PluginParameters implements Serializable {
@Getter(onMethod=@__({@Input}))
public class PluginParameters implements Serializable {

Not sure of the exact syntax. See Lombok docs: https://projectlombok.org/features/GetterSetter

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually need to implement Serializable too? I would also like to see this class extended by the Maven Mojo and the Gradle equivalent, so that the config properties are defined at the top level. I think that may eliminate the need for Serializable.

I guess to make this happen, we would need to extend both AbstractMojo and DefaultTask in PluginParameters. I think in that case, it makes more sense to name this BasePlugin or something.

private List<String> optionalAnnotations = Collections.emptyList();

@Input
@Optional
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Optional Inputs, we can use a variation of Getter on the specific field declaration:

@Getter(onMethod=@__({@Input, @Optional}))
private String schemaNameSuffix = "Schema";

@@ -0,0 +1,60 @@
plugins {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although this is a Gradle plugin, I would like to see this built with Maven to keep consistency in the project. It looks like typescript-generator has accomplished this. I think this is mostly encapsulated in that sub-module's pom.xml: https://github.com/vojtechhabarta/typescript-generator/blob/main/typescript-generator-gradle-plugin/pom.xml
As well as this META-INF file: https://github.com/vojtechhabarta/typescript-generator/blob/main/typescript-generator-gradle-plugin/src/main/resources/META-INF/gradle-plugins/cz.habarta.typescript-generator.properties

@@ -0,0 +1,320 @@
package sh.ivan.zod.plugins;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class should go into its own submodule, java-to-zod-plugin-support or something like that. It shouldn't be packaged with the core. Same with the class above

Comment on lines +31 to +36
tasks.withType<sh.ivan.zod.GenerateZodSchemas> {
val tempOutputDir = layout.buildDirectory.dir("temp/generated-schemas")
outputFile = tempOutputDir.map { it.file("schemas.ts") }.get().asFile
pluginParameters.jsonLibrary = JsonLibrary.jackson2
pluginParameters.classes = mutableListOf("sh.ivan.zod.resources.TestPersonClass", "sh.ivan.zod.resources.TestPersonRecord")
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the typical way to configure a plugin like this in Gradle? I'm expecting something more like this: https://github.com/vojtechhabarta/typescript-generator/blob/main/sample-gradle/build.gradle#L44-L65

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class GenerateZodSchemasTest {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally think we should delete this test. It looks way too reliant on internal details of how Gradle plugins work. I'm more interested in asserting that the can be used from a regular old Gradle project, and generate a file that meets expectations. This is what we test in the Maven plugin. Thoughts?

@@ -4,7 +4,7 @@
<parent>
<groupId>sh.ivan</groupId>
<artifactId>java-to-zod</artifactId>
<version>0.7.0-SNAPSHOT</version>
<version>0.8.0-SNAPSHOT</version>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to change the version number. This is all handled automatically when I do the release

import sh.ivan.zod.plugins.PluginParameters;
import sh.ivan.zod.schema.ObjectSchema;

public class JavaToZodConvertorWrapper {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested name: JavaToZodPluginConverter. Thoughts?

private static final long serialVersionUID = 1L;

/**
* Prefix added to generated schema names.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these comments get added to any kind of Gradle online documentation system? Would love to retain these somehow. Worst case, we can always link to the generated Maven configuration docs. Here's what that looks like: https://java-to-zod.ivan.sh/java-to-zod-maven-plugin/generate-mojo.html

This reminds me, we may want to find a way to publish any generated Gradle documentation to the site along with the Maven version. Site: https://java-to-zod.ivan.sh/

import java.util.Date;
import java.util.Objects;

public final class TestPersonClass {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not add more tests here. I'd like to maintain exact test parity with the Maven plugin. This can be accomplished in a few steps:

  1. Move the POJOs in java-to-zod-maven-plugin-test into their own new submodule named java-to-zod-plugin-test-support
  2. Bring that module in as a dependency to both java-to-zod-maven-plugin-test and to the module where we test the Gradle plugin
  3. Find a way to share the JS files (symlink a directory that contains them in both projects maybe?): https://github.com/ivangreene/java-to-zod/tree/main/java-to-zod-maven-plugin-test/js - not the schemas file though, that will get generated by each plugin
  4. The test of the Gradle plugin should exist as a separate directory. It will be the only Gradle project in the tree. It will configure the Gradle plugin, and then run the same JS tests. I'm assuming that's mostly what this gradle build file does? https://github.com/ivangreene/java-to-zod/blob/6735d0785a0fb59b5e655b49d21997ebed93d6a4/java-to-zod-gradle-plugin/src/test/resources/build.gradle.kts

@buchananwill
Copy link
Contributor Author

buchananwill commented Oct 15, 2024 via email

@ivangreene
Copy link
Owner

Oh yeah... brain not working lol. Hmm... maybe we can do something else there.

In the end, I'm trying to figure out what is a bigger priority:

  1. Share the configuration params in a single class
  2. Keep the API the same as typescript-generator with config at the top level

Probably number 1. So let's see if there's a way to "unwrap" the config for Maven or Gradle and do both. But ultimately this seems fine if we can't figure that out

@buchananwill
Copy link
Contributor Author

buchananwill commented Oct 15, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants