Skip to content
Draft

WIP #4669

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
1e3a611
Build: allow setting environment variables for the Gradle invocation
snazy Jun 11, 2026
02f6f9c
Add polaris-server-test-runner plugin
snazy Jun 9, 2026
9d4b6f0
Add external Polaris server test manager
snazy Jun 9, 2026
35ea4e0
Migrate Spark integration tests to server runner
snazy Jun 9, 2026
8bcaccc
Move Spark integration tests into Spark projects
snazy Jun 9, 2026
8c11c63
Migrate Ranger integration tests to server runner
snazy Jun 9, 2026
c06592f
Move Ranger integration tests into Ranger extension
snazy Jun 9, 2026
e2c747e
Move Ranger source up
snazy Jun 9, 2026
64a90b2
Migrate OPA integration tests to server runner
snazy Jun 9, 2026
623dad2
Move OPA tests into OPA extension
snazy Jun 9, 2026
6de1733
Migrate runtime-spark-tests to server runner
snazy Jun 9, 2026
80a251b
runtime-service/tests: unify Quarkus test profiles
snazy Jun 12, 2026
626c8b1
polaris-admin/test: Centralize Quarkus test profiles
snazy Jun 12, 2026
1c65fb5
polaris-admin/tests: consolidate to 1 test profile per backend
snazy Jun 12, 2026
7795108
polaris-admin/test: migrate some tests to pure unit tests
snazy Jun 12, 2026
a32b511
polaris-runtime-service/test: slight test-profile improvement
snazy Jun 13, 2026
8d41573
polaris-runtime,admin/testing: Update fork/jvm settings
snazy Jun 12, 2026
2b1f36a
Build: remove another usage of `Project.extra`
snazy Jun 13, 2026
5e563ef
Build: Truely memoize errorprone config
snazy Jun 13, 2026
3c856b4
Build: refactor some more eager resolutions
snazy Jun 13, 2026
c039d7f
Build: better project isolation
snazy Jun 13, 2026
67de53e
runtime-service/int-test: reuse Minio + RustFS containers across tests
snazy Jun 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ gradle/wrapper/gradle-wrapper-*.sha256
/.gradle
/build-logic/.gradle
/build-logic/.kotlin
/gradle/server-test-runner/.gradle
/gradle/server-test-runner/.kotlin
**/build/
!src/**/build/

Expand Down Expand Up @@ -111,6 +113,8 @@ venv
# And then use `./gradlew run -Dquarkus.profile=local` to run Polaris with dev profile.
application-local.properties

/.env

# AI / Agentic Development Tools
.agents/
.aider/
Expand Down
2 changes: 1 addition & 1 deletion api/iceberg-service/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ dependencies {
compileOnly(libs.microprofile.fault.tolerance.api)
}

val rootDir = rootProject.layout.projectDirectory
val rootDir = layout.settingsDirectory
val specsDir = rootDir.dir("spec")
val templatesDir = rootDir.dir("server-templates")
// Use a different directory than 'generated/', because OpenAPI generator's `GenerateTask` adds the
Expand Down
2 changes: 1 addition & 1 deletion api/management-model/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ dependencies {
testImplementation("com.fasterxml.jackson.core:jackson-databind")
}

val rootDir = rootProject.layout.projectDirectory
val rootDir = layout.settingsDirectory
val specsDir = rootDir.dir("spec")
val templatesDir = rootDir.dir("server-templates")
// Use a different directory than 'generated/', because OpenAPI generator's `GenerateTask` adds the
Expand Down
2 changes: 1 addition & 1 deletion api/management-service/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ dependencies {
implementation(libs.slf4j.api)
}

val rootDir = rootProject.layout.projectDirectory
val rootDir = layout.settingsDirectory
val specsDir = rootDir.dir("spec")
val templatesDir = rootDir.dir("server-templates")
// Use a different directory than 'generated/', because OpenAPI generator's `GenerateTask` adds the
Expand Down
2 changes: 1 addition & 1 deletion api/polaris-catalog-service/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ dependencies {
annotationProcessor(project(":polaris-immutables", configuration = "processor"))
}

val rootDir = rootProject.layout.projectDirectory
val rootDir = layout.settingsDirectory
val specsDir = rootDir.dir("spec")
val templatesDir = rootDir.dir("server-templates")
// Use a different directory than 'generated/', because OpenAPI generator's `GenerateTask` adds the
Expand Down
7 changes: 1 addition & 6 deletions bom/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -95,22 +95,17 @@ dependencies {
api(project(":polaris-relational-jdbc"))

api(project(":polaris-extensions-auth-opa"))
api(project(":polaris-extensions-auth-opa-tests"))
api(project(":polaris-extensions-auth-ranger"))
api(project(":polaris-extensions-auth-ranger-tests"))
api(project(":polaris-extensions-federation-bigquery"))
api(project(":polaris-extensions-federation-hadoop"))
api(project(":polaris-extensions-federation-hive"))
api(project(":polaris-hms-testcontainer"))

api(project(":polaris-spark-3.5_2.12"))
api(project(":polaris-spark-integration-3.5_2.12"))
val ideaActive = providers.systemProperty("idea.active").getOrElse("false").toBoolean()
if (!ideaActive) {
api(project(":polaris-spark-3.5_2.13"))
api(project(":polaris-spark-integration-3.5_2.13"))
api(project(":polaris-spark-4.0_2.13"))
api(project(":polaris-spark-integration-4.0_2.13"))
}

api(project(":polaris-admin"))
Expand All @@ -133,7 +128,7 @@ tasks.register<VerifyBomDependenciesTask>("verifyBomDependencies") {
configurations.api.map { it.dependencyConstraints.map { "${it.group}:${it.name}" } }
)
projectCoordinatesByPath.set(
rootProject.allprojects.associate { it.path to "${it.group}:${it.name}" }
provider { rootProject.allprojects.associate { it.path to "${it.group}:${it.name}" } }
)
excludedProjectPaths.set(
setOf(
Expand Down
4 changes: 2 additions & 2 deletions build-logic/src/main/kotlin/GitInfo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ class GitInfo(val gitHead: String, val gitDescribe: String, private val rawLinkR

companion object {
fun memoized(project: Project): GitInfo {
val rootProject = project.rootProject
val isRelease =
rootProject.hasProperty("release") || rootProject.hasProperty("jarWithGitInfo")
project.providers.gradleProperty("release").isPresent ||
project.providers.gradleProperty("jarWithGitInfo").isPresent
val service =
project.gradle.sharedServices.registerIfAbsent(
"gitInfo-$isRelease",
Expand Down
2 changes: 2 additions & 0 deletions build-logic/src/main/kotlin/Utilities.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import org.gradle.api.Project
import org.gradle.process.JavaForkOptions

val noSourceCheckProjects = listOf(":polaris-spark-3.5_2.13")

/**
* Extract the scala version from polaris spark project, and points the build directory to a sub-dir
* that uses scala version as name. The polaris spark project name is in format of
Expand Down
64 changes: 44 additions & 20 deletions build-logic/src/main/kotlin/polaris-java.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,20 @@ checkstyle {
.orElseThrow { GradleException("checkstyle version not found in libs.versions.toml") }
.requiredVersion
toolVersion = checkstyleVersion
configFile = rootProject.file("codestyle/checkstyle.xml")
configFile = layout.settingsDirectory.file("codestyle/checkstyle.xml").asFile
isIgnoreFailures = false
maxErrors = 0
maxWarnings = 0
}

// Ensure Checkstyle runs after jandex to avoid task dependency issues
tasks.withType<Checkstyle>().configureEach { tasks.findByName("jandex")?.let { mustRunAfter(it) } }
tasks.withType<Checkstyle>().configureEach {
if (noSourceCheckProjects.contains(project.path)) {
enabled = false
} else {
// Ensure Checkstyle runs after jandex to avoid task dependency issues
tasks.findByName("jandex")?.let { mustRunAfter(it) }
}
}

tasks.withType(JavaCompile::class.java).configureEach {
options.compilerArgs.addAll(
Expand All @@ -89,23 +95,41 @@ tasks.withType(JavaCompile::class.java).configureEach {
options.errorprone.disableWarningsInGeneratedCode = true
options.errorprone.excludedPaths =
".*/${project.layout.buildDirectory.get().asFile.relativeTo(projectDir)}/generated(-openapi)?/.*"
val errorproneRules = rootProject.projectDir.resolve("codestyle/errorprone-rules.properties")
val errorproneRules = layout.settingsDirectory.file("codestyle/errorprone-rules.properties")
inputs.file(errorproneRules).withPathSensitivity(PathSensitivity.RELATIVE)
options.errorprone.checks.putAll(provider { memoizedErrorproneRules(errorproneRules) })
options.errorprone.checks.putAll(
provider {
val service =
project.gradle.sharedServices.registerIfAbsent(
"errorProneConfig",
ErrorProneConfigService::class.java,
) {
parameters.configFile = errorproneRules
}
service.get().errorproneConfig
}
)
}

private fun memoizedErrorproneRules(rulesFile: File): Map<String, CheckSeverity> =
rulesFile.reader().use {
val rules = Properties()
rules.load(it)
rules
.mapKeys { e -> (e.key as String).trim() }
.mapValues { e -> (e.value as String).trim() }
.filter { e -> e.key.isNotEmpty() && e.value.isNotEmpty() }
.mapValues { e -> CheckSeverity.valueOf(e.value) }
.toMap()
abstract class ErrorProneConfigService : BuildService<ErrorProneConfigService.Parameters> {
interface Parameters : BuildServiceParameters {
val configFile: RegularFileProperty
}

val errorproneConfig: Map<String, CheckSeverity> by lazy {
parameters.configFile.get().asFile.reader().use {
val rules = Properties()
rules.load(it)
rules
.mapKeys { e -> (e.key as String).trim() }
.mapValues { e -> (e.value as String).trim() }
.filter { e -> e.key.isNotEmpty() && e.value.isNotEmpty() }
.mapValues { e -> CheckSeverity.valueOf(e.value) }
.toMap()
}
}
}

tasks.register("compileAll") {
group = "build"
description = "Runs all compilation and jar tasks"
Expand Down Expand Up @@ -139,7 +163,7 @@ testing {
// Special handling for test-suites with names containing `manualtest`, which are intended to
// be run on demand rather than implicitly via `check`.
if (!name.lowercase().contains("manualtest")) {
targets.all {
targets.configureEach {
if (testTask.name != "test") {
testTask.configure { shouldRunAfter("test") }
tasks.named("check").configure { dependsOn(testTask) }
Expand Down Expand Up @@ -273,7 +297,7 @@ class BannedDependencies(
}

fun applyTo(configurations: ConfigurationContainer) {
configurations.all { applyTo(this) }
configurations.configureEach { applyTo(this) }
}
}

Expand All @@ -284,10 +308,10 @@ fun bannedDependencies(): BannedDependencies {
BannedDependenciesService::class.java,
) {
parameters.globallyBannedFile.set(
rootProject.layout.projectDirectory.file("gradle/banned-dependencies.txt")
layout.settingsDirectory.file("gradle/banned-dependencies.txt")
)
parameters.quarkusProdBannedFile.set(
rootProject.layout.projectDirectory.file("gradle/banned-quarkus-prod-dependencies.txt")
layout.settingsDirectory.file("gradle/banned-quarkus-prod-dependencies.txt")
)
}
return service.get().bannedDependencies
Expand Down Expand Up @@ -340,7 +364,7 @@ tasks.withType<Test>().configureEach {
val constraintName =
if (isTestTask) "testParallelismConstraint" else "intTestParallelismConstraint"
usesService(gradle.sharedServices.registrations.named(constraintName).get().service)
if (project.hasProperty("noIntegrationTests") && !isTestTask) {
if (providers.gradleProperty("noIntegrationTests").isPresent && !isTestTask) {
enabled = false
}
}
12 changes: 1 addition & 11 deletions build-logic/src/main/kotlin/polaris-root.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,12 @@ import publishing.PublishingHelperPlugin

plugins {
id("polaris-base")
id("com.diffplug.spotless")
id("polaris-spotless")
id("org.jetbrains.gradle.plugin.idea-ext")
}

apply<PublishingHelperPlugin>()

if (!project.extra.has("duplicated-project-sources")) {
spotless {
kotlinGradle {
ktfmt().googleStyle()
// licenseHeaderFile(rootProject.file("codestyle/copyright-header-java.txt"), "$")
target("*.gradle.kts", "build-logic/*.gradle.kts", "build-logic/src/**/*.kt*")
}
}
}

if (providers.systemProperty("idea.sync.active").getOrElse("false").toBoolean()) {
idea {
module {
Expand Down
24 changes: 6 additions & 18 deletions build-logic/src/main/kotlin/polaris-runtime.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ plugins { id("polaris-server") }
testing {
suites {
withType<JvmTestSuite> {
targets.all {
targets.configureEach {
testTask.configure {
systemProperty("java.util.logging.manager", "org.jboss.logmanager.LogManager")
// Enable automatic extension detection to execute GradleDuplicateLoggingWorkaround
Expand All @@ -45,7 +45,7 @@ testing {
}
fun intTestSuiteConfigure(testSuite: JvmTestSuite) =
testSuite.run {
targets.all {
targets.configureEach {
testTask.configure {
// For Quarkus...
//
Expand All @@ -61,12 +61,12 @@ testing {
dependsOn("compileQuarkusTestGeneratedSourcesJava")
}
configurations.named(sources.runtimeOnlyConfigurationName).configure {
extendsFrom(configurations.getByName("testRuntimeOnly"))
extendsFrom(configurations.named("testRuntimeOnly"))
}
configurations.named(sources.implementationConfigurationName).configure {
// Let the test's implementation config extend testImplementation, so it also inherits the
// project's "main" implementation dependencies (not just the "api" configuration)
extendsFrom(configurations.getByName("testImplementation"))
extendsFrom(configurations.named("testImplementation"))
}
sources { java.srcDirs(tasks.named("quarkusGenerateCodeTests")) }
}
Expand All @@ -82,7 +82,7 @@ dependencies {
implementation("org.jboss.slf4j:slf4j-jboss-logmanager")
}

configurations.all {
configurations.configureEach {
// Validate that Logback dependencies are not used in Quarkus modules.
dependencies.configureEach {
if (group == "ch.qos.logback") {
Expand All @@ -95,7 +95,7 @@ configurations.all {
}

configurations.named("intTestRuntimeOnly").configure {
extendsFrom(configurations.getByName("testRuntimeOnly"))
extendsFrom(configurations.named("testRuntimeOnly"))
}

tasks.named("compileJava") { dependsOn("compileQuarkusGeneratedSourcesJava") }
Expand All @@ -112,20 +112,8 @@ tasks.withType(Test::class.java).configureEach {
// Gradle's Jacoco plugin doesn't work well with Quarkus's test coverage
extensions.configure(JacocoTaskExtension::class) { isEnabled = false }

// Quarkus tests run "in isolated class loaders", which means that class-statically active
// resources pile up used JVM, as those classes cannot be GC'd.
// Examples of those statically held active resources are:
// - Iceberg's worker pools (thread pools, executors, etc.)
// - Hadoop's stats-cleaner (org.apache.hadoop.fs.FileSystem.Statistics.STATS_DATA_CLEANER)
// - Guava's 'MoreExecutors' (via Iceberg `ThreadPools`)`
// Forcing a new JVM after each test class works around this issue.
forkEvery = 1

maxParallelForks = 1

// enlarge the max heap size to avoid out of memory error
maxHeapSize = "4g"

// Silence the 'OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader
// classes because bootstrap classpath has been appended' warning from OpenJDK.
jvmArgs("-Xshare:off")
Expand Down
18 changes: 15 additions & 3 deletions build-logic/src/main/kotlin/polaris-spotless.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,20 @@
plugins { id("com.diffplug.spotless") }

// skip spotless check for duplicated projects
if (!project.extra.has("duplicated-project-sources")) {
spotless {
spotless {
if (project.path == ":") {
// Root project
kotlinGradle {
ktfmt().googleStyle()
target(
"*.gradle.kts",
"build-logic/*.gradle.kts",
"build-logic/src/**/*.kt*",
"gradle/server-test-runner/**/*.gradle.kts",
"gradle/server-test-runner/src/**/*.kt*",
)
}
} else if (!noSourceCheckProjects.contains(project.path)) {
java {
target("src/*/java/**/*.java")
googleJavaFormat()
Expand All @@ -38,7 +50,7 @@ if (!project.extra.has("duplicated-project-sources")) {
target("src/**/*.xml", "src/**/*.xsd")
targetExclude("codestyle/copyright-header.xml")
eclipseWtp(com.diffplug.spotless.extra.wtp.EclipseWtpFormatterStep.XML)
.configFile(rootProject.file("codestyle/org.eclipse.wst.xml.core.prefs"))
.configFile(layout.settingsDirectory.file("codestyle/org.eclipse.wst.xml.core.prefs"))
// getting the license-header delimiter right is a bit tricky.
// licenseHeaderFile(rootProject.file("codestyle/copyright-header.xml"), '<^[!?].*$')
}
Expand Down
16 changes: 9 additions & 7 deletions build-logic/src/main/kotlin/publishing/MemoizedJarInfo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,21 @@ import org.gradle.api.java.archives.Attributes
*/
internal class MemoizedJarInfo {
companion object {
fun applyJarManifestAttributes(rootProject: Project, attribs: Attributes) {
val props = jarManifestAttributes(rootProject)
fun applyJarManifestAttributes(project: Project, attribs: Attributes) {
val props = jarManifestAttributes(project)
attribs.putAll(props)
}

private fun jarManifestAttributes(rootProject: Project): Map<String, String> {
val version = rootProject.version.toString()
val javaSpecificationVersion = System.getProperty("java.specification.version")
private fun jarManifestAttributes(project: Project): Map<String, String> {
val version = project.version.toString()
val javaSpecificationVersion =
project.providers.systemProperty("java.specification.version").get()
val includeGitInformation =
rootProject.hasProperty("release") || rootProject.hasProperty("jarWithGitInfo")
project.providers.gradleProperty("release").isPresent ||
project.providers.gradleProperty("jarWithGitInfo").isPresent

return if (includeGitInformation) {
val gi = GitInfo.memoized(rootProject)
val gi = GitInfo.memoized(project)
mapOf(
"Implementation-Version" to version,
"Apache-Polaris-Version" to version,
Expand Down
Loading