-
Notifications
You must be signed in to change notification settings - Fork 28.7k
Refactor Flutter Gradle Plugin so it can be applied using the declarative plugins {}
block
#123511
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
Refactor Flutter Gradle Plugin so it can be applied using the declarative plugins {}
block
#123511
Conversation
df323f9
to
0e11466
Compare
Successfully built Now I'm thinking what to do next: 1) All in
I think it won't be a breaking change since it'll be handled automatically by the migration. So we won't have to go through this process. 2) GradualWe migrate some example apps, integration test apps, and benchmark apps in the The "new way" and the "old way" coexist. We should write the migration anyway, IMHO. I prefer option 1) which will require less support. |
I am skeptical of requiring the migration for all apps even if we build a tool to do the migration. That said for code owned by flutter I think I could get behind requiring the migration. |
Neat! What would be the advantage of option 1 over option 2? What sorts of things would we be able to do because we're no longer supporting the old way, or what sorts of work would be required to continue supporting the old way? I'd be nervous about going all at once to supporting only the new way. Doing so would mean that if for any particular project the automatic migration doesn't quite work 100% seamlessly out of the box, that project would be totally blocked on upgrading Flutter until they figure out what this transition is about well enough for them to make the migration manually. Based on the diff in the example app, this will probably be a more complex migration than many migrations are. And the app build.gradle is a file that people regularly make manual changes to, for a variety of good and necessary reasons. So between those two factors, I think it's fairly likely that however well we write the auto-migration, there will be some projects where the file has been rearranged enough that the auto-migration isn't able to completely understand what's going on, and doesn't apply its changes. OTOH if
then after that's been out in a stable release for some time, if there's a clear benefit we'd get (perhaps even just cleaning up the code) from dropping support for the old way, I think dropping it would be a lot more palatable at that point. One point of comparison is Flutter's deprecation policy:
I think that policy doesn't directly apply here; it's intended for the framework's Dart API. But as long as there's an auto-migration, I think the situation is pretty comparable, and it'd be reasonable to take the same approach. |
4e7f9cd
to
36dc5d8
Compare
97e00ad
to
daf30af
Compare
I got both the "new" and "old" style Most tests pass except for add-to-app scenarios. Gonna work on fixing them now. |
plugins {}
block
Got all tests to pass. I'd be happy to hear your opinions on the current progress. I think the next steps are:
Automatic migrationHere's an overview of what it should do:
@gnprice raised some important caveats in this comment - the Gradle build files are often edited for various reasons, even more so in larger, complex projects. I tried to keep the migration as lean as possible, but I'm still afraid some edge cases might exist that'd make it hard/impossible to make it work 100% of the time (for example, add-to-app scenarios). So my question is: what should happen if the project can't be automatically migrated? How to fail gracefully in such a case? I'm also all in for writing a short article explaining (1) why this migration is good and (2) how to do it manually, in case it cannot be done automatically. Upgrade default templatesThat should be pretty straightforward - I've already done that in #122290 and #123426. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this looks good. Thanks for your contribution.
packages/flutter_tools/gradle/src/main/groovy/flutter.gradle.kts
Outdated
Show resolved
Hide resolved
8f00d72
to
c99259e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Small comments on the code.
So my question is: what should happen if the project can't be automatically migrated? How to fail gracefully in such a case?
Since the old way will continue to work (for some time, anyway), in this case the migration can just leave the files untouched and that will be safe.
Then it might also print a message, something like:
Unable to automatically upgrade Android build files to declarative form.
Consider doing the upgrade manually:
https://docs.flutter.dev/path/to/migration/guide
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On thinking about this again, I think it will make sense to merge this PR once the small remaining review comments are handled. The converted example validates that the new way works, and the other examples validate that the old way works.
Then the template changes and the migration can go in a followup PR or two.
Oof, Google testing failed. cc @reidbaker |
Thanks for taking a look.
Actually, I'd prefer to include template changes at least in this PR. No strong opinions though.
The main problem is that we can't detect if the migration was successful just after we've performed it. The developer has to run Gradle build, and only after it passes/fails, we can be certain. I'm not sure we could make this experience more seamless. The first idea off the top of my head:
Honestly? I hate this idea :) Another take: when the migration is performed, its logs are only printed when running with EDIT: Actually I see that |
Sure, WFM.
Ah. Yeah, the approach that's generally been taken in these migrations is to instead say: if we're not certain that the migration will be a success when it applies, then we make the patterns of what it's looking for in the file more specific until we are pretty much certain. As you outline, the model for how these migrations run doesn't really allow for a great UX/DX for doing a migration that has more uncertainty like that. I think that'd call for an interaction that the user had to more explicitly trigger — along the lines of the Android Studio upgrade wizards, and that's perhaps what I think it will be quite doable here to make a migration that we can be sure of in that way. It just means there'll be a significant swath of projects the auto-migration doesn't apply to; but the long tail which haven't changed much in this file from the template will still benefit. |
We'll need a way to test the migrations on some real apps. For example, run all the migrations over apps in
For them we could print a warning each time they
So to sum up todos:
I can create issues for them (or you can, if you want to) once you and @reidbaker agree on this rough plan. PS
I think that a separate |
/** | ||
* Some apps don't set default compile options. | ||
* Apps can change these values in android/app/build.gradle. | ||
* This just ensures that default values are set. | ||
*/ | ||
android { | ||
compileOptions { | ||
sourceCompatibility JavaVersion.VERSION_1_8 | ||
targetCompatibility JavaVersion.VERSION_1_8 | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has no effect when FGP is applied using the plugin {}
block.
Verified by changing to some ancient JavaVersion.VERSION_1_1
. examples/hello_world
(using declarative apply) continued to build fine, examples/flutter_view
(using imperative apply) started to spit out error: invalid source release: 1.1
.
It shouldn't be a big thing - the templates contain these lines anyway.
Definitely. I think customer_testing, and also Google testing, will contribute here too. There may be internal apps at Google where the overall app build doesn't get run in the presubmit "Google testing" check. In that case, once there's a draft of the migration, @reidbaker or another Googler can probably help by running the PR across those other Google-internal apps. That will confirm that the migration either succeeds, or successfully chooses not to apply itself.
SGTM!
I wouldn't consider that duplication a blocker. If the duplication is the best way to do it that we can find given how Gradle works, then that's OK. If you have any more ideas for how to deduplicate, though, it'd make sense to try a bit more. Or if you want to wait another day to see if that Stack Overflow question gets an answer. |
Hey sorry I can dig in but it will probably be a week. This impending Flamingo launch and the work associated with it is my top priority until it is handled. That said maybe another googler can take a look. @camsim99 After your gradle error catching work would you be willing to take a look at this? |
… declarative `plugins {}` block (flutter/flutter#123511)
… declarative `plugins {}` block (flutter/flutter#123511)
… declarative `plugins {}` block (flutter/flutter#123511)
… declarative `plugins {}` block (flutter/flutter#123511)
… declarative `plugins {}` block (flutter/flutter#123511)
… declarative `plugins {}` block (flutter/flutter#123511)
… declarative `plugins {}` block (flutter/flutter#123511)
… declarative `plugins {}` block (flutter/flutter#123511)
… declarative `plugins {}` block (flutter/flutter#123511)
… declarative `plugins {}` block (flutter/flutter#123511)
… declarative `plugins {}` block (flutter/flutter#123511)
… declarative `plugins {}` block (flutter/flutter#123511)
… declarative `plugins {}` block (flutter/flutter#123511)
… declarative `plugins {}` block (flutter/flutter#123511)
I'm removing an unneded block of configuration from the `settings.gradle` template. It was introduced by me in #123511. At that time, I did not know that it's unnecessary, and did not test removing it � sorry about that. I learned that it's unnecessary recently, when [I asked a question on StackOverflow](https://stackoverflow.com/questions/77073596/whats-the-difference-between-plugins-and-pluginmanagement-plugins-in). More context there.
Since WHEN AND WHICH VERSION the declarative way I have lost a half a day figuring this out!! Please someone mention the documentation or any useful link. I am using Flutter 3.10 and my android studio generates this when creating a new project
and my Colleague has this in their project
Can somebody please tell me why my version generates |
It was a gradual migration. See #135392 to see how Android build files differ between versions.
Your colleague and you have different Flutter versions installed. Upgrade to the newest one to take advantage of the latest, modern-Gradle-style template. |
This PR aims to resolve #121552.
Resources used:
This PR also paves way for #121541, because apps will no longer have:
hardcoded. Instead, they'll use:
Pre-launch Checklist
///
).