Allow configuration cache compatibility (#15693)

* Allow configuration cache compatibility

Use FileSystemOperations to delete output folder if Gradle Version >= 6

* Skip Gradle legacy test if JDK is not compatible
This commit is contained in:
Jérôme Prinet 2023-06-09 03:24:04 +02:00 committed by GitHub
parent 02790f987e
commit 113cf9db40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 165 additions and 2 deletions

View File

@ -16,8 +16,12 @@
package org.openapitools.generator.gradle.plugin.tasks package org.openapitools.generator.gradle.plugin.tasks
import javax.inject.Inject
import org.gradle.api.DefaultTask import org.gradle.api.DefaultTask
import org.gradle.api.GradleException import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.file.FileSystemOperations
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property import org.gradle.api.provider.Property
import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.Input import org.gradle.api.tasks.Input
@ -35,6 +39,7 @@ import org.gradle.internal.logging.text.StyledTextOutputFactory
import org.gradle.kotlin.dsl.listProperty import org.gradle.kotlin.dsl.listProperty
import org.gradle.kotlin.dsl.mapProperty import org.gradle.kotlin.dsl.mapProperty
import org.gradle.kotlin.dsl.property import org.gradle.kotlin.dsl.property
import org.gradle.util.GradleVersion
import org.openapitools.codegen.CodegenConstants import org.openapitools.codegen.CodegenConstants
import org.openapitools.codegen.DefaultGenerator import org.openapitools.codegen.DefaultGenerator
import org.openapitools.codegen.config.CodegenConfigurator import org.openapitools.codegen.config.CodegenConfigurator
@ -52,7 +57,8 @@ import org.openapitools.codegen.config.MergedSpecBuilder
*/ */
@Suppress("UnstableApiUsage") @Suppress("UnstableApiUsage")
@CacheableTask @CacheableTask
open class GenerateTask : DefaultTask() { open class GenerateTask @Inject constructor(private val objectFactory: ObjectFactory) : DefaultTask() {
/** /**
* The verbosity of generation * The verbosity of generation
*/ */
@ -547,6 +553,14 @@ open class GenerateTask : DefaultTask() {
protected open fun createDefaultCodegenConfigurator(): CodegenConfigurator = CodegenConfigurator() protected open fun createDefaultCodegenConfigurator(): CodegenConfigurator = CodegenConfigurator()
private fun createFileSystemManager(): FileSystemManager {
return if(GradleVersion.current() >= GradleVersion.version("6.0")) {
objectFactory.newInstance(FileSystemManagerDefault::class.java)
} else {
objectFactory.newInstance(FileSystemManagerLegacy::class.java, project)
}
}
@Suppress("unused") @Suppress("unused")
@TaskAction @TaskAction
fun doWork() { fun doWork() {
@ -557,7 +571,7 @@ open class GenerateTask : DefaultTask() {
cleanupOutput.ifNotEmpty { cleanup -> cleanupOutput.ifNotEmpty { cleanup ->
if (cleanup) { if (cleanup) {
project.delete(outputDir) createFileSystemManager().delete(outputDir)
val out = services.get(StyledTextOutputFactory::class.java).create("openapi") val out = services.get(StyledTextOutputFactory::class.java).create("openapi")
out.withStyle(StyledTextOutput.Style.Success) out.withStyle(StyledTextOutput.Style.Success)
out.println("Cleaned up output directory ${outputDir.get()} before code generation (cleanupOutput set to true).") out.println("Cleaned up output directory ${outputDir.get()} before code generation (cleanupOutput set to true).")
@ -861,3 +875,23 @@ open class GenerateTask : DefaultTask() {
} }
} }
} }
internal interface FileSystemManager {
fun delete(outputDir: Property<String>)
}
internal open class FileSystemManagerLegacy @Inject constructor(private val project: Project): FileSystemManager {
override fun delete(outputDir: Property<String>) {
project.delete(outputDir)
}
}
internal open class FileSystemManagerDefault @Inject constructor(private val fs: FileSystemOperations) : FileSystemManager {
override fun delete(outputDir: Property<String>) {
fs.delete { delete(outputDir) }
}
}

View File

@ -0,0 +1,129 @@
package org.openapitools.generator.gradle.plugin
import org.gradle.testkit.runner.TaskOutcome
import org.testng.SkipException
import org.testng.annotations.BeforeMethod
import org.testng.annotations.DataProvider
import org.testng.annotations.Test
import java.io.File
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class GenerateTaskConfigurationCacheTest : TestBase() {
private lateinit var projectDirCC: File
@BeforeMethod
override fun before() {
initialize()
projectDirCC = temp.resolve("projectDirCC").apply { mkdir() }
}
@DataProvider(name = "gradle_version_provider")
private fun gradleVersionProviderWithConfigurationCache(): Array<Array<String>> = arrayOf(arrayOf("8.1.1"), arrayOf("7.6"))
@DataProvider(name = "gradle_version_provider_without_cc")
private fun gradleVersionProviderWithoutConfigurationCache(): Array<Array<String>> = arrayOf(arrayOf("5.6.1"))
// inputSpec tests
private val inputSpecExtensionContents = """
generatorName = "kotlin"
inputSpec = file("spec.yaml").absolutePath
cleanupOutput.set(true)
""".trimIndent()
@Test(dataProvider = "gradle_version_provider")
fun `openApiGenerate should reuse configuration cache`(gradleVersion: String) {
// Arrange
withProject(inputSpecExtensionContents)
// Act
val result1 = build {
withProjectDir(projectDirCC)
withArguments("--configuration-cache", "clean", "openApiGenerate")
withGradleVersion(gradleVersion)
}
val expectedRelativeFilePathSet = projectDirCC.toRelativeFilePathSet()
val result2 = build {
withProjectDir(projectDirCC)
withArguments("--configuration-cache", "clean", "openApiGenerate")
withGradleVersion(gradleVersion)
}
// Assert
assertEquals(TaskOutcome.SUCCESS, result1.task(":openApiGenerate")?.outcome)
assertTrue(result1.output.contains("Configuration cache entry stored."))
assertEquals(TaskOutcome.SUCCESS, result2.task(":openApiGenerate")?.outcome)
assertTrue(result2.output.contains("Configuration cache entry reused."))
assertEquals(expectedRelativeFilePathSet, projectDirCC.toRelativeFilePathSet())
}
private fun getJavaVersion(): Int {
val version = System.getProperty("java.version")
val parts = version.split('.')
if (parts.first() == "1") return parts.getOrElse(1) { "0" }.toInt()
return parts.first().toInt()
}
@Test(dataProvider = "gradle_version_provider_without_cc")
fun `openApiGenerate should work with Gradle legacy versions`(gradleVersion: String) {
if(getJavaVersion() > 12) {
// https://docs.gradle.org/current/userguide/compatibility.html
throw SkipException("Skipping test as Gradle ${gradleVersion} is not compatible with Java ${getJavaVersion()}")
}
// Arrange
withProject(inputSpecExtensionContents)
// Act
val result1 = build {
withProjectDir(projectDirCC)
withArguments("clean", "openApiGenerate")
withGradleVersion(gradleVersion)
}
val expectedRelativeFilePathSet = projectDirCC.toRelativeFilePathSet()
val result2 = build {
withProjectDir(projectDirCC)
withArguments("clean", "openApiGenerate")
withGradleVersion(gradleVersion)
}
// Assert
assertEquals(TaskOutcome.SUCCESS, result1.task(":openApiGenerate")?.outcome)
assertEquals(TaskOutcome.SUCCESS, result2.task(":openApiGenerate")?.outcome)
assertEquals(expectedRelativeFilePathSet, projectDirCC.toRelativeFilePathSet())
}
// Helper methods & test fixtures
private fun File.toRelativeFilePathSet() =
resolve("build").walk().map { it.toRelativeString(resolve("build")) }.toSet()
private fun withProject(extensionContents: String) {
val settingsContents = """
rootProject.name = "openapi-generator"
""".trimIndent()
val buildContents = """
plugins {
id 'base'
id 'org.openapi.generator'
}
openApiGenerate {
$extensionContents
}
""".trimIndent()
val projectFiles = mapOf(
"spec.yaml" to javaClass.classLoader.getResourceAsStream("specs/petstore-v3.0.yaml")!!
)
withProject(
projectDir = projectDirCC,
settingsContents = settingsContents,
buildContents = buildContents,
projectFiles = projectFiles
)
}
}