This is an automated email from the ASF dual-hosted git repository. snazy pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/polaris.git
The following commit(s) were added to refs/heads/main by this push: new a0e31b058 Fix bunch of OpenAPI generation issues (#2005) a0e31b058 is described below commit a0e31b0584437602f30a97ed5fc110c50802d9c1 Author: Robert Stupp <sn...@snazy.de> AuthorDate: Wed Jul 9 13:07:56 2025 +0200 Fix bunch of OpenAPI generation issues (#2005) The current way how OpenAPI Java code is generated suffers from a bunch of issues: * Changes to any of the source spec files requires a Gradle `clean`, otherwise old generated Java source will remain - i.e. "no longer" existing sources are not removed. This is addressed by adding an additional action to `GenerateTask`. * The output of `GenerateTask` was explicitly not cached, this is removed, so the output is cached. * Add explicit inputs to `GenerateTask` to the whole templates and spec folders. --- api/iceberg-service/build.gradle.kts | 35 +++++++++++++++------- api/management-model/build.gradle.kts | 33 ++++++++++++++------ api/management-service/build.gradle.kts | 33 ++++++++++++++------ api/polaris-catalog-service/build.gradle.kts | 35 +++++++++++++++------- .../src/main/kotlin/polaris-java.gradle.kts | 2 +- 5 files changed, 97 insertions(+), 41 deletions(-) diff --git a/api/iceberg-service/build.gradle.kts b/api/iceberg-service/build.gradle.kts index 3ae10f821..44256e0d6 100644 --- a/api/iceberg-service/build.gradle.kts +++ b/api/iceberg-service/build.gradle.kts @@ -17,6 +17,8 @@ * under the License. */ +import org.openapitools.generator.gradle.plugin.tasks.GenerateTask + plugins { alias(libs.plugins.openapi.generator) id("polaris-client") @@ -49,14 +51,25 @@ dependencies { compileOnly(libs.microprofile.fault.tolerance.api) } +val rootDir = rootProject.layout.projectDirectory +val specsDir = rootDir.dir("spec") +val templatesDir = rootDir.dir("server-templates") +// Use a different directory than 'generated/', because OpenAPI generator's `GenerateTask` adds the +// whole directory to its task output, but 'generated/' is not exclusive to that task and in turn +// breaks Gradle's caching. +val generatedDir = project.layout.buildDirectory.dir("generated-openapi") +val generatedOpenApiSrcDir = project.layout.buildDirectory.dir("generated-openapi/src/main/java") + openApiGenerate { - inputSpec = "$rootDir/spec/polaris-catalog-service.yaml" + // The OpenAPI generator does NOT resolve relative paths correctly against the Gradle project + // directory + inputSpec = specsDir.file("polaris-catalog-service.yaml").asFile.absolutePath generatorName = "jaxrs-resteasy" - outputDir = "$projectDir/build/generated" + outputDir = generatedDir.get().asFile.absolutePath apiPackage = "org.apache.polaris.service.catalog.api" - ignoreFileOverride = "$rootDir/.openapi-generator-ignore" + ignoreFileOverride = rootDir.file(".openapi-generator-ignore").asFile.absolutePath removeOperationIdPrefix = true - templateDir = "$rootDir/server-templates" + templateDir = templatesDir.asFile.absolutePath globalProperties.put("apis", "CatalogApi,ConfigurationApi,OAuth2Api") globalProperties.put("models", "false") globalProperties.put("apiDocs", "false") @@ -109,16 +122,16 @@ openApiGenerate { ) } -listOf("sourcesJar", "compileJava").forEach { task -> +listOf("sourcesJar", "compileJava", "processResources").forEach { task -> tasks.named(task) { dependsOn("openApiGenerate") } } -sourceSets { - main { java { srcDir(project.layout.buildDirectory.dir("generated/src/main/java")) } } +sourceSets { main { java { srcDir(generatedOpenApiSrcDir) } } } + +tasks.named<GenerateTask>("openApiGenerate") { + inputs.dir(templatesDir) + inputs.dir(specsDir) + actions.addFirst { delete { delete(generatedDir) } } } tasks.named("javadoc") { dependsOn("jandex") } - -tasks.named("processResources") { dependsOn("openApiGenerate") } - -tasks.named("openApiGenerate") { outputs.cacheIf { false } } diff --git a/api/management-model/build.gradle.kts b/api/management-model/build.gradle.kts index 8292711c4..962ec1671 100644 --- a/api/management-model/build.gradle.kts +++ b/api/management-model/build.gradle.kts @@ -17,6 +17,8 @@ * under the License. */ +import org.openapitools.generator.gradle.plugin.tasks.GenerateTask + plugins { alias(libs.plugins.openapi.generator) id("polaris-client") @@ -36,14 +38,25 @@ dependencies { testImplementation("com.fasterxml.jackson.core:jackson-databind") } +val rootDir = rootProject.layout.projectDirectory +val specsDir = rootDir.dir("spec") +val templatesDir = rootDir.dir("server-templates") +// Use a different directory than 'generated/', because OpenAPI generator's `GenerateTask` adds the +// whole directory to its task output, but 'generated/' is not exclusive to that task and in turn +// breaks Gradle's caching. +val generatedDir = project.layout.buildDirectory.dir("generated-openapi") +val generatedOpenApiSrcDir = project.layout.buildDirectory.dir("generated-openapi/src/main/java") + openApiGenerate { - inputSpec = "$rootDir/spec/polaris-management-service.yml" + // The OpenAPI generator does NOT resolve relative paths correctly against the Gradle project + // directory + inputSpec = specsDir.file("polaris-management-service.yml").asFile.absolutePath generatorName = "jaxrs-resteasy" - outputDir = "$projectDir/build/generated" + outputDir = generatedDir.get().asFile.absolutePath modelPackage = "org.apache.polaris.core.admin.model" - ignoreFileOverride = "$rootDir/.openapi-generator-ignore" + ignoreFileOverride = rootDir.file(".openapi-generator-ignore").asFile.absolutePath removeOperationIdPrefix = true - templateDir = "$rootDir/server-templates" + templateDir = templatesDir.asFile.absolutePath globalProperties.put("apis", "false") globalProperties.put("models", "") globalProperties.put("apiDocs", "false") @@ -64,14 +77,16 @@ openApiGenerate { serverVariables = mapOf("basePath" to "api/v1") } -listOf("sourcesJar", "compileJava").forEach { task -> +listOf("sourcesJar", "compileJava", "processResources").forEach { task -> tasks.named(task) { dependsOn("openApiGenerate") } } -sourceSets { - main { java { srcDir(project.layout.buildDirectory.dir("generated/src/main/java")) } } +sourceSets { main { java { srcDir(generatedOpenApiSrcDir) } } } + +tasks.named<GenerateTask>("openApiGenerate") { + inputs.dir(templatesDir) + inputs.dir(specsDir) + actions.addFirst { delete { delete(generatedDir) } } } tasks.named("javadoc") { dependsOn("jandex") } - -tasks.named("processResources") { dependsOn("openApiGenerate") } diff --git a/api/management-service/build.gradle.kts b/api/management-service/build.gradle.kts index 7ebae4a15..31f493ac9 100644 --- a/api/management-service/build.gradle.kts +++ b/api/management-service/build.gradle.kts @@ -17,6 +17,8 @@ * under the License. */ +import org.openapitools.generator.gradle.plugin.tasks.GenerateTask + plugins { alias(libs.plugins.openapi.generator) id("polaris-client") @@ -45,15 +47,26 @@ dependencies { implementation(libs.slf4j.api) } +val rootDir = rootProject.layout.projectDirectory +val specsDir = rootDir.dir("spec") +val templatesDir = rootDir.dir("server-templates") +// Use a different directory than 'generated/', because OpenAPI generator's `GenerateTask` adds the +// whole directory to its task output, but 'generated/' is not exclusive to that task and in turn +// breaks Gradle's caching. +val generatedDir = project.layout.buildDirectory.dir("generated-openapi") +val generatedOpenApiSrcDir = project.layout.buildDirectory.dir("generated-openapi/src/main/java") + openApiGenerate { - inputSpec = "$rootDir/spec/polaris-management-service.yml" + // The OpenAPI generator does NOT resolve relative paths correctly against the Gradle project + // directory + inputSpec = specsDir.file("polaris-management-service.yml").asFile.absolutePath generatorName = "jaxrs-resteasy" - outputDir = "$projectDir/build/generated" + outputDir = generatedDir.get().asFile.absolutePath apiPackage = "org.apache.polaris.service.admin.api" modelPackage = "org.apache.polaris.core.admin.model" - ignoreFileOverride = "$rootDir/.openapi-generator-ignore" + ignoreFileOverride = rootDir.file(".openapi-generator-ignore").asFile.absolutePath removeOperationIdPrefix = true - templateDir = "$rootDir/server-templates" + templateDir = templatesDir.asFile.absolutePath globalProperties.put("apis", "") globalProperties.put("models", "false") globalProperties.put("apiDocs", "false") @@ -70,14 +83,16 @@ openApiGenerate { serverVariables.put("basePath", "api/v1") } -listOf("sourcesJar", "compileJava").forEach { task -> +listOf("sourcesJar", "compileJava", "processResources").forEach { task -> tasks.named(task) { dependsOn("openApiGenerate") } } -sourceSets { - main { java { srcDir(project.layout.buildDirectory.dir("generated/src/main/java")) } } +sourceSets { main { java { srcDir(generatedOpenApiSrcDir) } } } + +tasks.named<GenerateTask>("openApiGenerate") { + inputs.dir(templatesDir) + inputs.dir(specsDir) + actions.addFirst { delete { delete(generatedDir) } } } tasks.named("javadoc") { dependsOn("jandex") } - -tasks.named("processResources") { dependsOn("openApiGenerate") } diff --git a/api/polaris-catalog-service/build.gradle.kts b/api/polaris-catalog-service/build.gradle.kts index 9afb3ccf6..cab5f0cf9 100644 --- a/api/polaris-catalog-service/build.gradle.kts +++ b/api/polaris-catalog-service/build.gradle.kts @@ -17,6 +17,8 @@ * under the License. */ +import org.openapitools.generator.gradle.plugin.tasks.GenerateTask + plugins { alias(libs.plugins.openapi.generator) id("polaris-client") @@ -75,15 +77,26 @@ dependencies { compileOnly(libs.microprofile.fault.tolerance.api) } +val rootDir = rootProject.layout.projectDirectory +val specsDir = rootDir.dir("spec") +val templatesDir = rootDir.dir("server-templates") +// Use a different directory than 'generated/', because OpenAPI generator's `GenerateTask` adds the +// whole directory to its task output, but 'generated/' is not exclusive to that task and in turn +// breaks Gradle's caching. +val generatedDir = project.layout.buildDirectory.dir("generated-openapi") +val generatedOpenApiSrcDir = project.layout.buildDirectory.dir("generated-openapi/src/main/java") + openApiGenerate { - inputSpec = "$rootDir/spec/polaris-catalog-service.yaml" + // The OpenAPI generator does NOT resolve relative paths correctly against the Gradle project + // directory + inputSpec = specsDir.file("polaris-catalog-service.yaml").asFile.absolutePath generatorName = "jaxrs-resteasy" - outputDir = "$projectDir/build/generated" + outputDir = generatedDir.get().asFile.absolutePath apiPackage = "org.apache.polaris.service.catalog.api" modelPackage = "org.apache.polaris.service.types" - ignoreFileOverride = "$rootDir/.openapi-generator-ignore" + ignoreFileOverride = rootDir.file(".openapi-generator-ignore").asFile.absolutePath removeOperationIdPrefix = true - templateDir = "$rootDir/server-templates" + templateDir = templatesDir.asFile.absolutePath globalProperties.put("apis", "GenericTableApi,PolicyApi") globalProperties.put("models", models) globalProperties.put("apiDocs", "false") @@ -112,16 +125,16 @@ openApiGenerate { ) } -listOf("sourcesJar", "compileJava").forEach { task -> +listOf("sourcesJar", "compileJava", "processResources").forEach { task -> tasks.named(task) { dependsOn("openApiGenerate") } } -sourceSets { - main { java { srcDir(project.layout.buildDirectory.dir("generated/src/main/java")) } } +sourceSets { main { java { srcDir(generatedOpenApiSrcDir) } } } + +tasks.named<GenerateTask>("openApiGenerate") { + inputs.dir(templatesDir) + inputs.dir(specsDir) + actions.addFirst { delete { delete(generatedDir) } } } tasks.named("javadoc") { dependsOn("jandex") } - -tasks.named("processResources") { dependsOn("openApiGenerate") } - -tasks.named("openApiGenerate") { outputs.cacheIf { false } } diff --git a/build-logic/src/main/kotlin/polaris-java.gradle.kts b/build-logic/src/main/kotlin/polaris-java.gradle.kts index 4370b5518..980a144b7 100644 --- a/build-logic/src/main/kotlin/polaris-java.gradle.kts +++ b/build-logic/src/main/kotlin/polaris-java.gradle.kts @@ -60,7 +60,7 @@ tasks.withType(JavaCompile::class.java).configureEach { options.errorprone.disableAllWarnings = true options.errorprone.disableWarningsInGeneratedCode = true options.errorprone.excludedPaths = - ".*/${project.layout.buildDirectory.get().asFile.relativeTo(projectDir)}/generated/.*" + ".*/${project.layout.buildDirectory.get().asFile.relativeTo(projectDir)}/generated(-openapi)?/.*" val errorproneRules = rootProject.projectDir.resolve("codestyle/errorprone-rules.properties") inputs.file(errorproneRules).withPathSensitivity(PathSensitivity.RELATIVE) options.errorprone.checks.putAll(provider { memoizedErrorproneRules(errorproneRules) })