Skip to content

Commit

Permalink
patch: (#171) add workaround for the gradle task dependencies problem (
Browse files Browse the repository at this point in the history
…#172)

* we work around this by creating a dummy directory which we will use as a working directory for the forked spring bootRun task. Because some other tasks also seem to use this directory we also make them depend on this task. But that list might be incomplete.

Signed-off-by: Clemens Grabmann <[email protected]>
  • Loading branch information
cgrabmann authored Aug 22, 2023
1 parent 404fec2 commit 80b62cf
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 28 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ dependencies {

implementation(libs.springdoc.openapi.plugin)
implementation(libs.kotlinx.serialization.json)
implementation(libs.exec.fork.plugin)

testImplementation(libs.bundles.testImplementationDependencies)

Expand Down
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ swagger-codegen-plugin = { module = "gradle.plugin.org.hidetake:gradle-swagger-g
swagger-jersey2-jaxrs = { module = "io.swagger:swagger-jersey2-jaxrs", version = { strictly = "1.6.2" } }

springdoc-openapi-plugin = { module = "org.springdoc:springdoc-openapi-gradle-plugin", version = "1.7.0" }
exec-fork-plugin = { module = "com.github.psxpaul:gradle-execfork-plugin", version = "0.2.0" }

# we need to manually inject this version because of https://github.com/ronmamo/reflections/issues/273 (we would transitively pull 0.9.2 otherwise)
reflections = { module = "org.reflections:reflections", version = { strictly = "0.9.11" } }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package io.cloudflight.gradle.autoconfigure.extentions.gradle.api

import org.gradle.api.DomainObjectCollection
import org.gradle.api.NamedDomainObjectProvider
import org.gradle.api.NamedDomainObjectSet
import kotlin.reflect.KClass

internal fun <T : Any, S : T> NamedDomainObjectSet<T>.withType(klass: KClass<S>): NamedDomainObjectSet<S> = this.withType(klass.java)
internal fun <T : Any, S : T> NamedDomainObjectSet<T>.withType(klass: KClass<S>): NamedDomainObjectSet<S> = this.withType(klass.java)

internal fun <T : Any, S : T> NamedDomainObjectSet<T>.withType(klass: KClass<S>, configuration: (it: S) -> Unit): DomainObjectCollection<S> = this.withType(klass.java, configuration)

internal fun <T: Any, S : T> NamedDomainObjectSet<T>.named(name: String, klass: KClass<S>): NamedDomainObjectProvider<S> = this.named(name, klass.java)

internal fun <T: Any, S : T> NamedDomainObjectSet<T>.named(name: String, klass: KClass<S>, configuration: (it: S) -> Unit): NamedDomainObjectProvider<S> = this.named(name, klass.java, configuration)
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package io.cloudflight.gradle.autoconfigure.springdoc.openapi

import com.github.psxpaul.task.JavaExecFork
import io.cloudflight.gradle.autoconfigure.AutoConfigureGradlePlugin.Companion.TASK_GROUP
import io.cloudflight.gradle.autoconfigure.extentions.gradle.api.named
import io.cloudflight.gradle.autoconfigure.extentions.gradle.api.withType
import io.cloudflight.gradle.autoconfigure.java.JavaConfigurePlugin
import io.cloudflight.gradle.autoconfigure.util.addApiDocumentationPublication
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.publish.maven.tasks.GenerateMavenPom
import org.gradle.api.tasks.TaskProvider
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springdoc.openapi.gradle.plugin.OpenApiExtension
import org.springdoc.openapi.gradle.plugin.OpenApiGradlePlugin
import org.springframework.boot.gradle.plugin.SpringBootPlugin
import java.net.ServerSocket
import java.nio.file.Files

class SpringDocOpenApiConfigurePlugin : Plugin<Project> {
override fun apply(target: Project) {
Expand All @@ -31,16 +37,50 @@ class SpringDocOpenApiConfigurePlugin : Plugin<Project> {
}
}

target.tasks.register("clfGenerateOpenApiDocumentation") {
val documentationTask = target.tasks.register("clfGenerateOpenApiDocumentation") {
it.group = TASK_GROUP
it.dependsOn(json2Yaml)
}

target.tasks.withType(GenerateMavenPom::class) {
it.dependsOn(documentationTask)
}

`setupWorkaroundFor#171`(target, openapi)

target.afterEvaluate {
configureJsonDocumentPublishing(openapi, target, openApiTask)
configureYamlDocumentPublishing(target, openapi, json2Yaml)
}
}

private fun `setupWorkaroundFor#171`(target: Project, openapi: OpenApiExtension) {
val forkedSpringBootRun = target.tasks.named("forkedSpringBootRun", JavaExecFork::class)

val createDirTask = target.tasks.register("createDummyForkedSpringBootWorkingDir") { task ->
// use same working dir resolution as plugin itself: https://github.com/springdoc/springdoc-openapi-gradle-plugin/blob/master/src/main/kotlin/org/springdoc/openapi/gradle/plugin/OpenApiGradlePlugin.kt#L98
val workingDirProvider = openapi.customBootRun.workingDir.zip(forkedSpringBootRun) { dir, forked ->
dir?.asFile ?: forked.workingDir
}
task.outputs.dir(workingDirProvider)
task.doFirst {
val workingDir = workingDirProvider.get()
Files.createDirectories(workingDir.toPath())
}
}

// these tasks also need to depend on the createDirTask since they somehow access the dummy folder as well
val dependingTaskNames = setOf("resolveMainClassName", "processResources", "compileKotlin", "compileJava")

target.tasks.matching { dependingTaskNames.contains(it.name) }.configureEach {
it.dependsOn(createDirTask)
}

forkedSpringBootRun.configure {
it.dependsOn(createDirTask)
}
}

private fun configureOpenApiExtension(
openapi: OpenApiExtension,
target: Project,
Expand All @@ -51,17 +91,16 @@ class SpringDocOpenApiConfigurePlugin : Plugin<Project> {
val managementPort = freeServerSocketPort()

outputDir.set(target.layout.buildDirectory.dir("generated/resources/openapi"))
logger.debug("outputDir={}", outputDir.get())
outputFileName.set("${basename}.json")
logger.debug("outputFileName={}", outputFileName.get())
apiDocsUrl.set("http://localhost:${serverPort}/v3/api-docs")
logger.debug("apiDocsUrl={}", apiDocsUrl.get())
customBootRun {
it.workingDir.set(target.layout.buildDirectory.dir("dummyForkedSpringBootWorkingDir"))
}

mapOf(
"--server.port" to serverPort,
"--management.server.port" to managementPort
).forEach { arg ->
logger.debug("Set ${arg.key}=${arg.value}")
customBootRun.args.add("${arg.key}=${arg.value}")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,18 +146,12 @@ class SwaggerApiConfigurePlugin : Plugin<Project> {
}
}





companion object {


private fun getFilesFromSourceSet(project: Project): FileCollection {
val javaPluginExtension = project.extensions.getByType(JavaPluginExtension::class.java)
val sourceSetMain = javaPluginExtension.sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME)

return sourceSetMain.output.classesDirs
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import org.ajoberstar.reckon.gradle.ReckonExtension

pluginManagement {
repositories {
maven {
url = uri("https://artifacts.cloudflight.io/repository/plugins-maven")
}
}
}

plugins {
id("io.cloudflight.autoconfigure-settings")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
plugins {
id("io.cloudflight.autoconfigure.springdoc-openapi-configure")
id("io.cloudflight.autoconfigure.springdoc-openapi-configure")
id("maven-publish")
}

group = "io.cloudflight.skeleton.angular"

java {
withJavadocJar()
}

dependencies {
Expand All @@ -21,10 +28,14 @@ dependencies {
implementation(libs.springdoc.openapi.starter.webmvc.api)
}

tasks.named("forkedSpringBootRun") {
doNotTrackState("We cannot track the state during the test since the working directory is already blocked by the test-executing gradle-process.")
}

openApi {
outputFileName.set("custom-openapi.json")
}

publishing {
publications {
create<MavenPublication>("maven") {
from(components.getByName("java"))
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.cloudflight.gradle.autoconfigure.springdocopenapi

import io.cloudflight.gradle.autoconfigure.test.util.ProjectFixture
import io.cloudflight.gradle.autoconfigure.test.util.normalizedOutput
import io.cloudflight.gradle.autoconfigure.test.util.useFixture
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
Expand All @@ -17,11 +18,10 @@ class SpringDocOpenApiConfigurePluginTest {
assertThat(buildDir().resolve("generated/resources/openapi/springdoc-openapi.yaml")).exists()
}


@Test
fun `the openapi document is created in a multi module project`():
Unit = springdocFixture("kotlin-springboot-angular") {
val result = run("clfGenerateOpenApiDocumentation")
val result = run("publishToMavenLocal")

assertThat(buildDir("skeleton-server").resolve("generated/resources/openapi/custom-openapi.json")).exists()
assertThat(buildDir("skeleton-server").resolve("generated/resources/openapi/custom-openapi.yaml")).exists()
Expand Down

0 comments on commit 80b62cf

Please sign in to comment.