feat(deps): Bump Micronaut platform to 5.0.0 (GA)#15677
Conversation
Micronaut Platform 5.0.0 shipped on Maven Central (io.micronaut.platform:micronaut-platform:5.0.0). Replace the 5.0.0-M2 milestone we were tracking with the released GA. Accompanying alignments required to keep validateDependencyVersions green: - dependencies.gradle: bump the grails-micronaut-bom Groovy override from 5.0.5 to 5.0.6 so the strict pin matches Micronaut 5 GA's managed groovy.version. spock stays at 2.4-groovy-5.0 (unchanged in GA). - grails-bom/micronaut/build.gradle: refresh the comment on the tools.jackson exclude. Micronaut 5.0.0 ships jackson-bom 3.1.3 while Spring Boot 4.0.6 ships 3.1.2 - the two platforms still disagree on the patch, but the direction is now reversed (Micronaut ahead of Spring Boot rather than behind). The exclude itself stays in place so spring-boot-dependencies remains the single source of truth for Jackson 3. This is the first commit of a draft PR; more fallout is expected as downstream modules pick up the new platform. Assisted-by: claude-code:claude-opus-4-7
Micronaut 5.0.0 GA publishes JARs with `org.gradle.jvm.version=25` and bytecode targeting JVM 25. The Grails 8 baseline is JDK 21, so the Java 21 matrix entries in `gradle.yml` cannot resolve or compile the Grails-Micronaut "island" (grails-micronaut, grails-micronaut-bom, the four micronaut-tied test-examples) without UnsupportedClassVersionError. The `-PskipMicronautProjects` mechanism already exists in `settings.gradle` (added in #15613) and is already wired into `groovy-joint-workflow.yml` (line 175). Mirror that pattern in the main `gradle.yml` matrix: pass the flag on Java 21 jobs only and let Java 25 jobs build the full graph including the Micronaut island. Jobs touched: - `build` - conditional flag, was failing on Java 21 - `buildRerunTasks` - Java 21 only, unconditional flag - `functional` - conditional flag - `mongodbFunctional` - conditional flag - `hibernate5Functional` - conditional flag `buildGradle` (grails-gradle composite build) and `buildForge` (grails-forge composite build) are left untouched - both are separate composite builds that do not include the Grails-Micronaut island and were not failing for this reason. Verified locally: ``` JAVA_HOME=corretto-21 ./gradlew validateDependencyVersions \ compileGroovy compileTestGroovy -PskipMicronautProjects # BUILD SUCCESSFUL JAVA_HOME=corretto-25 ./gradlew :grails-micronaut:compileGroovy \ :grails-test-examples-micronaut:compileGroovy ... # BUILD SUCCESSFUL JAVA_HOME=corretto-25 ./gradlew validateDependencyVersions # BUILD SUCCESSFUL ``` The `publish` job (line 388) still pins `java-version: 21` and would fail to publish Micronaut artifacts after this change. That is a release-flow gap that needs a separate follow-up (likely a parallel `publishMicronaut` job on JDK 25, or moving the existing job to JDK 25), tracked in the PR description. Assisted-by: claude-code:claude-opus-4-7
`micronautSerdeJacksonVersion=2.11.0` was pinned in January 2024 and
has missed 15 patch releases on the Micronaut Serde 2.x line. Bump
to the latest 2.x release, 2.16.2 (2025-11-10).
Stays on the 2.x line deliberately. Micronaut Serde 3.0.0 (which
the Micronaut 5 platform manages) has a hard compile dependency on
`micronaut-core:5.0.0` and would drag the Micronaut Core 5 / JVM 25
constraint into the main Grails graph. The consumers of this pin
(`grails-data-graphql/plugin` and the four `grails-test-examples/
graphql/*` apps) live outside the Grails-Micronaut "island" and
build on JDK 21, so they cannot take Serde 3.0.0.
The pin is intentionally floated outside the BOM today (per the
comment in `gradle.properties` line 55: "micronaut libraries not in
the bom due to the potential for spring mismatches"). That stays
the same; just the version moves.
`micronautRxjava2Version=2.9.0` is already the latest published
release on the Micronaut RxJava 2 line and is not bumped here. That
project has not been ported to Micronaut 5 (the platform removed
`io.micronaut.rxjava2` in PR micronaut-platform#1427) and 2.9.x
remains the current default branch.
Verified locally on JDK 21:
```
./gradlew validateDependencyVersions \
:grails-data-graphql:compileGroovy \
:grails-test-examples-graphql-grails-docs-app:compileGroovy \
:grails-test-examples-graphql-grails-docs-app:compileIntegrationTestGroovy \
:grails-test-examples-graphql-grails-multi-datastore-app:compileGroovy \
:grails-test-examples-graphql-grails-multi-datastore-app:compileIntegrationTestGroovy \
:grails-test-examples-graphql-grails-test-app:compileGroovy \
:grails-test-examples-graphql-grails-test-app:compileIntegrationTestGroovy \
:grails-test-examples-graphql-grails-tenant-app:compileGroovy \
:grails-test-examples-graphql-grails-tenant-app:compileIntegrationTestGroovy \
-PskipMicronautProjects
# BUILD SUCCESSFUL
```
Assisted-by: claude-code:claude-opus-4-7
The Forge composite build includes the root grails-core build via
`includeBuild('..')` in `grails-forge/settings.gradle:75`. When the
`buildForge` job in `.github/workflows/gradle.yml` runs `./gradlew
build` on Java 21, that triggers task resolution in the included
grails-core build - which pulls the JVM-25 Micronaut island and
fails with `Could not resolve io.micronaut:micronaut-inject-groovy`
(only compatible with JVM 25+).
Apply the same conditional `-PskipMicronautProjects` flag as the
other Java 21 matrix jobs. Forge itself stays on Micronaut 4.10.10
regardless; the flag only affects the included grails-core build's
Micronaut island, not Forge's own Micronaut 4 modules.
Verified locally on JDK 21:
```
cd grails-forge && JAVA_HOME=corretto-21 \
./gradlew assemble -PgrailsIndy=false -PskipCodeStyle \
-PskipTests -PskipMicronautProjects
# BUILD SUCCESSFUL
```
Assisted-by: claude-code:claude-opus-4-7
… tests
The `GraphQLSpec` test trait in `grails-data-graphql/plugin` shipped a
Micronaut RxJava2 HTTP client (`io.micronaut.rxjava2:micronaut-rxjava2-http-client`)
purely to exercise the GraphQL controller from integration tests. Spring
Boot 4 already provides everything that trait needs via Spring's
`RestClient` (org.springframework.web.client.RestClient) - there is no
reason for a Grails GraphQL plugin to depend on the Micronaut HTTP stack,
and `io.micronaut.rxjava2` has not been ported to Micronaut 5 anyway.
Replace the Micronaut HTTP client with Spring `RestClient`:
- `GraphQLSpec.groovy` is rewritten to use `RestClient.builder()` with a
single `StringHttpMessageConverter` (configured to accept all media
types). JSON encoding/decoding is handled by Groovy's `JsonOutput` and
`JsonSlurper` so the trait does not pull a Jackson or Gson runtime
onto the consuming apps - the graphql test apps use `grails-views-gson`
but do not actually ship the Gson library, and Grails 8 does not ship
Jackson on the default classpath either.
- Helper return type changes from `io.micronaut.http.HttpResponse<Map>`
to `org.springframework.http.ResponseEntity<Map>`. Spring's
`ResponseEntity.getBody()` returns `T` directly (not `Optional<T>`),
so the 109 `resp.body()` call sites collapse to `resp.body` (Groovy
property access) across 17 integration test specs.
- The two-arg `graphql(String, Class<T>)` overload survives but is now
String-only (the one caller, `InheritanceIntegrationSpec`, asserts on
the raw JSON string body). The single remaining `resp.getBody().get()`
call site (from Micronaut's `Optional`-returning getter) becomes
`resp.getBody()`.
The unused-after-removal version pins are dropped from `gradle.properties`:
- `micronautRxjava2Version=2.9.0` - was the rxjava2 client pin.
- `micronautSerdeJacksonVersion=2.16.2` - was only there as the JSON
mapper for the rxjava2 client. No production code uses
`@Serdeable` or any `io.micronaut.serde.*` API; confirmed via grep
across `grails-data-graphql/` and `grails-test-examples/graphql/`.
Each of the 4 graphql test apps loses both `implementation` lines (rxjava2
+ serde-jackson) - they brought no Spring Boot-side value once the Mn
HTTP client is gone.
Verified locally on JDK 21:
```
./gradlew validateDependencyVersions \
:grails-test-examples-graphql-grails-test-app:integrationTest \
:grails-test-examples-graphql-grails-docs-app:integrationTest \
:grails-test-examples-graphql-grails-multi-datastore-app:integrationTest \
:grails-test-examples-graphql-grails-tenant-app:integrationTest \
-PskipMicronautProjects
# BUILD SUCCESSFUL - all integration tests pass across all 4 apps
```
Side note: this closes the long-standing "out-of-band Micronaut pin"
comment in `gradle.properties`: nothing in grails-core now depends on
Micronaut artifacts outside the Grails-Micronaut "island" managed by
`grails-micronaut-bom`.
Assisted-by: claude-code:claude-opus-4-7
…lish
The existing `publish` job runs on JDK 21 and invokes the aggregate
`publish` task across the whole project. With the Micronaut 5 platform
bump that island now requires JVM 25 bytecode, so the JDK 21 publish
would fail trying to compile `grails-micronaut` / `grails-micronaut-bom`.
Mirror the matrix-job split into the publish side:
- Existing `publish` job (Java 21): pass `-PskipMicronautProjects` so
it publishes everything EXCEPT the Micronaut island. Same task list
(`publish aggregateChecksums aggregatePublishedArtifacts`), same
retry harness, same secrets.
- New `publishMicronaut` job (Java 25): publishes the two island
artifacts via the explicit task list
`:grails-micronaut:publish :grails-micronaut-bom:publish`. The three
test-example projects in the island are not published. Same retry
harness and secrets as the sibling job. Same `needs:` / `if:` gates
so both jobs fire from the same successful upstream matrix runs.
Going with the explicit task-list approach instead of adding a
complementary `-PonlyMicronautProjects` flag to `settings.gradle` -
the island only publishes two artifacts and the symmetric flag would
require inverting the gating logic in `settings.gradle:88`, which is
more moving parts than the situation warrants.
Verified locally:
```
# JDK 25 - publishes the Micronaut island
JAVA_HOME=corretto-25 ./gradlew :grails-micronaut:publishToMavenLocal \
:grails-micronaut-bom:publishToMavenLocal --no-build-cache --rerun-tasks
# BUILD SUCCESSFUL
# Artifacts confirmed:
# ~/.m2/.../grails-micronaut/8.0.0-SNAPSHOT/grails-micronaut-8.0.0-SNAPSHOT.pom
# ~/.m2/.../grails-micronaut-bom/8.0.0-SNAPSHOT/grails-micronaut-bom-8.0.0-SNAPSHOT.pom
# JDK 21 + -PskipMicronautProjects - the parallel non-Micronaut publish path
JAVA_HOME=corretto-21 ./gradlew :grails-core:publishToMavenLocal \
-PskipMicronautProjects --no-build-cache --rerun-tasks
# BUILD SUCCESSFUL
```
Also verified that the JDK-25 Micronaut island runs full tests (not
just compile) cleanly: `./gradlew :grails-micronaut:test
:grails-test-examples-micronaut:test
:grails-test-examples-micronaut-groovy-only:test
:grails-test-examples-plugins-micronaut-singleton:test` -> BUILD
SUCCESSFUL.
Assisted-by: claude-code:claude-opus-4-7
The Micronaut 5 platform GA targets JVM 25 bytecode, so the `grails-micronaut` and `grails-micronaut-bom` artifacts cannot be assembled or staged on the existing JDK 21.0.7 reproducibility pin. Apply the same JDK-split pattern already in place for the CI matrix (see `.github/workflows/gradle.yml`) to the Apache release flow: - New `JAVA_VERSION_MICRONAUT=25.0.3` env var alongside the existing `JAVA_VERSION=21.0.7`. This is the SECOND reproducibility pin for this repository - any verifier wanting to reproduce the Micronaut artifacts must use this exact JDK (Liberica, version `25.0.3+11`). - `release.yml`'s `publish` job now runs the existing pre-publish smoke checks and the three sibling publishToSonatype blocks (Gradle plugins, Grails Core, Grails Forge) on JDK 21 with `-PskipMicronautProjects`. The `assemble`, `grails-doc:build`, and forge composite builds all need the flag - the Forge composite includes `..` so it transitively pulls the Micronaut island. - A new `Publish Grails-Micronaut to Staging Repository` step switches to JDK 25 via `setup-java@v4` and stages the two island artifacts via the explicit task list `:grails-micronaut:publishToSonatype :grails-micronaut-bom:publishToSonatype`. It uses `findSonatypeStagingRepository` to land in the same staging repository that the JDK 21 blocks already populated (matched by `NEXUS_PUBLISH_DESCRIPTION`). - A trailing `setup-java@v4` step restores JDK 21 before the `closeSonatypeStagingRepository` and checksum/artifact-list combination steps. Symmetric, keeps any future steps that touch the repository's own Gradle config on the documented JDK. - `release-publish-docs.yml` and the `docs` job in `release.yml` both build `grails-doc` from the root project; they now pass `-PskipMicronautProjects` to keep Gradle from resolving the island's JVM 25 variants on the JDK 21 runner. The SDKMAN release steps (`sdkMinorRelease` / `sdkMajorRelease`, run from the Forge composite) also get the flag - they do not compile anything, but the include-build dependency on the Micronaut island makes the flag defensive. `.sdkmanrc` is documented as the primary JDK source; a comment block now explicitly tells local committers that the Micronaut island requires a separate `JAVA_VERSION_MICRONAUT` JDK installed via `sdk install java <version>-librca`, and points to the relevant RELEASE.md verification section (to be written in a follow-up commit on this PR). Downstream consumer impact (documented in the PR description): the published `grails-micronaut:8.0.0` artifact will carry `org.gradle.jvm.version=25` in its Gradle module metadata, so Grails 8 apps running on JDK 21 cannot depend on it. JDK-25 consumers can use the Micronaut integration; JDK-21 consumers use the rest of Grails 8. Phase 1 of 3 for the dual-JDK release flow. Follow-up commits update `etc/bin/Dockerfile`, the verify scripts, and `RELEASE.md` so verifiers can actually reproduce the JDK 25 artifacts. Assisted-by: claude-code:claude-opus-4-7
Verifiers reproduce release artifacts by running etc/bin/verify-reproducible.sh
inside the etc/bin/Dockerfile container. With Micronaut 5 now staged from
JDK 25, the verifier needs the matching Liberica JDK on disk and the
verify script needs to switch into it for the island only.
`etc/bin/Dockerfile`:
- Adds a second Liberica JDK install, version pinned via `JDK_25_VERSION`
and exposed via `JDK_25_HOME=/opt/liberica-jdk25`. Keep
`JDK_25_VERSION` synced with `JAVA_VERSION_MICRONAUT` in
`.github/workflows/release.yml`. Liberica's amd64 + arm64 tarballs are
downloaded from `download.bell-sw.com` and verified against the
SHA-512 checksums baked into the Dockerfile (multi-arch via
`dpkg --print-architecture`). The primary JDK 21.0.7 stays the
default - everything in `PATH`, `JAVA_HOME` is unchanged. The
secondary JDK is opt-in via `JDK_25_HOME`.
`etc/bin/verify-reproducible.sh`:
- The single-pass build (`grails-gradle → root → grails-forge`) splits
into two passes:
1. Default JDK 21: builds `grails-gradle` composite as-is, then
`./gradlew publishToMavenLocal -PskipMicronautProjects` in root,
then `grails-forge` composite (also with the skip flag because
Forge does `includeBuild('..')` and would otherwise pull the
Micronaut island through the transitive evaluation).
2. JDK 25 via `JDK_25_HOME` override: builds the two Micronaut
island artifacts only -
`:grails-micronaut:publishToMavenLocal :grails-micronaut-bom:publishToMavenLocal`.
- Script fails fast with a clear error if `JDK_25_HOME` is not set
(the container exports it; manual verifiers outside the container
must install Liberica JDK matching `$JAVA_VERSION_MICRONAUT` from
`release.yml` and export the env var).
`etc/bin/test-reproducible-builds.sh`:
- Same dual-pass structure, extracted into a `build_all()` helper so
both reproducibility passes (`first` and `second`) execute the same
sequence. The Micronaut island gets the same dual-build treatment
as the rest of the artifacts so any JDK-25-specific reproducibility
hazards (timestamp ordering in class files, constant pool ordering,
stack map frame layout) surface locally before they reach a
release vote.
Phase 2 of 3. Phase 3 updates RELEASE.md to teach maintainers and
ASF voters the dual-JDK requirement.
Assisted-by: claude-code:claude-opus-4-7
Three sections of RELEASE.md teach maintainers and ASF voters the new dual-JDK requirement that this PR introduces: 1. Section 2's "Manual Verification: Reproducible Jar Files" gets a new "Dual-JDK requirement for the Grails-Micronaut island" sub-section. Explains that Grails 8 release artifacts now come from two reproducibility pins ($JAVA_VERSION for everything except the Micronaut island, $JAVA_VERSION_MICRONAUT for grails-micronaut + grails-micronaut-bom) and tells outside-the- container verifiers how to install the secondary JDK and export $JDK_25_HOME before running `verify-reproducible.sh`. 2. The "Appendix: Verification from a Container" section gains a paragraph noting that the container now ships both JDKs and that `verify-reproducible.sh` switches between them automatically - no manual JDK juggling inside the container. 3. The "Step 1: Ensuring we are reproducible" appendix gets a note above the existing reproducibility gotchas list explaining the dual-JDK split, where both pins live, and the cross-file sync requirement: bumping either pin requires bumping the matching one in etc/bin/Dockerfile so the verification container can reproduce the new artifacts. Phase 3 of 3 - completes the dual-JDK release-flow work in this PR. Assisted-by: claude-code:claude-opus-4-7
Micronaut-leak audit (post-
|
build.gradle |
Project | In the island gating? |
|---|---|---|
grails-bom/micronaut/build.gradle |
:grails-micronaut-bom |
✅ |
grails-micronaut/build.gradle |
:grails-micronaut |
✅ |
grails-test-examples/micronaut/build.gradle |
:grails-test-examples-micronaut |
✅ |
grails-test-examples/plugins/issue-11767/build.gradle |
:grails-test-examples-plugins-issue-11767 |
✅ |
grails-test-examples/plugins/micronaut-singleton/build.gradle |
:grails-test-examples-plugins-micronaut-singleton |
✅ |
Plus the two transitive consumers that depend on :grails-micronaut without naming io.micronaut directly:
:grails-test-examples-issue-11767(grails-test-examples/issue-11767/):grails-test-examples-micronaut-groovy-only(grails-test-examples/micronaut-groovy-only/)
All seven live inside the if (!skipMicronautProjects) { ... } block at settings.gradle:511-520.
Heads up: island is 7 projects, not 5
I'd been referring to "5 island projects" in earlier commits and the PR description. The correct count from settings.gradle is 7 build-graph projects in the island (the two missing in my count were :grails-test-examples-issue-11767 and :grails-test-examples-plugins-issue-11767). The two issue-11767 projects exist to repro apache/grails-core#11767 and depend on :grails-micronaut + :grails-micronaut-bom, so they correctly belong in the island gating.
The PUBLISHED subset is still just 2 (grails-micronaut plugin + grails-micronaut-bom), which is what publishMicronaut in gradle.yml and the new JDK 25 publish step in release.yml stage. The three test-examples + two issue-11767 projects build inside the island but aren't published.
grails-data-graphql was the only real leak; it's fixed
grails-data-graphql/plugin was the only non-island main-build project with a direct io.micronaut.* dependency, via the rxjava2 HTTP client compileOnly in GraphQLSpec.groovy. Removed in 228f9a52ce (replaced with Spring RestClient + Groovy JsonSlurper).
grails-forge/ is intentionally separate
The 50+ io.micronaut.* references in grails-forge/*/build.gradle are all in the separate composite build which is itself a Micronaut 4.10.10 app (grails-forge/gradle.properties:27). Out of scope - the Forge stays on Micronaut 4.x regardless of what the main grails-core multi-project does with Micronaut 5.
Net
Nothing in grails-core outside the explicitly-gated 7-project Micronaut island pulls Micronaut 5 / JDK 25 onto the JDK 21 classpath. The Forge composite is its own Micronaut 4.x universe. Audit clean.
|
Is this supposed to still be draft? |
There was a problem hiding this comment.
Pull request overview
This PR bumps the Micronaut platform to 5.0.0 GA and adapts the build, CI, release, and GraphQL test infrastructure for Micronaut’s JDK 25 requirement while keeping the rest of Grails on the JDK 21 baseline.
Changes:
- Updates Micronaut/Groovy dependency versions and removes obsolete RxJava2/Serde test dependencies.
- Splits CI/release/reproducibility flows so non-Micronaut projects run on JDK 21 and the Grails-Micronaut island runs on JDK 25.
- Replaces GraphQL integration-test HTTP usage from Micronaut client APIs to Spring
RestClient.
Reviewed changes
Copilot reviewed 34 out of 37 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
RELEASE.md |
Documents the dual-JDK reproducibility and verification process. |
.sdkmanrc |
Documents the primary JDK pin and secondary JDK requirement. |
gradle.properties |
Bumps micronautPlatformVersion and removes unused Micronaut pins. |
dependencies.gradle |
Aligns the Micronaut BOM Groovy override with Micronaut 5 GA. |
grails-bom/micronaut/build.gradle |
Updates Jackson exclusion rationale. |
grails-data-graphql/plugin/build.gradle |
Replaces Micronaut client compile dependency with Spring Web. |
grails-data-graphql/plugin/src/main/groovy/org/grails/gorm/graphql/plugin/testing/GraphQLSpec.groovy |
Rewrites GraphQL test helper to use RestClient and Groovy JSON parsing. |
grails-test-examples/graphql/grails-test-app/build.gradle |
Removes Micronaut HTTP client and Serde dependencies. |
grails-test-examples/graphql/grails-test-app/src/integration-test/groovy/grails/test/app/*.groovy |
Updates GraphQL response body access for ResponseEntity. |
grails-test-examples/graphql/grails-tenant-app/build.gradle |
Removes Micronaut test HTTP dependencies. |
grails-test-examples/graphql/grails-tenant-app/src/integration-test/groovy/grails/tenant/app/UserIntegrationSpec.groovy |
Updates GraphQL response body access. |
grails-test-examples/graphql/grails-multi-datastore-app/build.gradle |
Removes Micronaut test HTTP dependencies. |
grails-test-examples/graphql/grails-multi-datastore-app/src/integration-test/groovy/myapp/BarIntegrationSpec.groovy |
Updates GraphQL response body access. |
grails-test-examples/graphql/grails-multi-datastore-app/src/integration-test/groovy/myapp/FooIntegrationSpec.groovy |
Updates GraphQL response body access. |
grails-test-examples/graphql/grails-docs-app/build.gradle |
Removes unused Micronaut test HTTP dependencies. |
etc/bin/Dockerfile |
Adds pinned secondary Liberica JDK 25 for reproducible Micronaut builds. |
etc/bin/verify-reproducible.sh |
Splits reproducibility verification into JDK 21 and JDK 25 passes. |
etc/bin/test-reproducible-builds.sh |
Splits local reproducibility testing into JDK 21 and JDK 25 passes. |
.github/workflows/gradle.yml |
Skips Micronaut projects on JDK 21 jobs and adds JDK 25 Micronaut snapshot publishing. |
.github/workflows/release.yml |
Splits release publishing between JDK 21 and JDK 25. |
.github/workflows/release-publish-docs.yml |
Skips Micronaut projects for JDK 21 docs publishing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
The PR diff shows that the .github/workflows/gradle.yml |
- release.yml: append the Micronaut island (grails-micronaut, grails-micronaut-bom) checksums and published-artifact entries to the combined CHECKSUMS.txt / PUBLISHED_ARTIFACTS.txt. The grails-core aggregation runs with -PskipMicronautProjects on JDK 21 and therefore omits the island. The island's per-project files are produced by publishedChecksums / savePublishedArtifacts as finalizers of the JDK 25 publishToSonatype step, so they are appended here rather than re-running aggregateChecksums on JDK 25 - which would re-fingerprint the JDK 21 artifacts against a JDK 25 compiler and break reproducibility. - etc/bin/verify-reproducible.sh, etc/bin/test-reproducible-builds.sh: add --no-daemon to all gradle invocations. - grails-data-graphql: document that the GraphQLSpec testing trait serializes and parses JSON with Groovy JsonOutput / JsonSlurper instead of the application's configured object mapper, so trait assertions may differ from production response rendering. Assisted-by: claude-code:claude-4.8-opus
Forge behavior: the
|
Add GrailsMicronautSpec asserting that the grails-micronaut Forge feature: - renders the org.apache.grails:grails-micronaut dependency when JDK 25 is selected, and - rejects generation with the expected IllegalArgumentException when a sub-25 JDK (JDK 21) is selected. This closes the test gap noted during PR #15677 review - the guard in GrailsMicronaut#processSelectedFeatures previously had no dedicated negative test. Assisted-by: claude-code:claude-4.8-opus
|
Added the negative test in cb75043 (
Verified locally (run with |
settings.gradle now decides whether the Grails-Micronaut "island"
(grails-micronaut, grails-micronaut-bom, the micronaut-tied test-examples)
is part of the build graph based on the build JDK:
- sub-25 JDK : island auto-excluded (Micronaut 5 GA targets JVM 25 bytecode
and declares org.gradle.jvm.version=25, which a sub-25 JDK
cannot resolve or compile)
- JDK 25+ : island auto-included
A plain ./gradlew build therefore works on the Grails 8 baseline (JDK 21) and
transparently picks up the island on JDK 25+. Two presence-based overrides
still win over the auto-detection:
-PskipMicronautProjects force-exclude on any JDK (used by
groovy-joint-workflow.yml, where the island's
Groovy 5 pin clashes with the Groovy 4 snapshot
that build swaps in, independent of the JDK)
-PincludeMicronautProjects force-include on a sub-25 JDK (escape hatch; the
island still cannot compile there)
skip wins if both are present.
Because the CI jobs pin a specific JDK via setup-java, the per-job
matrix.java == 21 conditionals and the unconditional JDK-21 skip flags became
redundant and are removed from gradle.yml, release.yml, and
release-publish-docs.yml. The explicit flag is kept where it is NOT merely a
JDK proxy:
- groovy-joint-workflow.yml excludes the island for a Groovy-version reason,
not a JDK reason (issue #15613)
- etc/bin/verify-reproducible.sh and etc/bin/test-reproducible-builds.sh are
standalone scripts whose first pass must exclude the island regardless of
the ambient default JDK; their JDK 25 pass addresses the island tasks
directly and resolves them via the auto-include
Verified on JDK 21 with ./gradlew projects: island absent by default, present
with -PincludeMicronautProjects, absent with both flags.
Assisted-by: claude-code:claude-opus-4-8
…tion The comment described only the manual -PskipMicronautProjects flag. Update it to match the build-JDK auto-detection added in settings.gradle and mention the -PincludeMicronautProjects override. Assisted-by: claude-code:claude-opus-4-8
Local build now keys off the build JDKPushed a change to
Explicit flags still win over the detection:
Because each CI job pins its JDK via Verified on JDK 21 with |
Resolve conflict in .github/workflows/gradle.yml: keep the JDK 25 Micronaut island publish comment while adopting the nick-fields/retry v4.0.0 pin from 8.0.x. Also align the new publishMicronaut job's actions with the SHA-pinned versions used elsewhere in the workflow (checkout v6.0.2, setup-java v5.2.0, setup-gradle v6.1.0 with cache-provider: basic, setup-testlens v1.9.2, retry v4.0.0) per the ASF action-pinning policy. Assisted-by: claude-code:claude-4.8-opus
🔎 No tests executed 🔎🏷️ Commit: 40d0bc6 Learn more about TestLens at testlens.app. |
Draft - stacked on
deps/spring-boot-4.0.6(#15676) so the Spring Boot 4.0.6 dependency fallout does not muddy this one.Bumps
micronautPlatformVersionfrom5.0.0-M2to5.0.0(GA).Release notes: https://github.com/micronaut-projects/micronaut-platform/releases/tag/v5.0.0
The core problem
Micronaut 5.0.0 GA publishes JARs targeting JVM 25 bytecode and declares
org.gradle.jvm.version=25. Grails 8 keeps its baseline at JDK 21. A sub-25 JDK cannot resolve or compile the Micronaut platform, so the Grails-Micronaut "island" -grails-micronaut,grails-micronaut-bom, and the micronaut-tiedgrails-test-examples-*- cannot be part of a JDK 21 build.What this PR does
1. Platform bump
gradle.properties:micronautPlatformVersion5.0.0-M2->5.0.0.dependencies.gradle: bump thegrails-micronaut-bomGroovy override to5.0.6to match Micronaut 5 GA's managedgroovy.version. Spock stays at2.4-groovy-5.0.grails-bom/micronaut/build.gradle: thetools.jacksonexclude stays sospring-boot-dependenciesremains the single source of truth for Jackson 3 (Micronaut 5 GA ships jackson-bom 3.1.3, Spring Boot 4.0.6 ships 3.1.2).2. The island is toggled automatically by the build JDK
settings.gradlenow decides island membership from the JDK running the build:./gradlew buildworks on the Grails 8 baseline (JDK 21) with no flags.Two presence-based overrides always win over the auto-detection:
-PskipMicronautProjects- force-exclude on any JDK.-PincludeMicronautProjects- force-include on a sub-25 JDK (escape hatch; the island still cannot compile there).-PskipMicronautProjectswins if both are passed.3. CI (
gradle.yml)setup-java- the oldmatrix.java == 21 && -PskipMicronautProjectsconditionals are gone.publishjob (JDK 21) publishes everything except the island; apublishMicronautjob (JDK 25) publishesgrails-micronaut+grails-micronaut-bom.4. Apache release flow (
release.yml) + reproducibilityASF releases must be byte-for-byte reproducible against a pinned JDK. The flow keeps
JAVA_VERSION=21.0.7for everything outside the island and adds a second pinJAVA_VERSION_MICRONAUT=25.0.3for the island:etc/bin/Dockerfile: the verification container installs a second Liberica JDK 25 (pinned version + multi-arch SHA-512) exposed as$JDK_25_HOME; JDK 21 stays the default.etc/bin/verify-reproducible.sh+etc/bin/test-reproducible-builds.sh: each runs a JDK 21 pass for everything outside the island, then aJAVA_HOME=$JDK_25_HOMEpass for the two island artifacts. Both fail fast when$JDK_25_HOMEis unset.RELEASE.mddocuments the dual-JDK requirement.The explicit
-PskipMicronautProjectsflag is retained only where it is not a JDK proxy:groovy-joint-workflow.yml- the island's Groovy 5 / Spock 2.4-groovy-5.0 pin clashes with the Groovy 4.x snapshot that build swaps in, a reason independent of the JDK (CI - Groovy Joint Validation Build is broken: spock-core:2.4-groovy-5.0 incompatible with Groovy 4.x snapshot #15613).PATH.5. Micronaut HTTP client removed from
grails-data-graphqltestsGraphQLSpecpreviously pulledmicronaut-rxjava2-http-client+micronaut-serde-jacksonjust to call the running app from integration tests. Micronaut 5 drops RxJava 2 from the BOM, so it now uses Spring Boot 4'sRestClientwith GroovyJsonOutput/JsonSlurper(no Jackson or Gson on the test classpath).gradle.propertiesloses the now-unusedmicronautRxjava2VersionandmicronautSerdeJacksonVersionpins. Nothing ingrails-corenow depends on Micronaut artifacts outside the island.Consumer impact
The published
grails-micronaut:8.0.0artifact carriesorg.gradle.jvm.version=25. Grails 8 apps on JDK 21 will have Gradle variant resolution reject it - it is consumable only on JDK 25+. JDK 21 users get the rest of Grails 8 without the Micronaut integration. The release ships both audiences; choosing the right artifact set is on the consumer's build config.Key versions in Micronaut 5.0.0 GA
micronaut.core.version5.0.0micronaut.data.version5.0.1micronaut.serde.version3.0.0jackson.version3.1.3groovy.version5.0.6spring.boot.version4.0.6spring.version7.0.7Platform-level breaking changes in v5.0.0 that are landmines for downstream Grails-on-Micronaut apps (not consumed by
grails-coreitself): RxJava 2 and MicroStream removed from the BOM,jaxrs.api.version3 -> 4,kafka.version3.9 -> 4.2.grails-forgestays onmicronautVersion=4.10.10(the Forge is itself a Micronaut 4.x app) - out of scope for this platform bump.Verification
Project-graph toggle verified on JDK 21 via
./gradlew projects: island absent by default, present with-PincludeMicronautProjects, absent with both override flags (skip wins).