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

Plugin sources generation #2

Merged
merged 16 commits into from
Jan 29, 2025
Merged

Plugin sources generation #2

merged 16 commits into from
Jan 29, 2025

Conversation

andriy-dmytruk
Copy link
Collaborator

This adds support for generating Maven and Gradle stubs (#209).

Description

A plugin task configuration can be provided in a micronaut repo, like micronaut-json-schema. It is marked and configured using @PluginTask annotation. Then, @GenerateGradlePlugin or @GenerateMavenMojo annotations can be used in plugin repositories to generate plugin sources.

This has the advantage:

  • Plugin parameters can be defined in a single place and do not need to be repeated in plugins (currently we repeat parameters once for Maven and three times for Gradle).
  • This makes sure that parameter names and parameter defaults are consistent between plugins reducing manual errors.
  • The documentation needs to be written only once improving consistency again.

As an example, OpenAPI plugin has more than 40 parameters, which can be added and modified. This would simplify that effort.

Example

Example is provided in the test-suite-plugin-.
A plugin task can be configured with

@PluginTask
public record GenerateSimpleRecordTask(
    @PluginTaskParameter(required = true, globalProperty = "typeName")
    String typeName,
    @PluginTaskParameter(defaultValue = "1", globalProperty = "version")
    Integer version,
    @PluginTaskParameter(defaultValue = "com.example", globalProperty = "packageName")
    String packageName,
    Map<String, String> properties,
    List<String> javadoc,
    @PluginTaskParameter(output = true, directory = true, required = true)
    File outputFolder
) {

    /**
     * Generate a simple record in the supplied package and with the specified version.
     * This javadoc will be copied to the respected plugin implementations.
     */
    @PluginTaskExecutable
    public void generateSimpleRecord() {
       /* ... */
    }
}

Then gradle and maven sources can be generated by triggering annotations:

@GenerateGradlePlugin(
    namePrefix = "Test",
    micronautPlugin = false,
    types = {
        Type.GRADLE_TASK,
        Type.GRADLE_EXTENSION,
        Type.GRADLE_SPECIFICATION,
        Type.GRADLE_PLUGIN
    },
    tasks = {
        @GenerateGradleTask(
            namePrefix = "GenerateSimpleRecord",
            extensionMethodName = "generateSimpleRecord",
            source = "io.micronaut.sourcegen.example.plugin.GenerateSimpleRecordTask"
        ),
        @GenerateGradleTask(
            namePrefix = "GenerateSimpleResource",
            extensionMethodName = "generateSimpleResource",
            source = "io.micronaut.sourcegen.example.plugin.GenerateSimpleResourceTask"
        )
    }
)
public final class GeneratePluginTrigger {
}
@GenerateMavenMojo(
    namePrefix = "AbstractGenerateSimpleRecord",
    micronautPlugin = false,
    source = "io.micronaut.sourcegen.example.plugin.GenerateSimpleRecordTask",
    mavenPropertyPrefix = "test.generate.simple.record"
)
@GenerateMavenMojo(
    namePrefix = "AbstractGenerateSimpleResource",
    micronautPlugin = false,
    source = "io.micronaut.sourcegen.example.plugin.GenerateSimpleResourceTask",
    mavenPropertyPrefix = "test.generate.simple.resource"
)
public final class GenerateMojoTrigger {
}

This generates Gradle plugin, extension, specifications and tasks. For maven it generates maven mojos.
Test suite provides a more complete example.

Gradle extension and maven mojos are extended with implementation-specific details and also tests are shown.

Copy link
Contributor

@graemerocher graemerocher left a comment

Choose a reason for hiding this comment

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

Probably needs documentation, not sure if the PR will pass after merging without docs

var pluginContent = stripImports(files.get("test.WolfPlugin").getCharContent(false))
pluginContent == """public class WolfPlugin implements Plugin<Project> {
protected WolfExtension createExtension(Project project, Configuration classpath) {
return project.getExtensions().create(WolfExtension.class, "Wolf", DefaultWolfExtension.class, project, classpath);
Copy link

Choose a reason for hiding this comment

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

The defaults should probably be handled at the extension level, rather than in the task execution.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

They are handled on both levels. Not sure if required, but that seems to be the way for current plugins. I suppose this allows using task on its own.

Copy link

Choose a reason for hiding this comment

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

mmm, usually the tasks default to (convention()) the extension, which itself has convention(). That should be good.

public void execute(WolfTask arg1) {
arg1.getClasspath().from(this.classpath);
arg1.setDescription("Configure the awooo");
arg1.getSlogan().convention(this.spec.getSlogan());
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The defaults are set in extension, too. This configurator sets all the conventions.

@melix
Copy link

melix commented Jan 27, 2025

So we need this sourcegen to generate a Gradle plugin that would generate plugins :)

@andriy-dmytruk
Copy link
Collaborator Author

andriy-dmytruk commented Jan 28, 2025

@melix Do you know what might be causing the sonar issue?

2025-01-27T16:53:08.8424607Z 2025-01-27T16:53:08.750+0000 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Completing Build operation 'Execute run for :sonar'
2025-01-27T16:53:08.8426826Z 2025-01-27T16:53:08.750+0000 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Completing Build operation 'Executing task ':sonar''
2025-01-27T16:53:08.8428469Z 2025-01-27T16:53:07.742+0000 [LIFECYCLE] [class org.gradle.internal.buildevents.TaskExecutionLogger] 
2025-01-27T16:53:08.8429887Z 2025-01-27T16:53:07.742+0000 [LIFECYCLE] [class org.gradle.internal.buildevents.TaskExecutionLogger] > Task :sonar FAILED
2025-01-27T16:53:08.8432438Z 2025-01-27T16:53:08.212+0000 [DEBUG] [org.sonarqube.gradle.SonarTask] <-- 404 https://sonarcloud.io/api/settings/values.protobuf?component=micronaut-projects_***-plugin-sourcegen (851ms, unknown-length body)
2025-01-27T16:53:08.8434913Z 2025-01-27T16:53:08.213+0000 [DEBUG] [okhttp3.internal.concurrent.TaskRunner] Q10000 scheduled after   0 µs: OkHttp ConnectionPool
2025-01-27T16:53:08.8436432Z 2025-01-27T16:53:08.215+0000 [INFO] [org.sonarqube.gradle.SonarTask] Process project properties
2025-01-27T16:53:08.8437667Z 2025-01-27T16:53:08.227+0000 [DEBUG] [org.sonarqube.gradle.SonarTask] Process project properties (done) | time=12ms
2025-01-27T16:53:08.8439129Z 2025-01-27T16:53:08.229+0000 [INFO] [org.sonarqube.gradle.SonarTask] Project key: micronaut-projects_***-plugin-sourcegen
2025-01-27T16:53:08.8440953Z 2025-01-27T16:53:08.229+0000 [INFO] [org.sonarqube.gradle.SonarTask] Base dir: /home/runner/work/***-plugin-sourcegen/***-plugin-sourcegen
2025-01-27T16:53:08.8442988Z 2025-01-27T16:53:08.229+0000 [INFO] [org.sonarqube.gradle.SonarTask] Working dir: /home/runner/work/***-plugin-sourcegen/***-plugin-sourcegen/build/sonar
2025-01-27T16:53:08.8444564Z 2025-01-27T16:53:08.229+0000 [DEBUG] [org.sonarqube.gradle.SonarTask] Project global encoding: UTF-8, default locale: en
2025-01-27T16:53:08.8445724Z 2025-01-27T16:53:08.229+0000 [DEBUG] [org.sonarqube.gradle.SonarTask] Creating module hierarchy
2025-01-27T16:53:08.8447471Z 2025-01-27T16:53:08.230+0000 [DEBUG] [org.sonarqube.gradle.SonarTask]   Init module '***-plugin-sourcegen-parent'
2025-01-27T16:53:08.8448869Z 2025-01-27T16:53:08.230+0000 [DEBUG] [org.sonarqube.gradle.SonarTask]     Base dir: /home/runner/work/***-plugin-sourcegen/***-plugin-sourcegen
2025-01-27T16:53:08.8449959Z 2025-01-27T16:53:08.230+0000 [DEBUG] [org.sonarqube.gradle.SonarTask]     Working dir: /home/runner/work/***-plugin-sourcegen/***-plugin-sourcegen/build/sonar
2025-01-27T16:53:08.8450835Z 2025-01-27T16:53:08.230+0000 [DEBUG] [org.sonarqube.gradle.SonarTask]     Module global encoding: UTF-8, default locale: en
2025-01-27T16:53:08.8451664Z 2025-01-27T16:53:08.230+0000 [DEBUG] [org.sonarqube.gradle.SonarTask]   Init module '***-plugin-sourcegen-annotations'
2025-01-27T16:53:08.8452773Z 2025-01-27T16:53:08.230+0000 [DEBUG] [org.sonarqube.gradle.SonarTask]     Base dir: /home/runner/work/***-plugin-sourcegen/***-plugin-sourcegen/***-plugin-sourcegen-annotations
2025-01-27T16:53:08.8453659Z 2025-01-27T16:53:08.767+0000 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] 
2025-01-27T16:53:08.8454447Z 2025-01-27T16:53:08.767+0000 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] FAILURE: Build failed with an exception.
2025-01-27T16:53:08.8455212Z 2025-01-27T16:53:08.767+0000 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] 
2025-01-27T16:53:08.8455899Z 2025-01-27T16:53:08.768+0000 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] * What went wrong:
2025-01-27T16:53:08.8457078Z 2025-01-27T16:53:08.768+0000 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] Execution failed for task ':sonar'.
2025-01-27T16:53:08.8458111Z 2025-01-27T16:53:08.768+0000 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] > Unable to load component class org.sonar.scanner.scan.filesystem.InputComponentStore

@sdelamo sdelamo changed the base branch from master to 0.0.x January 28, 2025 14:07
@melix
Copy link

melix commented Jan 28, 2025

@melix Do you know what might be causing the sonar issue?

Is the project created in sonar cloud?

@sdelamo
Copy link
Contributor

sdelamo commented Jan 28, 2025

@melix Do you know what might be causing the sonar issue?

Is the project created in sonar cloud?

I have just created it. We had not completed #3

@melix
Copy link

melix commented Jan 28, 2025

In checklists we trust!

@sdelamo
Copy link
Contributor

sdelamo commented Jan 28, 2025

@andriy-dmytruk sonatype is now running but failing :-)

@graemerocher
Copy link
Contributor

@andriy-dmytruk can you address the sonar failures :)

@graemerocher graemerocher merged commit 3785477 into 0.0.x Jan 29, 2025
12 checks passed
@graemerocher
Copy link
Contributor

@andriy-dmytruk merged this but documentation publishing seems broken

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

Successfully merging this pull request may close these issues.

4 participants