openrewrite / rewrite

Automated mass refactoring of source code.
https://docs.openrewrite.org
Apache License 2.0
2.15k stars 321 forks source link

Openrewrite: apply recipe list step by step (to have a proper commit history) #4052

Closed yluom closed 7 months ago

yluom commented 7 months ago

What problem are you trying to solve?

I want to apply the openrewrite recipe list for migrating to java 17 to my codebase, and commit each step separately.

It works wonderfully using the provided mvn command, but all changes (listed in the "recipe list") are done at the same time and thus can't be commited separately.

I am dealing with a huge codebase and I can't just have a single commit "Java 17 migration" that includes thousands and thousands of changes which are unrelated (e.g. java multiline strings changes in the same commit as dependencies changes).

Describe the solution you'd like

I wonder if there is a convenient solution, like an "interactive mode", that would apply each item from the recipe list, pause to let me commit changes properly and then continue applying next item ? Maybe even automatically commit each step for me following a commit message pattern?

Have you considered any alternatives or workarounds?

Of course, I can run each step separately and manually commit every step, but it's not convenient and timeconsuming ... which is what we are trying to avoid with openrewrite right ? :)

Are you interested in [contributing this feature to OpenRewrite]

Might be interested to contribute if it doesn't exist!

timtebeek commented 7 months ago

Glad to hear the recipe at least works wonderfully, and you like the changes enough to want to commit them. Our recipes are highly hierarchical in nature, and when you execute the Java 17 migration, you're actually executing 180 individual migration recipes. Some of those recipes are partial steps, that by themselves would not make sense; consider for instance how different recipes change imports versus add a dependency; you'd need both for the change to make sense, and committing just a part of that would lead to failing intermediate steps. That's why we don't support intermediate steps to commit the results; it would simply be too much to handle feasibly. We'd also have to write out to disk repeatedly, which would slow the migration down even more.

I do understand that you'd like to migrate in steps, and for that I have a couple recommendations that you can combine as needed.

  1. Firstly you can run only part of the hierarchy; for instance: Migrate to Java 17 is composed of Migrate to Java 11, Migrate to Jakarta EE 9, and Migrate to Java 8. You can run each of these separately

  2. You can also use Preconditions to limit the changes to for instance a particular source set or set of files.

Using these two approaches together in separate runs you can likely create something that's feasible to review still, especially as the changes are likely very similar when constrained through 1.

Each recipe run would however have to build up the lossless semantic tree yet again, which can take some time, especially for larger projects. If you'd like to speed that up you can have a look at Moderne.io, where we allow you to use precomputed LSTs.

I hope that helps you see a way forward to get these changes across the line. Always welcome to ask questions in our Slack as well.

Answer lifted over from Stackoverflow; there's no need to ask both there and here; I monitor both + Slack. :)