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]