Skip to content

Upgrade Gradle Build Compatibility for Gradle 9 and JDK 25 - #40810

Open
alisha-1000 wants to merge 1 commit into
apache:masterfrom
alisha-1000:pr/gradle9-jdk25-compatibility
Open

alisha-1000 wants to merge 1 commit into
apache:masterfrom
alisha-1000:pr/gradle9-jdk25-compatibility

Conversation

@alisha-1000

Copy link
Copy Markdown
Contributor

Summary

This PR updates Apache Beam's Gradle build configuration to improve compatibility with Gradle 9 and JDK 25.

Changes

  • Upgrade relevant Gradle build plugins and Java tooling dependencies.
  • Update Gradle APIs and property access patterns for compatibility with newer Gradle versions.
  • Adjust Java compilation configuration for JDK 25.
  • Update affected build scripts across Beam modules, runners, and playground components.
  • Remove stale project includes that prevent Gradle project configuration from completing successfully.

Validation

  • Gradle 9.8.2 project configuration (help) succeeded on JDK 25.
  • Java core compilation and tests were validated under JDK 17.
  • Selected Java modules compiled successfully under JDK 25.
  • Transform-service launcher tests passed under JDK 25.

Known limitation

On Apple Silicon, the protoc-gen-grpc-java 1.69.0 artifact downloaded for the osx-aarch_64 classifier was identified as an x86_64 executable, preventing a fresh local protobuf generation run without a workaround. This remains to be investigated independently.

Further CI validation is needed across the affected modules.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 Review Summary

This PR modernizes Gradle build scripts across the repository by migrating deprecated task APIs (project.exec, archivePath, archivesBaseName, mainClassName, fileMode, etc.) and upgrading several build plugins and tools (Checker Framework, Error Prone, SpotBugs, Protobuf, Google Java Format, and Kotlin).

🔍 General Feedback

  • When converting ad-hoc doLast { exec { ... } } tasks to typed Exec tasks (with tasks.register<Exec>), closures passed to register run at task configuration time rather than task execution time. Several migrated tasks in learning/tour-of-beam and playground have broken task dependencies or premature property evaluations as a result.
  • In BeamModulePlugin.groovy, the new com.google.protobuf:protobuf-gradle-plugin:0.9.6 changes the default directory layout for generated protobuf/gRPC Java sources compared to 0.8.13, which should be verified against the hardcoded generatedProto* paths.

💡 Tip: Comment /gemini review on this pull request to trigger a new Gemini code review.

tasks.register("generateCode") {
dependsOn(":playground:frontend:playground_components:generateCode")

tasks.register<org.gradle.api.tasks.Exec>("generateCode") {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High: dependsOn(":playground:frontend:playground_components:generateCode") was removed from generateCode, and no ordering constraint (mustRunAfter) exists between cleanFlutter and pubGet. Without the dependency on playground_components:generateCode and ordering pubGet after cleanFlutter, running generateCode can fail due to missing generated component files or race between cleaning and fetching packages.

""
}

val projectId = project.rootProject.extra["playground_gke_project"]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Critical: Because applyMigrations is now a typed Exec task, its configuration block executes during the configuration phase—before setPlaygroundGkeProject (or takeConfig) has executed its doLast action to populate project.rootProject.extra["playground_gke_project"]. Accessing project.rootProject.extra["playground_gke_project"] here will throw an UnknownExtraPropertyException whenever applyMigrations is configured (e.g., when running gkebackend). Additionally, applyMigrations does not declare dependsOn("setPlaygroundGkeProject"). Consider keeping this as a doLast block using providers.exec or using an CommandLineArgumentProvider coupled with dependsOn("setPlaygroundGkeProject").

"run",
"cmd/remove_unused_snippets/remove_unused_snippets.go",
"cleanup",
"-day_diff", System.getProperty("dayDiff"),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High: Moving args(...) with System.getProperty(...) out of doLast into the Exec task configuration block causes System.getProperty(...) to be evaluated when the task is configured rather than only when removeUnusedSnippet (and similarly removeSnippet below on line 73) is executed. If any task in the project realizes all tasks (or during IDE sync) without -DdayDiff, -DprojectId, and -Dnamespace set, args(...) will receive null values or fail. Use argumentProviders.add(CommandLineArgumentProvider { ... }) or providers.exec inside doLast.

val base = file(directory)
if (base.exists()) {
fileTree(base).files.filter {
regex.matches(it.relativeTo(base).invariantSeparatorsPath)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium: Previously, find assets lib test -regex ... matched against paths prefixed with the directory name (e.g. lib/foo.g.dart). Using it.relativeTo(base) strips the directory prefix (producing foo.g.dart), and println(it) now prints absolute File paths instead of relative paths. While the current patterns start with .*, using it.relativeTo(projectDir).invariantSeparatorsPath would preserve the original regex matching semantics and output format.

Suggested change
regex.matches(it.relativeTo(base).invariantSeparatorsPath)
regex.matches(it.relativeTo(projectDir).invariantSeparatorsPath)

)
standardOutput = FileOutputStream("playground/frontend/playground_components/assets/symbols/go.g.yaml")
}
layout.projectDirectory.file("assets/symbols/go.g.yaml")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High: Previously, FileOutputStream("playground/frontend/playground_components/assets/symbols/go.g.yaml") resolved relative to the root project working directory because exec resolved stream paths from the Gradle daemon's CWD, whereas layout.projectDirectory.file("assets/symbols/go.g.yaml") resolves properly inside playground_components. However, neither extractBeamSymbolsGo nor extractBeamSymbolsPython declares dependsOn("ensureSymbolsDirectoryExists") (only extractBeamSymbols depends on all of them in parallel without ordering), so writeBytes will throw FileNotFoundException if assets/symbols does not yet exist when extractBeamSymbolsGo or extractBeamSymbolsPython finishes before ensureSymbolsDirectoryExists.

@codecov

codecov Bot commented Oct 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.90%. Comparing base (a8d6afd) to head (733a1a0).
⚠️ Report is 76 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #40810      +/-   ##
==========================================
- Coverage   80.04%   79.90%   -0.15%     
==========================================
  Files         490      493       +3     
  Lines       82916    83473     +557     
==========================================
+ Hits        66373    66697     +324     
- Misses      16543    16776     +233     
Flag Coverage Δ
python 79.90% <ø> (-0.15%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

Copy link
Copy Markdown
Contributor

Checks are failing. Will not request review until checks are succeeding. If you'd like to override that behavior, comment assign set of reviewers

@CH-Abhinav

Copy link
Copy Markdown
Contributor

/gemini review

@CH-Abhinav

Copy link
Copy Markdown
Contributor

man is gemini stuck or something?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants