codeconsole opened a new pull request, #16009:
URL: https://github.com/apache/grails-core/pull/16009

   ## Problem
   
   `GrailsGradlePlugin.applyGrailsBom()` applies `BomPropertyOverridesPlugin` 
from inside its own `project.afterEvaluate {}` callback. Since 
`BomPropertyOverridesPlugin.apply()` itself registers a *second*, nested 
`project.afterEvaluate {}` for the actual override-application logic, and 
Gradle appends newly-registered `afterEvaluate` listeners to the end of the 
notification queue that's currently being processed, that nested registration 
ends up running **after** every `afterEvaluate` callback other plugins 
registered synchronously during `apply()` — including `GrailsCliGradlePlugin`'s 
`configureApplicationCommands` (added in #15948), which eagerly resolves the 
`api`/`implementation`/`runtimeOnly` buckets via the `grailsCliDetect` probe 
configuration and locks them against further mutation.
   
   In multi-project builds this surfaces as:
   
   ```
   Cannot mutate the dependencies of configuration ':foo:api' after the 
configuration's child
   configuration ':foo:grailsCliDetect' was resolved. After a configuration has 
been observed,
   it should not be modified.
   ```
   
   The trigger: resolving one project's `grailsCliDetect` (e.g. while a sibling 
project's own CLI probe reaches it through a `project(...)` dependency) forces 
that project to fully configure mid-resolution. If the forced configuration 
happens to land inside the window between the CLI probe locking its buckets and 
the re-queued BOM-override callback trying to mutate them, the build fails at 
configuration time — with any `grailsVersion`/BOM property override active 
(e.g. `-PgrailsVersion=...`) in a build with `project(...)` dependencies 
between Grails-plugin projects.
   
   Reproduced against a real multi-project Grails 8 app; confirmed via 
`--stacktrace` that the failure is exactly this ordering race 
(`BomManagedVersions.applyTo()` → `DependencyConstraintSet.add()` on `api`, 
after `GrailsCliGradlePlugin.autoProvisionCliDependencies()` had already 
resolved `grailsCliDetect`, which extends `api`).
   
   ## Fix
   
   Register the `bomPropertyOverrides` extension eagerly (not via 
`project.plugins.apply(BomPropertyOverridesPlugin)` inside the 
`afterEvaluate`), and call `BomPropertyOverridesPlugin.applyOverrides()` 
directly from the *existing*, correctly-ordered `afterEvaluate` callback in 
`applyGrailsBom`, immediately after the platform is injected — instead of 
re-deferring through `project.plugins.apply()`. This eliminates the extra 
deferral hop entirely while preserving the required "platform injected, then 
overrides computed" sequencing, and keeps `BomPropertyOverridesPlugin` 
unchanged for its documented standalone use case.
   
   As a side benefit, the `bomPropertyOverrides {}` extension is now created 
eagerly at `apply()` time rather than inside `afterEvaluate`, so it's now 
actually usable from a consumer's own `build.gradle` (previously the extension 
didn't exist yet when the user's own script body ran).
   
   ## Testing
   
   - `:grails-gradle-plugins:compileGroovy` — clean compile.
   - Published the patched plugin to `mavenLocal`, pointed a real multi-project 
Grails 8 app's buildscript at it (scoped via `content { includeModule(...) }` 
so only this one artifact was affected), and reran the previously-failing 
`-PgrailsVersion=8.0.0-SNAPSHOT` build: every subproject now configures 
successfully (`BUILD SUCCESSFUL`), where it previously failed with the 
`InvalidUserCodeException` above.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to