GoogleCloudPlatform / buildpacks

Builders and buildpacks designed to run on Google Cloud's container platforms
Apache License 2.0
991 stars 147 forks source link

Java buildpack doesn't respect Java Runtime version set in conf files #254

Open feliperyan opened 1 year ago

feliperyan commented 1 year ago

The Java buildpack should look for runtime specification in pom.xml or gradle... (sorry not a java person) as the other buildpacks do. It only respects GOOGLE_RUNTIME_VERSION.

For example, the Node buildpack looks for a node version in packages.json or if GOOGLE_NODEJS_VERSION is set, it gives that preference.

jama22 commented 1 year ago

Hi @feliperyan , raising this issue. It does look like Java buildpacks respects Gradle and Maven configurations

https://github.com/GoogleCloudPlatform/buildpack-samples/blob/049092c48626cc1f6cd1885e00ad84de881ad934/sample-java-gradle/build.gradle#L12

https://github.com/GoogleCloudPlatform/buildpack-samples/blob/049092c48626cc1f6cd1885e00ad84de881ad934/sample-java-mvn/system.properties#L1

I think this is something I can update on our docs though, because to your point, we only show how you can pin via the GOOGLE_RUNTIME_VERSION environment variable

jama22 commented 1 year ago

Docs have been updated to clarify Java languge pin behavior https://cloud.google.com/docs/buildpacks/java#specify_a_java_version

Hope that helps @feliperyan

feliperyan commented 1 year ago

Hey @jama22 thanks for this, I stumbled on this issue when trying to follow https://cloud.google.com/run/docs/quickstarts/build-and-deploy/deploy-java-service which fails as the runtime in the buildpack defaults to 11 and seems not to pick up on the fact that the build.gradle defines sourceCompatibility = '17' here's the whole build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.0.0'
    id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}
jama22 commented 1 year ago

reopening, I'll take a look when more folks are back online

jama22 commented 1 year ago

@feliperyan Not a Java expert, but going by sourceCompatibility = '17' do you have to wrap the sourceCompatability line in java like so:

java { sourceCompatibility = '17' }

Update I misinterperted your note, that is literally the gradle.build that's been generated from spring starter so it should work as is

jama22 commented 1 year ago

Did some digging. Mea culpa I was misled by our own examples and how (I assumed) the Java buildpacks work. I've requested a rollback the documentation changes I made yesterday, since I now understand them to be incorrect. To help clarify the situation, there are 3 separate issues at hand here:

Java buildpack keeps defaulting to JDK 11

Although we recently released support for the JDK 17 in our OSS buildpacks, most projects will default to JDK 11. The root cause of that can be found here: https://github.com/GoogleCloudPlatform/buildpacks/blob/1588a5e7eb2b474daf03f259d021dc168ed7544d/cmd/java/runtime/main.go#L33

Without GOOGLE_RUNTIME_VERSION set, the Java buildpack will always default to 11

The concrete action here would be to bump the default to always use the latest JDK available. However, this could be a breaking change since some folks might have come to depend on the fact that JDK 11 is always being used. I think a good opportunity to make this change is in conjunction with the fix to #232 , where we plan on rolling out a builder:v2 which will have the new Ubuntu 22 base image.

java buildpacks don't actually respect the gradle and mvn files

Going through our buildpack samples under https://github.com/GoogleCloudPlatform/buildpack-samples/tree/master/sample-java-gradle and https://github.com/GoogleCloudPlatform/buildpack-samples/tree/master/sample-java-mvn , i was pretty confident that our buildpacks were picking up version details from the build systems themselvses. This is not the case.

The issue remains that we should provide language idiomatic ways for detecting the preferred JDK version. I'm going to leave this Github issue open to capture that request.

Looking at Heroku and Paketo, something tells me there's more to it than just inspecting the files to infer the JDK version. Both buildpacks rely on a buildpack-specific configuration or environment variable.

Documentation should include additional instructions on how to pin

Right now, the only reliable way to force a JDK version with the Java buildpacks is by using the GOOGLE_RUNTIME_VERSION environment variable. That said, there are many (frustrating) ways to set that environment variable, especially if you're trying to manipulate the environment variables using the gcloud CLI. A more declarative approach is to embed the environment variable declaration alongside your source code in a project.toml file as so:

[[build.env]]
name = "GOOGLE_RUNTIME_VERSION"
value = "17"

This has a few benefits:

I'll take on documenting that functionality after the rollback of the docs complete . Tracking bug is #255