You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@grails.apache.org by "jamesfredley (via GitHub)" <gi...@apache.org> on 2026/04/16 17:24:17 UTC
[PR] Fix forge dockerBuildNative builder stage to use Java 21 GraalVM image [grails-core]
jamesfredley opened a new pull request, #15580:
URL: https://github.com/apache/grails-core/pull/15580
## Summary
- [PR #15579](https://github.com/apache/grails-core/pull/15579) fixed the Forge prev-snapshot GCP deploy runtime stage image, but [the very next workflow run](https://github.com/apache/grails-core/actions/runs/24518601227) on the merge commit still fails `:grails-forge-web-netty:dockerBuildNative` (and the analytics variant) with `UnsupportedClassVersionError: class file version 65.0`.
- Root cause: on Micronaut Gradle Plugin `3.7.10` (our pinned `micronautApplicationPluginVersion`), `baseImage(...)` on `dockerfileNative` only controls the final runtime stage of the generated multi-stage Dockerfile. The builder stage (`FROM ... AS graalvm`), where `native-image` actually compiles our Java 21 bytecode, is controlled by the separate `graalImage` property. Its default clamps `jdkVersion` against `SUPPORTED_JAVA_VERSIONS = [17, 11]` and falls back to `ghcr.io/graalvm/native-image:ol7-java17-22.3.2`.
- Explicitly set `graalImage` on `dockerfileNative` to the same Java 21 image in both `grails-forge-web-netty/build.gradle` and `grails-forge-analytics-postgres/build.gradle`. Both stages of the generated Dockerfile now run on Java 21.
## Failure excerpt
```
Step 1/13 : FROM ghcr.io/graalvm/native-image:ol7-java17-22.3.2 AS graalvm
...
Fatal error: java.lang.UnsupportedClassVersionError: org/grails/forge/netty/Application
has been compiled by a more recent version of the Java Runtime (class file version 65.0),
this version of the Java Runtime only recognizes class file versions up to 61.0
Error: Image build request failed with exit status 1
> Task :grails-forge-web-netty:dockerBuildNative FAILED
```
Full log: https://github.com/apache/grails-core/actions/runs/24518601227/job/71673053922
## Why the previous fix was insufficient
Reading [`NativeImageDockerfile.java` at tag `v3.7.10`](https://github.com/micronaut-projects/micronaut-gradle-plugin/blob/v3.7.10/docker-plugin/src/main/java/io/micronaut/gradle/docker/NativeImageDockerfile.java):
- Builder stage is emitted via `from(new From(getGraalImage().get()).withStage("graalvm"))`.
- `graalImage` convention: `getGraalVersion().zip(getJdkVersion(), NativeImageDockerfile::toGraalVMBaseImageName)` -> `ghcr.io/graalvm/native-image:ol7-${jdkVersion}-${graalVersion}`.
- `jdkVersion` auto-derives from the toolchain but passes through `toSupportedJavaVersion`, which is backed by `SUPPORTED_JAVA_VERSIONS = Arrays.asList(17, 11)`. Java 21 therefore silently becomes `java17`.
- `baseImage(...)` only calls `getBaseImage().set(imageName)`, and `BaseImageForBuildStrategyResolver.resolve()` returns that value for the final `from(baseImageProvider)` (runtime stage) only.
So the PR #15579 override reaches only the runtime `FROM`. The builder `FROM ... AS graalvm` was still `ghcr.io/graalvm/native-image:ol7-java17-22.3.2`, which rejects class file 65.0.
## Verification
- Cannot exercise `dockerBuildNative` locally in this environment (no Docker), but the change is a pure DSL override that takes precedence over the plugin's Java-17-only convention. The image tag matches the one already chosen for the runtime stage in #15579.
- No application code changes; only the GraalVM **builder** container reference is added, next to the existing runtime container reference.
## Longer-term follow-up
`micronautApplicationPluginVersion=3.7.10` (March 2023) is the root reason we need this manual override: plugin 4.x adds first-class Java 21 and `native-image-community` support, so `graalImage` would be derived correctly without a hard-coded string. Bumping the plugin would be a broader change though (DSL surface shifts across 3.x -> 4.x), so this PR is intentionally minimal - just unblocking the current CI workflow.
## Notes for reviewers
- Targeting `8.0.x` because that's where the deploy workflow was bumped to Java 21 in [`d1362be7`](https://github.com/apache/grails-core/commit/d1362be708) ("Minimum requirement for Java 21 & update to asset-pipeline to fix NPE"). `7.1.x` still runs `java-version: '17'` in the same workflow (last run [#24475218726](https://github.com/apache/grails-core/actions/runs/24475218726) succeeded), so it is not affected.
- The `fix/` branch prefix should auto-label this PR as `bug` per `.github/release-drafter.yml`.
--
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: notifications-unsubscribe@grails.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix forge dockerBuildNative builder stage to use Java 21 GraalVM image [grails-core]
Posted by "jamesfredley (via GitHub)" <gi...@apache.org>.
jamesfredley commented on code in PR #15580:
URL: https://github.com/apache/grails-core/pull/15580#discussion_r3095145842
##########
grails-forge/grails-forge-web-netty/build.gradle:
##########
@@ -64,6 +64,15 @@ tasks.named('dockerfileNative') {
// dockerBuildNative to fail with `UnsupportedClassVersionError` (class file version 65.0).
// Pin to a specific patch + OS so dockerBuildNative is reproducible (21.0.2 is the final
// GraalVM Community release for JDK 21; later GraalVM Community releases target JDK 22+).
+ //
+ // NOTE: On Micronaut Gradle Plugin 3.7.10, `baseImage(...)` only controls the final runtime
+ // stage of the generated Dockerfile. The builder stage (`FROM ... AS graalvm`), which is
+ // where `native-image` actually runs against our Java 21 bytecode, is controlled by the
+ // separate `graalImage` property. Its default is derived from `jdkVersion`, which the
+ // plugin silently clamps to Java 17 (see NativeImageDockerfile.SUPPORTED_JAVA_VERSIONS =
+ // [17, 11]). Without the explicit `graalImage` override below the builder would still use
+ // `ghcr.io/graalvm/native-image:ol7-java17-22.3.2` and fail with class file version 65.0.
+ graalImage = 'ghcr.io/graalvm/native-image-community:21.0.2-ol9'
baseImage('ghcr.io/graalvm/native-image-community:21.0.2-ol9')
Review Comment:
Good catch - applied in 0fd3b8bffe. Extracted the tag into a
ativeImageContainer local and reused it for both graalImage and aseImage(...) so the builder and runtime stages can't drift apart on a future bump.
##########
grails-forge/grails-forge-analytics-postgres/build.gradle:
##########
@@ -65,6 +65,15 @@ tasks.named('dockerfileNative') {
// dockerBuildNative to fail with `UnsupportedClassVersionError` (class file version 65.0).
// Pin to a specific patch + OS so dockerBuildNative is reproducible (21.0.2 is the final
// GraalVM Community release for JDK 21; later GraalVM Community releases target JDK 22+).
+ //
+ // NOTE: On Micronaut Gradle Plugin 3.7.10, `baseImage(...)` only controls the final runtime
+ // stage of the generated Dockerfile. The builder stage (`FROM ... AS graalvm`), which is
+ // where `native-image` actually runs against our Java 21 bytecode, is controlled by the
+ // separate `graalImage` property. Its default is derived from `jdkVersion`, which the
+ // plugin silently clamps to Java 17 (see NativeImageDockerfile.SUPPORTED_JAVA_VERSIONS =
+ // [17, 11]). Without the explicit `graalImage` override below the builder would still use
+ // `ghcr.io/graalvm/native-image:ol7-java17-22.3.2` and fail with class file version 65.0.
+ graalImage = 'ghcr.io/graalvm/native-image-community:21.0.2-ol9'
baseImage('ghcr.io/graalvm/native-image-community:21.0.2-ol9')
Review Comment:
Good catch - applied in 0fd3b8bffe. Extracted the tag into a
ativeImageContainer local and reused it for both graalImage and aseImage(...) so the builder and runtime stages can't drift apart on a future bump.
--
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: notifications-unsubscribe@grails.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix forge dockerBuildNative builder stage to use Java 21 GraalVM image [grails-core]
Posted by "Copilot (via GitHub)" <gi...@apache.org>.
Copilot commented on code in PR #15580:
URL: https://github.com/apache/grails-core/pull/15580#discussion_r3095123110
##########
grails-forge/grails-forge-web-netty/build.gradle:
##########
@@ -64,6 +64,15 @@ tasks.named('dockerfileNative') {
// dockerBuildNative to fail with `UnsupportedClassVersionError` (class file version 65.0).
// Pin to a specific patch + OS so dockerBuildNative is reproducible (21.0.2 is the final
// GraalVM Community release for JDK 21; later GraalVM Community releases target JDK 22+).
+ //
+ // NOTE: On Micronaut Gradle Plugin 3.7.10, `baseImage(...)` only controls the final runtime
+ // stage of the generated Dockerfile. The builder stage (`FROM ... AS graalvm`), which is
+ // where `native-image` actually runs against our Java 21 bytecode, is controlled by the
+ // separate `graalImage` property. Its default is derived from `jdkVersion`, which the
+ // plugin silently clamps to Java 17 (see NativeImageDockerfile.SUPPORTED_JAVA_VERSIONS =
+ // [17, 11]). Without the explicit `graalImage` override below the builder would still use
+ // `ghcr.io/graalvm/native-image:ol7-java17-22.3.2` and fail with class file version 65.0.
+ graalImage = 'ghcr.io/graalvm/native-image-community:21.0.2-ol9'
baseImage('ghcr.io/graalvm/native-image-community:21.0.2-ol9')
Review Comment:
The image tag is duplicated across `graalImage` and `baseImage(...)`. To avoid future drift (e.g., updating only one and reintroducing the Java version mismatch), consider assigning the image string once (local variable or extra property) and reusing it for both settings.
```suggestion
def nativeImageContainer = 'ghcr.io/graalvm/native-image-community:21.0.2-ol9'
graalImage = nativeImageContainer
baseImage(nativeImageContainer)
```
##########
grails-forge/grails-forge-analytics-postgres/build.gradle:
##########
@@ -65,6 +65,15 @@ tasks.named('dockerfileNative') {
// dockerBuildNative to fail with `UnsupportedClassVersionError` (class file version 65.0).
// Pin to a specific patch + OS so dockerBuildNative is reproducible (21.0.2 is the final
// GraalVM Community release for JDK 21; later GraalVM Community releases target JDK 22+).
+ //
+ // NOTE: On Micronaut Gradle Plugin 3.7.10, `baseImage(...)` only controls the final runtime
+ // stage of the generated Dockerfile. The builder stage (`FROM ... AS graalvm`), which is
+ // where `native-image` actually runs against our Java 21 bytecode, is controlled by the
+ // separate `graalImage` property. Its default is derived from `jdkVersion`, which the
+ // plugin silently clamps to Java 17 (see NativeImageDockerfile.SUPPORTED_JAVA_VERSIONS =
+ // [17, 11]). Without the explicit `graalImage` override below the builder would still use
+ // `ghcr.io/graalvm/native-image:ol7-java17-22.3.2` and fail with class file version 65.0.
+ graalImage = 'ghcr.io/graalvm/native-image-community:21.0.2-ol9'
baseImage('ghcr.io/graalvm/native-image-community:21.0.2-ol9')
Review Comment:
The image tag is duplicated across `graalImage` and `baseImage(...)`. To reduce the chance of updating only one later (and reintroducing the Java version mismatch), consider assigning the image string once and reusing it for both settings.
```suggestion
def nativeImageContainer = 'ghcr.io/graalvm/native-image-community:21.0.2-ol9'
graalImage = nativeImageContainer
baseImage(nativeImageContainer)
```
--
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: notifications-unsubscribe@grails.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix forge dockerBuildNative builder stage to use Java 21 GraalVM image [grails-core]
Posted by "jamesfredley (via GitHub)" <gi...@apache.org>.
jamesfredley commented on code in PR #15580:
URL: https://github.com/apache/grails-core/pull/15580#discussion_r3095145842
##########
grails-forge/grails-forge-web-netty/build.gradle:
##########
@@ -64,6 +64,15 @@ tasks.named('dockerfileNative') {
// dockerBuildNative to fail with `UnsupportedClassVersionError` (class file version 65.0).
// Pin to a specific patch + OS so dockerBuildNative is reproducible (21.0.2 is the final
// GraalVM Community release for JDK 21; later GraalVM Community releases target JDK 22+).
+ //
+ // NOTE: On Micronaut Gradle Plugin 3.7.10, `baseImage(...)` only controls the final runtime
+ // stage of the generated Dockerfile. The builder stage (`FROM ... AS graalvm`), which is
+ // where `native-image` actually runs against our Java 21 bytecode, is controlled by the
+ // separate `graalImage` property. Its default is derived from `jdkVersion`, which the
+ // plugin silently clamps to Java 17 (see NativeImageDockerfile.SUPPORTED_JAVA_VERSIONS =
+ // [17, 11]). Without the explicit `graalImage` override below the builder would still use
+ // `ghcr.io/graalvm/native-image:ol7-java17-22.3.2` and fail with class file version 65.0.
+ graalImage = 'ghcr.io/graalvm/native-image-community:21.0.2-ol9'
baseImage('ghcr.io/graalvm/native-image-community:21.0.2-ol9')
Review Comment:
Good catch - applied in 0fd3b8bffe. Extracted the tag into a `nativeImageContainer` local and reused it for both `graalImage` and `baseImage(...)` so the builder and runtime stages can't drift apart on a future bump.
##########
grails-forge/grails-forge-analytics-postgres/build.gradle:
##########
@@ -65,6 +65,15 @@ tasks.named('dockerfileNative') {
// dockerBuildNative to fail with `UnsupportedClassVersionError` (class file version 65.0).
// Pin to a specific patch + OS so dockerBuildNative is reproducible (21.0.2 is the final
// GraalVM Community release for JDK 21; later GraalVM Community releases target JDK 22+).
+ //
+ // NOTE: On Micronaut Gradle Plugin 3.7.10, `baseImage(...)` only controls the final runtime
+ // stage of the generated Dockerfile. The builder stage (`FROM ... AS graalvm`), which is
+ // where `native-image` actually runs against our Java 21 bytecode, is controlled by the
+ // separate `graalImage` property. Its default is derived from `jdkVersion`, which the
+ // plugin silently clamps to Java 17 (see NativeImageDockerfile.SUPPORTED_JAVA_VERSIONS =
+ // [17, 11]). Without the explicit `graalImage` override below the builder would still use
+ // `ghcr.io/graalvm/native-image:ol7-java17-22.3.2` and fail with class file version 65.0.
+ graalImage = 'ghcr.io/graalvm/native-image-community:21.0.2-ol9'
baseImage('ghcr.io/graalvm/native-image-community:21.0.2-ol9')
Review Comment:
Good catch - applied in 0fd3b8bffe. Extracted the tag into a `nativeImageContainer` local and reused it for both `graalImage` and `baseImage(...)` so the builder and runtime stages can't drift apart on a future bump.
--
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: notifications-unsubscribe@grails.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix forge dockerBuildNative builder stage to use Java 21 GraalVM image [grails-core]
Posted by "jamesfredley (via GitHub)" <gi...@apache.org>.
jamesfredley merged PR #15580:
URL: https://github.com/apache/grails-core/pull/15580
--
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: notifications-unsubscribe@grails.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org