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

Features backed by Open rewrite recipes #2703

Draft
wants to merge 18 commits into
base: 4.8.x
Choose a base branch
from

Conversation

sdelamo
Copy link
Contributor

@sdelamo sdelamo commented Feb 14, 2025

No description provided.

@sdelamo sdelamo marked this pull request as draft February 14, 2025 10:33
@sdelamo
Copy link
Contributor Author

sdelamo commented Feb 14, 2025

@alvarosanchez this PR has a lot of package imports changes because I extracted a micronaut-stater-sdk module. Please, ignore those for now.

I created a proof of concept of a starter feature consuming a OpenRewrite declarative recipe, in particular Gradle and Maven dependency recipes. See the RecipeDependencyFetcher api and its usage in the Mockito feature.

What do you think? It is still far from complete but this will allow us to define every feature dependencies with open rewrite recipes. We can then move to configuration recipes etc.

@alvarosanchez
Copy link
Member

Note that there is org.openrewrite.java.dependencies.AddDependency which works for both Maven and Gradle.

Other than that, as far as I can see (the browser crashes with this gigantic PR), you're not really invoking OpenRewrite, but rather using its declarative recipe format as an alternative, internal way to define dependencies. Which, if I'm not mistaken, would end up going the same route of rendering Rocker templates.

I don't think we should do this. What I meant was to use OpenRewrite to actually perform changes to an existing project, via an additional command (eg mn add-feature). With this idea, features may (or may not) have, in addition to what they do today, a corresponding OpenRewrite recipe, that would only be used by such command. So that I can run mn add-feature mockito in my existing app. With this approach, we can gradually support more and more features in the add-feature command, without having to make deep changes in the existing Starter functionality

@sdelamo sdelamo changed the title F Features backed by Open rewrite recipes Feb 14, 2025
@sdelamo sdelamo force-pushed the openrewrite-backed-features branch from d4b4028 to d79b1d6 Compare February 14, 2025 16:19
@sdelamo
Copy link
Contributor Author

sdelamo commented Feb 14, 2025

@alvarosanchez I think we are on the same page. I pushed an extra commit which hopefully clarifies the direction I am suggesting.

As you said, I want to support both use cases:

  • Project Creation (create, create-app, ... commands),
  • Project Modification (add-feature command).

Project Modification will invoke OpenRewrite recipes in an existing project. However, I have not implemented that yet. I have pushed a commit with an AddFeatureCommand class with a TODO where we will invoke OpenRewrite to execute the rules associated with features.

To gradually add features I have created a marker interface OpenRewriteFeature. Beans of type OpenRewriteFeature have OpenRewrite rules associated with them.

For me, the key is to define things only in a single place. That it is the reason why I created the RecipeDependencyFetcher API. To support defining the dependencies as open rewrite rules but transform those rules to Dependencyies to support the project creation use case. We will define the dependencies a feature adds on a single place - the OpenRewrite recipe associated with the feature.

NOTE: Currently, OpenRewrite does not support adding a gradle dependency to a Gradle file using the Kotlin DSL only the Groovy DSL.

Let me know if you think I am going in the right direction.

extract variable
@sdelamo sdelamo force-pushed the openrewrite-backed-features branch from 76021a9 to 362de03 Compare February 14, 2025 16:34
@@ -1,13 +1,10 @@
---
type: specs.openrewrite.org/v1beta/recipe
name: micronaut.starter.feature.mockito.AddDependencyMockito
name: micronaut.starter.feature.Mockito
Copy link
Member

Choose a reason for hiding this comment

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

Convention seems to be using package names.

Also, I'd have a YML per main recipe, instead of having a huge rewrite.yml. OpenRewrite will detect them all within META-INF/rewrite.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not sure about using multiple files, we can decided about this later. micronaut resource loader api is not super flexible.

public interface OpenRewriteFeature extends Feature {

@NonNull
String getRecipeName();
Copy link
Member

Choose a reason for hiding this comment

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

I suppose this also supports using Refaster and imperative recipes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I have tried only with declarative recipes. But ideally, we should support every type of recipe.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

maybe we could use a default convention such as io.micronaut.starter.feature.${featureName} to ensure unique name

@alvarosanchez
Copy link
Member

@sdelamo amazing, then we are in agreement!

@sdelamo
Copy link
Contributor Author

sdelamo commented Feb 17, 2025

@alvarosanchez I have pushed a commit of an example of a feature contributing configuration. d71a1e7

We are going to need to create our own AddProperty implementation similar to AddSpringProperty, or AddQuarkusProperty as the AddProperty I used in my commit does not allow to provide a fileMatcher and in a Micronaut Application the property entry will be added to gradle.properties instead of application.properties in Micronaut gradle app.

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