Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: prevent cache invalidation due to project directory change #159

Merged
merged 2 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions src/main/kotlin/dev/monosoul/jooq/GenerateJooqClassesTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import dev.monosoul.jooq.settings.JooqDockerPluginSettings.WithoutContainer
import dev.monosoul.jooq.settings.SettingsAware
import dev.monosoul.jooq.util.CodegenClasspathAwareClassLoaders
import dev.monosoul.jooq.util.callWith
import dev.monosoul.jooq.util.copy
import dev.monosoul.jooq.util.getCodegenLogging
import groovy.lang.Closure
import org.gradle.api.Action
Expand Down Expand Up @@ -162,7 +163,6 @@ open class GenerateJooqClassesTask
private val configurationProvider =
ConfigurationProvider(
basePackageName = basePackageName,
outputDirectory = outputDirectory,
outputSchemaToDefault = outputSchemaToDefault,
schemaToPackageMapping = schemaToPackageMapping,
schemas = schemas,
Expand Down Expand Up @@ -254,14 +254,15 @@ open class GenerateJooqClassesTask
codegenRunner.generateJooqClasses(
codegenAwareClassLoader = jdbcAwareClassLoader,
configuration =
_generatorConfig.get().value.postProcess(
_generatorConfig.get().value.copy().postProcess(
schemaVersion = schemaVersion,
credentials = credentials,
extraTableExclusions =
listOfNotNull(
migrationRunner.flywayTableName.takeUnless { includeFlywayTable.get() },
),
),
outputDirectory = outputDirectory,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package dev.monosoul.jooq.codegen

import dev.monosoul.jooq.migration.SchemaVersion
import dev.monosoul.jooq.settings.DatabaseCredentials
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileContents
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.MapProperty
Expand All @@ -28,7 +27,6 @@ import java.io.InputStream

internal class ConfigurationProvider(
private val basePackageName: Property<String>,
private val outputDirectory: DirectoryProperty,
private val outputSchemaToDefault: SetProperty<String>,
private val schemaToPackageMapping: MapProperty<String, String>,
private val schemas: ListProperty<String>,
Expand Down Expand Up @@ -66,7 +64,7 @@ internal class ConfigurationProvider(
private fun codeGenTarget() =
Target()
.withPackageName(basePackageName.get())
.withDirectory(outputDirectory.asFile.get().toString())
.withDirectory("./generated-jooq-placeholder")
.withEncoding("UTF-8")
.withClean(true)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dev.monosoul.jooq.codegen

import dev.monosoul.jooq.JooqDockerPlugin.Companion.CONFIGURATION_NAME
import dev.monosoul.jooq.util.CodegenClasspathAwareClassLoaders
import org.gradle.api.file.DirectoryProperty
import org.jooq.meta.jaxb.Configuration
import org.slf4j.Logger
import org.slf4j.LoggerFactory
Expand All @@ -12,7 +13,10 @@ internal class UniversalJooqCodegenRunner {
fun generateJooqClasses(
codegenAwareClassLoader: CodegenClasspathAwareClassLoaders,
configuration: Configuration,
outputDirectory: DirectoryProperty,
) {
configuration.generator.target.directory = outputDirectory.asFile.get().toString()

runCatching {
ReflectiveJooqCodegenRunner(codegenAwareClassLoader.buildscriptExclusive)
}.onFailure {
Expand Down
20 changes: 20 additions & 0 deletions src/main/kotlin/dev/monosoul/jooq/util/ConfigurationCopy.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dev.monosoul.jooq.util

import org.jooq.meta.jaxb.Configuration
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.ObjectInputStream
import java.io.ObjectOutputStream

internal fun Configuration.copy(): Configuration {
val serialized =
ByteArrayOutputStream().apply {
ObjectOutputStream(this).use { oos ->
oos.writeObject(this@copy)
}
}.toByteArray()

return ObjectInputStream(ByteArrayInputStream(serialized)).use { ois ->
ois.readObject() as Configuration
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dev.monosoul.jooq.functional

import org.gradle.testkit.runner.TaskOutcome.FROM_CACHE
import org.gradle.testkit.runner.TaskOutcome.SUCCESS
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import strikt.api.expect
Expand All @@ -13,10 +14,27 @@ class CacheJooqDockerPluginFunctionalTest : JooqDockerPluginFunctionalTestBase()
@TempDir
private lateinit var localBuildCacheDirectory: File

@TempDir
private lateinit var siblingProjectDir: File

@BeforeEach
fun siblingSetUp() {
siblingProjectDir.copy(from = "/testkit-gradle.properties", to = "gradle.properties")
}

@Test
fun `should load generateJooqClasses task output from cache`() {
// given
configureLocalGradleCache()
writeProjectFile("settings.gradle.kts") {
"""
buildCache {
local {
directory = "${localBuildCacheDirectory.path}"
}
}
""".trimIndent()
}

prepareBuildGradleFile {
"""
plugins {
Expand Down Expand Up @@ -61,15 +79,63 @@ class CacheJooqDockerPluginFunctionalTest : JooqDockerPluginFunctionalTestBase()
}
}

private fun configureLocalGradleCache() {
writeProjectFile("settings.gradle.kts") {
"""
buildCache {
local {
directory = "${localBuildCacheDirectory.path}"
}
@Test
fun `sibling project in a different directory should have the same cache hash`() {
// given
"""
buildCache {
local {
directory = "${localBuildCacheDirectory.path}"
}
""".trimIndent()
}
""".trimIndent().also {
writeProjectFile("settings.gradle.kts") { it }
siblingProjectDir.writeBuildGradleFile("settings.gradle.kts") { it }
}

"""
plugins {
id("dev.monosoul.jooq-docker")
}

repositories {
mavenCentral()
}

dependencies {
jooqCodegen("org.postgresql:postgresql:42.3.6")
}
""".trimIndent().also {
prepareBuildGradleFile { it }
siblingProjectDir.writeBuildGradleFile { it }
}

copyResource(from = "/V01__init.sql", to = "src/main/resources/db/migration/V01__init.sql")
siblingProjectDir.copy(from = "/V01__init.sql", to = "src/main/resources/db/migration/V01__init.sql")

// when
// run from the first project loads to cache
val resultWithoutCache = runGradleWithArguments("generateJooqClasses", "--build-cache")

// run from the sibling project uses the cache
val resultFromCache =
runGradleWithArguments(
"generateJooqClasses",
"--build-cache",
projectDirectory = siblingProjectDir,
)

// then
expect {
that(resultWithoutCache).generateJooqClassesTask.outcome isEqualTo SUCCESS
that(resultFromCache).generateJooqClassesTask.outcome isEqualTo FROM_CACHE

that(
projectFile("build/generated-jooq/org/jooq/generated/tables/Foo.java"),
).exists()
that(
siblingProjectDir.getChild("build/generated-jooq/org/jooq/generated/tables/Foo.java"),
).exists()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ abstract class FunctionalTestBase {
private lateinit var projectDir: File

protected open fun recreateProjectDir() {
projectDir.deleteRecursively()
projectDir.mkdirs()
projectDir.recreate()
}

protected fun runGradleWithArguments(vararg arguments: String): BuildResult =
protected fun runGradleWithArguments(
vararg arguments: String,
projectDirectory: File = projectDir,
): BuildResult =
GradleRunner.create()
.withProjectDir(projectDir)
.withProjectDir(projectDirectory)
.withPluginClasspath()
.forwardOutput()
.withArguments(*arguments, "--stacktrace", "--info")
Expand All @@ -29,27 +31,19 @@ abstract class FunctionalTestBase {
protected fun copyResource(
from: String,
to: String,
) {
val destinationFile = projectFile(to)
javaClass.getResourceAsStream(from)?.use { sourceStream ->
FileOutputStream(destinationFile).use { destinationStream ->
sourceStream.copyTo(destinationStream)
}
} ?: throw IllegalStateException("Resource not found: $from")
}
) = projectDir.copy(from, to)

protected fun prepareBuildGradleFile(
scriptName: String = "build.gradle.kts",
scriptSupplier: () -> String,
) = writeProjectFile(scriptName, scriptSupplier)
) = projectDir.writeBuildGradleFile(scriptName, scriptSupplier)

protected fun writeProjectFile(
fileName: String,
bodySupplier: () -> String,
) = projectFile(fileName)
.writeText(bodySupplier())
) = projectDir.writeChild(fileName, bodySupplier)

protected fun projectFile(fileName: String) = File(projectDir, fileName).also { it.parentFile.mkdirs() }
protected fun projectFile(fileName: String) = projectDir.getChild(fileName)

protected fun Assertion.Builder<BuildResult>.getTask(taskName: String) =
get { task(":$taskName") }
Expand All @@ -60,4 +54,34 @@ abstract class FunctionalTestBase {
protected fun Assertion.Builder<BuildResult>.getTaskOutcome(taskName: String) = getTask(taskName).outcome

protected val Assertion.Builder<BuildResult>.generateJooqClassesTask get() = getTask("generateJooqClasses")

protected fun File.recreate() {
deleteRecursively()
mkdirs()
}

protected fun File.getChild(fileName: String) = File(this, fileName).also { it.parentFile.mkdirs() }

protected fun File.writeChild(
fileName: String,
bodySupplier: () -> String,
) = getChild(fileName)
.writeText(bodySupplier())

protected fun File.writeBuildGradleFile(
scriptName: String = "build.gradle.kts",
scriptSupplier: () -> String,
) = writeChild(scriptName, scriptSupplier)

protected fun File.copy(
from: String,
to: String,
) {
val destinationFile = getChild(to)
[email protected](from)?.use { sourceStream ->
FileOutputStream(destinationFile).use { destinationStream ->
sourceStream.copyTo(destinationStream)
}
} ?: throw IllegalStateException("Resource not found: $from")
}
}
Loading