diff --git a/avro/src/main/kotlin/com/bakdata/gradle/SourceSetConfigurator.kt b/avro/src/main/kotlin/com/bakdata/gradle/SourceSetConfigurator.kt index 0a6f20a..12813bd 100644 --- a/avro/src/main/kotlin/com/bakdata/gradle/SourceSetConfigurator.kt +++ b/avro/src/main/kotlin/com/bakdata/gradle/SourceSetConfigurator.kt @@ -29,10 +29,7 @@ import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.ConfigurationContainer -import org.gradle.api.file.Directory import org.gradle.api.file.FileCollection -import org.gradle.api.provider.Provider -import org.gradle.api.tasks.Copy import org.gradle.api.tasks.Delete import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.compile.JavaCompile @@ -40,7 +37,7 @@ import java.io.File import java.util.zip.ZipEntry import java.util.zip.ZipFile -private const val EXTERNAL_AVRO_RESOURCES = "externalAvroResources" +private const val AVRO_JAVA = "avroJava" private const val EXTERNAL_JAVA = "externalJava" @@ -50,16 +47,14 @@ class SourceSetConfigurator(project: Project, sourceSet: SourceSet) { private val generateAvroJava: GenerateAvroJavaTask private val configureDeleteExternalJava: Task private val deleteExternalJava: Delete - private val externalAvroDir: Provider - private val configureCopyAvro: Task - private val copyAvro: Copy + private val configureGenerateAvroJava: Task private val avroOutputs: FileCollection init { this.project = project this.sourceSet = sourceSet this.generateAvroJava = - project.tasks.named(sourceSet.getTaskName("generate", "avroJava"), GenerateAvroJavaTask::class.java).get() + project.tasks.named(sourceSet.getTaskName("generate", AVRO_JAVA), GenerateAvroJavaTask::class.java).get() this.configureDeleteExternalJava = project.task(sourceSet.getTaskName("configureDelete", EXTERNAL_JAVA)) { dependsOn(generateAvroJava) group = generateAvroJava.group @@ -69,15 +64,10 @@ class SourceSetConfigurator(project: Project, sourceSet: SourceSet) { dependsOn(configureDeleteExternalJava) group = generateAvroJava.group } - this.externalAvroDir = project.layout.buildDirectory.dir("external-${sourceSet.name}-avro") - this.configureCopyAvro = project.task(sourceSet.getTaskName("configureCopy", EXTERNAL_AVRO_RESOURCES)) { + this.configureGenerateAvroJava = project.task(sourceSet.getTaskName("configureGenerate", AVRO_JAVA)) { group = generateAvroJava.group } - this.copyAvro = - project.tasks.create(sourceSet.getTaskName("copy", EXTERNAL_AVRO_RESOURCES), Copy::class.java) { - dependsOn(configureCopyAvro) - group = generateAvroJava.group - } + generateAvroJava.dependsOn(configureGenerateAvroJava) this.avroOutputs = generateAvroJava.outputs.files } @@ -113,28 +103,21 @@ class SourceSetConfigurator(project: Project, sourceSet: SourceSet) { avroConfiguration: Configuration ) { extendsFrom(avroConfiguration) - generateAvroJava.addSources(avroConfiguration) + addSources(avroConfiguration) configureDeleteExternalJava.configureCompilation(avroConfiguration) } - private fun GenerateAvroJavaTask.addSources( + private fun addSources( avroConfiguration: Configuration ) { - configureCopyAvro.dependsOn(avroConfiguration) - // copy external avro files to separate build directory. - // Directly adding zipTree as source breaks caching: https://github.com/gradle/gradle/issues/18382 - configureCopyAvro.doLast { - copyAvro.from( - avroConfiguration.map { file: File -> - copyAvro.project.zipTree(file) - }) { - include("**/*.avsc") + configureGenerateAvroJava.dependsOn(avroConfiguration) + configureGenerateAvroJava.doLast { + avroConfiguration.map { file: File -> + project.zipTree(file).files + }.forEach { files: Set -> + generateAvroJava.source(files) } - copyAvro.into(externalAvroDir) - copyAvro.includeEmptyDirs = false } - dependsOn(copyAvro) - source(externalAvroDir) } private fun Task.configureCompilation( diff --git a/avro/src/test/kotlin/com/bakdata/gradle/AvroPluginIntegrationTest.kt b/avro/src/test/kotlin/com/bakdata/gradle/AvroPluginIntegrationTest.kt index 998d4c0..7ea5923 100644 --- a/avro/src/test/kotlin/com/bakdata/gradle/AvroPluginIntegrationTest.kt +++ b/avro/src/test/kotlin/com/bakdata/gradle/AvroPluginIntegrationTest.kt @@ -81,12 +81,12 @@ internal class AvroPluginIntegrationTest { softly.assertThat(result.tasks) .haveExactly(1, taskWithPathAndOutcome(":configureDeleteExternalJava", TaskOutcome.SUCCESS)) .haveExactly(1, taskWithPathAndOutcome(":deleteExternalJava", TaskOutcome.SUCCESS)) - .haveExactly(1, taskWithPathAndOutcome(":configureCopyExternalAvroResources", TaskOutcome.SUCCESS)) - .haveExactly(1, taskWithPathAndOutcome(":copyExternalAvroResources", TaskOutcome.SUCCESS)) + .haveExactly(1, taskWithPathAndOutcome(":configureGenerateAvroJava", TaskOutcome.SUCCESS)) + .haveExactly(1, taskWithPathAndOutcome(":generateAvroJava", TaskOutcome.SUCCESS)) .haveExactly(1, taskWithPathAndOutcome(":configureDeleteTestExternalJava", TaskOutcome.SUCCESS)) .haveExactly(1, taskWithPathAndOutcome(":deleteTestExternalJava", TaskOutcome.SUCCESS)) - .haveExactly(1, taskWithPathAndOutcome(":configureCopyTestExternalAvroResources", TaskOutcome.SUCCESS)) - .haveExactly(1, taskWithPathAndOutcome(":copyTestExternalAvroResources", TaskOutcome.SUCCESS)) + .haveExactly(1, taskWithPathAndOutcome(":configureGenerateTestAvroJava", TaskOutcome.SUCCESS)) + .haveExactly(1, taskWithPathAndOutcome(":generateTestAvroJava", TaskOutcome.SUCCESS)) val javaClasses = testProjectDir.resolve("build/classes/java") softly.assertThat(javaClasses.resolve("main/com/bakdata/kafka/DeadLetter.class").toFile()) .doesNotExist() @@ -98,4 +98,61 @@ internal class AvroPluginIntegrationTest { .exists() } } + + @Test + fun shouldCache(@TempDir testProjectDir: Path) { + Files.writeString( + testProjectDir.resolve("build.gradle.kts"), """ + plugins { + java + id("com.bakdata.avro") + } + repositories { + mavenCentral() + } + dependencies { + avroImplementation(group = "com.bakdata.kafka", name = "error-handling", version = "1.2.2") + } + """.trimIndent() + ) + Files.writeString( + testProjectDir.resolve("gradle.properties"), """ + org.gradle.caching=true + """.trimIndent() + ) + Files.createDirectories(testProjectDir.resolve("src/main/avro/")) + Files.copy( + AvroPluginIntegrationTest::class.java.getResourceAsStream("/Record.avsc"), + testProjectDir.resolve("src/main/avro/Record.avsc") + ) + Files.createDirectories(testProjectDir.resolve("src/test/avro/")) + Files.copy( + AvroPluginIntegrationTest::class.java.getResourceAsStream("/TestRecord.avsc"), + testProjectDir.resolve("src/test/avro/TestRecord.avsc") + ) + + GradleRunner.create() + .withProjectDir(testProjectDir.toFile()) + .withArguments("build") + .withProjectPluginClassPath() + .build() + + val result = GradleRunner.create() + .withProjectDir(testProjectDir.toFile()) + .withArguments("build") + .withProjectPluginClassPath() + .build() + + SoftAssertions.assertSoftly { softly -> + softly.assertThat(result.tasks) + .haveExactly(1, taskWithPathAndOutcome(":configureDeleteExternalJava", TaskOutcome.SUCCESS)) + .haveExactly(1, taskWithPathAndOutcome(":deleteExternalJava", TaskOutcome.SUCCESS)) + .haveExactly(1, taskWithPathAndOutcome(":configureGenerateAvroJava", TaskOutcome.SUCCESS)) + .haveExactly(1, taskWithPathAndOutcome(":generateAvroJava", TaskOutcome.FROM_CACHE)) + .haveExactly(1, taskWithPathAndOutcome(":configureDeleteTestExternalJava", TaskOutcome.SUCCESS)) + .haveExactly(1, taskWithPathAndOutcome(":deleteTestExternalJava", TaskOutcome.SUCCESS)) + .haveExactly(1, taskWithPathAndOutcome(":configureGenerateTestAvroJava", TaskOutcome.SUCCESS)) + .haveExactly(1, taskWithPathAndOutcome(":generateTestAvroJava", TaskOutcome.FROM_CACHE)) + } + } } \ No newline at end of file diff --git a/avro/src/test/kotlin/com/bakdata/gradle/AvroPluginTest.kt b/avro/src/test/kotlin/com/bakdata/gradle/AvroPluginTest.kt index ab21e30..587a6d3 100644 --- a/avro/src/test/kotlin/com/bakdata/gradle/AvroPluginTest.kt +++ b/avro/src/test/kotlin/com/bakdata/gradle/AvroPluginTest.kt @@ -38,14 +38,14 @@ import org.junit.jupiter.api.Test import java.io.File internal class AvroPluginTest { - fun taskWithName(name: String): Condition = Condition({ it.name == name }, "Task with name $name") - fun configurationWithName(name: String): Condition = + private fun taskWithName(name: String): Condition = Condition({ it.name == name }, "Task with name $name") + private fun configurationWithName(name: String): Condition = Condition({ it.name == name }, "Configuration with name $name") - fun folderWithName(name: String): Condition = + private fun folderWithName(name: String): Condition = Condition({ it.path.endsWith(name.replace("/", File.separator)) }, "File with name $name") - fun Project.evaluate() { + private fun Project.evaluate() { (this as DefaultProject).evaluate() } @@ -65,12 +65,10 @@ internal class AvroPluginTest { softly.assertThat(project.tasks) .haveExactly(1, taskWithName("configureDeleteExternalJava")) .haveExactly(1, taskWithName("deleteExternalJava")) - .haveExactly(1, taskWithName("configureCopyExternalAvroResources")) - .haveExactly(1, taskWithName("copyExternalAvroResources")) + .haveExactly(1, taskWithName("configureGenerateAvroJava")) .haveExactly(1, taskWithName("configureDeleteTestExternalJava")) .haveExactly(1, taskWithName("deleteTestExternalJava")) - .haveExactly(1, taskWithName("configureCopyTestExternalAvroResources")) - .haveExactly(1, taskWithName("copyTestExternalAvroResources")) + .haveExactly(1, taskWithName("configureGenerateTestAvroJava")) softly.assertThat(project.configurations) .haveExactly(1, configurationWithName("avroImplementation")) .haveExactly(0, configurationWithName("avroApi")) @@ -110,12 +108,10 @@ internal class AvroPluginTest { softly.assertThat(project.tasks) .haveExactly(1, taskWithName("configureDeleteExternalJava")) .haveExactly(1, taskWithName("deleteExternalJava")) - .haveExactly(1, taskWithName("configureCopyExternalAvroResources")) - .haveExactly(1, taskWithName("copyExternalAvroResources")) + .haveExactly(1, taskWithName("configureGenerateAvroJava")) .haveExactly(1, taskWithName("configureDeleteTestExternalJava")) .haveExactly(1, taskWithName("deleteTestExternalJava")) - .haveExactly(1, taskWithName("configureCopyTestExternalAvroResources")) - .haveExactly(1, taskWithName("copyTestExternalAvroResources")) + .haveExactly(1, taskWithName("configureGenerateTestAvroJava")) softly.assertThat(project.configurations) .haveExactly(1, configurationWithName("avroImplementation")) .haveExactly(1, configurationWithName("avroApi"))