Repository navigation
[AGP 9.1.0 Migration #4] Replace plugin build-type copy with initWith on public DSL - #191606
Conversation
4aa474b to
9ad1211
Compare
9ad1211 to
f678456
Compare
20c1a4c to
5010702
Compare
| signal (the library-plugin build-type copy in `PluginHandler`). This | ||
| preserves add-to-app custom-debuggable matching (a host `staging` | ||
| debuggable build type maps to debug engine artifacts). | ||
| 6. **P3 pre-spike / PR 4 (afterEvaluate DSL mutation under newDsl).** The planned scratch-app |
There was a problem hiding this comment.
What purpose does this planning doc serve now that the work is done. Do any future prs in the 11 pr stack reference P3?
There was a problem hiding this comment.
This design/migration doc serves as the persistent architectural record for the AGP 9 public API migration (#180137) documenting why specific public API approaches (like initWith, AgpCommonExtensionWrapper, and onVariants) were chosen and how edge cases (like finalizeDsl fallback) are handled. Future PRs in the stack (PR 10 and PR 11) reference this document for the complete migration context.
| // Copy the app project's build types onto the plugin project so that its variants | ||
| // resolve. These are `initWith` copies, not live aliases: `initWith` copies the | ||
| // properties both build types understand (matchingFallbacks included), and | ||
| // app-specific properties are additionally copied when both sides are application | ||
| // build types. Library build types cannot receive app-specific properties (such | ||
| // as isDebuggable) through the public DSL. |
There was a problem hiding this comment.
Is the point of this work to help libraries handle the migration with fewer breaking changes? If so can you give an example? Or maybe is this a carry over from supporting flavors. Either way I dont understand why this change is needed.
There was a problem hiding this comment.
In Gradle / AGP, when an app defines custom build types (e.g. staging, profile_qa), Gradle variant matching requires plugin library subprojects (e.g. :camera_android) to define matching build types or compatible matchingFallbacks. Because Flutter plugins are authored independently and only define debug and release, building an app with custom build types would fail variant resolution without this copy step.
copyAppBuildTypesToPlugin copies missing build types from the app to the plugin project. This PR migrates that copy logic away from internal AGP types (com.android.build.gradle.internal.dsl.BuildType) to the public DSL create(name) { initWith(appBuildType) }.
| } | ||
| val pluginProject: Project = project.rootProject.findProject(":$pluginName") ?: return | ||
|
|
||
| // Warning: Iterating buildTypes causes the project-level 'implementation' dependency to be added multiple times. |
There was a problem hiding this comment.
I added this comment because it came up in adversarial review but was unrelated to the change in this pr.
| val dependencyProject = | ||
| project.rootProject.findProject(":$pluginDependencyName") ?: return@innerForEach | ||
| pluginProject.afterEvaluate { | ||
| // this.dependencies.add("implementation", dependencyProject) |
There was a problem hiding this comment.
Intentional removal of dead code.
| action.execute(createdBuildType) | ||
| createdBuildType | ||
| } | ||
| pluginProjectBuildTypes.create("staging", capture(createActionSlot)) |
There was a problem hiding this comment.
It looks like this test moved from debug to staging? why?
There was a problem hiding this comment.
In AGP, standard projects already have debug and release build types created by default. Using a custom build type like staging cleanly tests the behavior of creating a missing custom build type from the app on the plugin project without colliding with default build types. (A separate test at line 282 explicitly verifies that pre-existing build types are skipped).
| verify { pluginProject.afterEvaluate(capture(capturePluginActionSlot)) } | ||
| capturePluginActionSlot.forEach { it.execute(pluginProject) } | ||
|
|
||
| // For library plugins, individual missing build types must be created explicitly rather than bulk-copied. |
There was a problem hiding this comment.
Is this comment no longer valuable or correct?
There was a problem hiding this comment.
The old comment was contrasting legacy addAll (for app plugins) with manual property copying (for library plugins). In the new implementation, both app and library plugins use the unified public create(name) { initWith(appBuildType) } mechanism. Detailed KDoc explaining the initWith copy semantics across library and application build types is documented directly in PluginHandler.kt.
| ) | ||
|
|
||
| verify { pluginProject.afterEvaluate(capture(capturePluginActionSlot)) } | ||
| capturePluginActionSlot[0].execute(pluginProject) |
There was a problem hiding this comment.
Why change from using the first to a list?
There was a problem hiding this comment.
PluginHandler.configurePlugins registers multiple afterEvaluate callbacks on pluginProject (e.g. for plugin dependencies and embedding dependencies). Executing only capturePluginActionSlot[0] left subsequent registered actions unexecuted in the test, making the test brittle to callback registration ordering. Using capturePluginActionSlot.forEach { it.execute(pluginProject) } ensures that all registered lifecycle actions are executed.
| } | ||
|
|
||
| val container = mockk<NamedDomainObjectContainer<ApplicationBuildType>>() | ||
| val container = mockk<NamedDomainObjectContainer<ApplicationBuildType>>(relaxed = true) |
There was a problem hiding this comment.
Is relaxed needed here? does it avoid a lot of setup? if not can we remove it?
There was a problem hiding this comment.
Removed relaxed = true. The mock container now explicitly stubs findByName (returning matching build types from the list or null) and create (executing configuration actions), providing realistic container semantics without relaxed mocks.
|
|
||
| /** | ||
| * Guards the AGP public-API migration (https://github.com/flutter/flutter/issues/180137): | ||
| * production sources must not use AGP internals. AGP 10 removes access to internals |
There was a problem hiding this comment.
AGP 10 is not published so we can not say that it removes access to internals.
There was a problem hiding this comment.
This is similar to packages/flutter_tools/gradle/src/test/kotlin/BytecodeValidatorTest.kt
I think we should put all the test that help enforce that our flutter gradle plugin code follows the right imports into their own folder that is different from code that verifies that the flutter gradle plugin code works the way we expect.
There was a problem hiding this comment.
Updated the KDoc and assertions to avoid speculative claims about unpublished AGP versions, framing the rule around ensuring FGP production code uses the public AGP DSL surface and is ready to compile against the public gradle-api artifact.
There was a problem hiding this comment.
Moved InternalAgpApiImportTest.kt into packages/flutter_tools/gradle/src/test/kotlin/validation/ (package com.flutter.gradle.validation). Relocating pre-existing tests like BytecodeValidatorTest.kt can be done in a dedicated cleanup PR to keep downstream PR rebases clean.
6474d60 to
b236996
Compare
…With on the public DSL - PluginHandler no longer imports com.android.build.gradle.internal.dsl.BuildType. The build-type copy block that shared live legacy BuildType instances (addAll) for app-type plugin projects and hand-copied two properties for library plugin projects is replaced by a single initWith-based copy on the public DSL containers: missing build types are created on the plugin project with initWith(appBuildType) (which carries matchingFallbacks), and isDebuggable is additionally copied when both sides are application build types. Library build types cannot receive app-specific properties through the public DSL - this is a documented behavior change of the migration. - Production sources are now free of com.android.build.gradle.internal imports; InternalAgpApiImportTest locks that in. - PluginHandlerTest: replaced legacy mock-only copy tests with tests that run configurePlugins and assert the initWith copy for both library and app plugin projects, including the custom-debuggable-build-type -> debug engine artifact mapping and skipping pre-existing build types. - Updated documentation with P3 pre-spike and finalizeDsl fallback details.
b236996 to
85e9f2b
Compare
There was a problem hiding this comment.
Code Review
This pull request migrates the Flutter Gradle Plugin's build type copying logic to use the public Android Gradle Plugin (AGP) DSL instead of internal AGP APIs. It introduces copyAppBuildTypesToPlugin in PluginHandler to copy app build types to plugin projects using initWith and public DSL properties, removing legacy extension utilities. Unit tests are updated to mock the public ApplicationExtension and LibraryExtension APIs, and a new architectural test InternalAgpApiImportTest is added to prevent future imports of AGP internal packages in production code. I have no feedback to provide as there are no review comments.
|
@reidbaker-agent can you respond to this comment with an integration test that already exists in the flutter codebase that executes the code path modified in this pr? Or if one does not exist say that. |
|
@reidbaker Yes, several integration tests in the Flutter repository execute this code path (
|
|
For custom build types and product flavors, the following integration and DeviceLab tests specifically cover these workflows:
How this relates to PR 4: When an app defines both product flavors (e.g. |
flutter/flutter@8d8c1aa...c978386 2026-08-30 [email protected] Roll Skia from ce359c7fbfe6 to 588b550a4dd8 (1 revision) (flutter/flutter#192040) 2026-08-30 [email protected] Roll Skia from 3ae8e3d1e335 to ce359c7fbfe6 (1 revision) (flutter/flutter#192037) 2026-08-30 [email protected] Roll Fuchsia Linux SDK from J123CwfDPYyVDpkMl... to o9DikEfRoFyVK3LKD... (flutter/flutter#192031) 2026-08-29 [email protected] Make the AbsorbPointer sample show the difference from IgnorePointer (flutter/flutter#188940) 2026-08-29 [email protected] Roll Dart SDK from 391ff83cd1d3 to 76abdf94faa8 (1 revision) (flutter/flutter#192021) 2026-08-29 [email protected] Roll Skia from b392fb672d13 to 3ae8e3d1e335 (1 revision) (flutter/flutter#192020) 2026-08-29 [email protected] Roll Skia from 0b4249b26b38 to b392fb672d13 (6 revisions) (flutter/flutter#192016) 2026-08-29 [email protected] Fixes for texture-backed gradients (flutter/flutter#191925) 2026-08-29 [email protected] Roll Dart SDK from ae63a6eca3f1 to 391ff83cd1d3 (3 revisions) (flutter/flutter#192010) 2026-08-29 [email protected] Fix Android license detection for cmdline-tools 23.0+ (flutter/flutter#191554) 2026-08-29 [email protected] [flutter_tools] Pause web server requests until initial compilation finishes (flutter/flutter#191990) 2026-08-28 [email protected] fix(workflow): Mac Verify Binaries needs `Linux mac_android_aot_engine` (flutter/flutter#191999) 2026-08-28 [email protected] Roll Fuchsia Linux SDK from dDxH8G5cDBP602eyG... to J123CwfDPYyVDpkMl... (flutter/flutter#191984) 2026-08-28 [email protected] Update scheduled workflow for more tasks, add goldctl update (flutter/flutter#191991) 2026-08-28 [email protected] Update no-main-prs to leave a comment (flutter/flutter#191973) 2026-08-28 [email protected] [AGP 9.1.0 Migration #4] Replace plugin build-type copy with initWith on public DSL (flutter/flutter#191606) 2026-08-28 [email protected] Roll Skia from fe0b9a5261f9 to 0b4249b26b38 (1 revision) (flutter/flutter#191974) 2026-08-28 [email protected] [UIScene] Migrate dev/benchmarks/macrobenchmarks to UIScene lifecycle (flutter/flutter#191648) 2026-08-28 [email protected] Uiscene migrate remaining apps (flutter/flutter#191652) 2026-08-28 [email protected] [tool] Migrate SymbolizeCommand to modular dependency injection (flutter/flutter#190744) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…r#12693) flutter/flutter@8d8c1aa...c978386 2026-08-30 [email protected] Roll Skia from ce359c7fbfe6 to 588b550a4dd8 (1 revision) (flutter/flutter#192040) 2026-08-30 [email protected] Roll Skia from 3ae8e3d1e335 to ce359c7fbfe6 (1 revision) (flutter/flutter#192037) 2026-08-30 [email protected] Roll Fuchsia Linux SDK from J123CwfDPYyVDpkMl... to o9DikEfRoFyVK3LKD... (flutter/flutter#192031) 2026-08-29 [email protected] Make the AbsorbPointer sample show the difference from IgnorePointer (flutter/flutter#188940) 2026-08-29 [email protected] Roll Dart SDK from 391ff83cd1d3 to 76abdf94faa8 (1 revision) (flutter/flutter#192021) 2026-08-29 [email protected] Roll Skia from b392fb672d13 to 3ae8e3d1e335 (1 revision) (flutter/flutter#192020) 2026-08-29 [email protected] Roll Skia from 0b4249b26b38 to b392fb672d13 (6 revisions) (flutter/flutter#192016) 2026-08-29 [email protected] Fixes for texture-backed gradients (flutter/flutter#191925) 2026-08-29 [email protected] Roll Dart SDK from ae63a6eca3f1 to 391ff83cd1d3 (3 revisions) (flutter/flutter#192010) 2026-08-29 [email protected] Fix Android license detection for cmdline-tools 23.0+ (flutter/flutter#191554) 2026-08-29 [email protected] [flutter_tools] Pause web server requests until initial compilation finishes (flutter/flutter#191990) 2026-08-28 [email protected] fix(workflow): Mac Verify Binaries needs `Linux mac_android_aot_engine` (flutter/flutter#191999) 2026-08-28 [email protected] Roll Fuchsia Linux SDK from dDxH8G5cDBP602eyG... to J123CwfDPYyVDpkMl... (flutter/flutter#191984) 2026-08-28 [email protected] Update scheduled workflow for more tasks, add goldctl update (flutter/flutter#191991) 2026-08-28 [email protected] Update no-main-prs to leave a comment (flutter/flutter#191973) 2026-08-28 [email protected] [AGP 9.1.0 Migration flutter#4] Replace plugin build-type copy with initWith on public DSL (flutter/flutter#191606) 2026-08-28 [email protected] Roll Skia from fe0b9a5261f9 to 0b4249b26b38 (1 revision) (flutter/flutter#191974) 2026-08-28 [email protected] [UIScene] Migrate dev/benchmarks/macrobenchmarks to UIScene lifecycle (flutter/flutter#191648) 2026-08-28 [email protected] Uiscene migrate remaining apps (flutter/flutter#191652) 2026-08-28 [email protected] [tool] Migrate SymbolizeCommand to modular dependency injection (flutter/flutter#190744) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…r#12693) flutter/flutter@8d8c1aa...c978386 2026-08-30 [email protected] Roll Skia from ce359c7fbfe6 to 588b550a4dd8 (1 revision) (flutter/flutter#192040) 2026-08-30 [email protected] Roll Skia from 3ae8e3d1e335 to ce359c7fbfe6 (1 revision) (flutter/flutter#192037) 2026-08-30 [email protected] Roll Fuchsia Linux SDK from J123CwfDPYyVDpkMl... to o9DikEfRoFyVK3LKD... (flutter/flutter#192031) 2026-08-29 [email protected] Make the AbsorbPointer sample show the difference from IgnorePointer (flutter/flutter#188940) 2026-08-29 [email protected] Roll Dart SDK from 391ff83cd1d3 to 76abdf94faa8 (1 revision) (flutter/flutter#192021) 2026-08-29 [email protected] Roll Skia from b392fb672d13 to 3ae8e3d1e335 (1 revision) (flutter/flutter#192020) 2026-08-29 [email protected] Roll Skia from 0b4249b26b38 to b392fb672d13 (6 revisions) (flutter/flutter#192016) 2026-08-29 [email protected] Fixes for texture-backed gradients (flutter/flutter#191925) 2026-08-29 [email protected] Roll Dart SDK from ae63a6eca3f1 to 391ff83cd1d3 (3 revisions) (flutter/flutter#192010) 2026-08-29 [email protected] Fix Android license detection for cmdline-tools 23.0+ (flutter/flutter#191554) 2026-08-29 [email protected] [flutter_tools] Pause web server requests until initial compilation finishes (flutter/flutter#191990) 2026-08-28 [email protected] fix(workflow): Mac Verify Binaries needs `Linux mac_android_aot_engine` (flutter/flutter#191999) 2026-08-28 [email protected] Roll Fuchsia Linux SDK from dDxH8G5cDBP602eyG... to J123CwfDPYyVDpkMl... (flutter/flutter#191984) 2026-08-28 [email protected] Update scheduled workflow for more tasks, add goldctl update (flutter/flutter#191991) 2026-08-28 [email protected] Update no-main-prs to leave a comment (flutter/flutter#191973) 2026-08-28 [email protected] [AGP 9.1.0 Migration flutter#4] Replace plugin build-type copy with initWith on public DSL (flutter/flutter#191606) 2026-08-28 [email protected] Roll Skia from fe0b9a5261f9 to 0b4249b26b38 (1 revision) (flutter/flutter#191974) 2026-08-28 [email protected] [UIScene] Migrate dev/benchmarks/macrobenchmarks to UIScene lifecycle (flutter/flutter#191648) 2026-08-28 [email protected] Uiscene migrate remaining apps (flutter/flutter#191652) 2026-08-28 [email protected] [tool] Migrate SymbolizeCommand to modular dependency injection (flutter/flutter#190744) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
This is PR 4 of 11 in the AGP 9.1.0 / public
gradle-api/ newdsl migration stack.There are no breaking changes expected in this pr. Only internal logic is impacted.
I will be honest I also found the tests hard to review. I had the agent pull out shared mocking logic but I am not sure that actually made review easier.
Depends on #191218 (PR 3).
Standard review context for this pr stack
This is PR is part of an 11 pr stack to migrate the "newdsl"
gradle-apispecifically in agp 9.1.0.All of the code was LLM authored. A mix of manual prompting, automatic prompting, several models and adversarial review. The combined sessions are enough that I cannot include relevant prompts like I have been doing on other prs.
If you want to review the pr stack you can find it here. These prs will be abandoned/closed as prs land into flutter/flutter.
This work is urgent in the sense that we are worried that android will publish agp 10 with no opt out but not so urgent that we are willing to break flutter users because we didn't review or understand the code because we were in a rush.
Breaking changes are expected as part of this work. There are patterns the android team explicitly does not want apps to use and apis that have no equivalent.
As part of the effort to ensure this work does not slip into ai slop, prs from this stack will be reviewed by me (@reidbaker) before asking for review. Then we will have 2 android expert reviewers also review every pr.
Agent authored description.
This is PR 4 of 11 in the AGP 9.1.0 / public
gradle-apimigration stack (#180137, #166550).Key Changes
initWithCopy: Replaces the legacygetLegacyAndroidExtensionbuild-type copy inPluginHandlerwithinitWithon the public DSL (AgpCommonExtensionWrapper.buildTypes). Missing build types on the plugin project are created withinitWith(appBuildType), andisDebuggableis copied when both sides areApplicationBuildType.com.android.build.gradle.internalimports from production code (src/main).InternalAgpApiImportTestto continuously enforce that production sources do not introducecom.android.build.gradle.internal.*imports.PluginHandlerTestwith tests that executeconfigurePluginsand verifyinitWithcopying for both library and application plugin projects, mapping custom debuggable build types to debug engine artifacts, and verifying that pre-existing plugin build types are skipped.finalizeDslfallback inMigrating-Flutter-Gradle-Plugin-to-AGP-public-API.md.Pre-launch Checklist
///).