enable gradle build cache, and improve tasks
This commit is contained in:
parent
f339333f76
commit
b81e62e2fd
17 changed files with 330 additions and 200 deletions
|
|
@ -1,60 +1,30 @@
|
|||
package dev.adamko.kafkatorio.gradle
|
||||
|
||||
import dev.adamko.kafkatorio.jsonMapper
|
||||
import java.io.ByteArrayOutputStream
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.file.Directory
|
||||
import org.gradle.api.file.ProjectLayout
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.MapProperty
|
||||
import org.gradle.api.specs.NotSpec
|
||||
import org.gradle.api.specs.Spec
|
||||
import org.gradle.kotlin.dsl.invoke
|
||||
import org.gradle.plugins.ide.idea.model.IdeaModule
|
||||
import org.gradle.process.ExecSpec
|
||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension
|
||||
|
||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.yarn
|
||||
|
||||
operator fun <T> Spec<T>.not(): Spec<T> = Spec<T> { !this(it) }
|
||||
import org.jetbrains.kotlin.incremental.md5
|
||||
|
||||
|
||||
fun Project.isProcessRunning(process: String, ignoreCase: Boolean = true): Spec<Task> =
|
||||
Spec<Task> {
|
||||
ByteArrayOutputStream().use { outputStream ->
|
||||
project.exec {
|
||||
commandLine("tasklist") // Windows only for now...
|
||||
standardOutput = outputStream
|
||||
}
|
||||
outputStream.toString()
|
||||
.contains(process, ignoreCase)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun Project.areJsonPropertiesUpToDate(
|
||||
packageJsonFile: RegularFileProperty,
|
||||
properties: MapProperty<String, String>
|
||||
): Spec<Task> = Spec<Task> {
|
||||
val packageJsonContent = packageJsonFile.get().asFile.readText()
|
||||
val packageJson = jsonMapper.parseToJsonElement(packageJsonContent).jsonObject
|
||||
|
||||
properties.get().all { (key, expectedVal) ->
|
||||
val actualVal = packageJson[key]?.jsonPrimitive?.content
|
||||
val isUpToDate = expectedVal == actualVal
|
||||
|
||||
if (isUpToDate) {
|
||||
logger.info("package.json property is up to date, '$key = $actualVal'")
|
||||
} else {
|
||||
logger.lifecycle(
|
||||
"package.json has outdated property '$key' (expected: $expectedVal, actual: $actualVal)"
|
||||
)
|
||||
}
|
||||
|
||||
isUpToDate
|
||||
}
|
||||
}
|
||||
operator fun <T> Spec<T>.not(): NotSpec<T> = NotSpec(this)
|
||||
//
|
||||
//
|
||||
//fun isProcessRunning(process: String, ignoreCase: Boolean = true): Spec<Task> =
|
||||
// Spec<Task> {
|
||||
// ByteArrayOutputStream().use { outputStream ->
|
||||
// project.exec {
|
||||
// }
|
||||
// outputStream.toString().contains(process, ignoreCase)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
|
||||
/** exclude generated Gradle code, so it doesn't clog up search results */
|
||||
|
|
@ -91,3 +61,10 @@ fun Project.execCapture(spec: ExecSpec.() -> Unit): String {
|
|||
|
||||
/** https://youtrack.jetbrains.com/issue/KT-50848 */
|
||||
fun Project.yarn(configure: YarnRootExtension.() -> Unit) = with(yarn, configure)
|
||||
|
||||
|
||||
fun Directory.filesChecksum() = asFileTree
|
||||
.files
|
||||
.map { it.readBytes() + it.absolutePath.toByteArray() }
|
||||
.fold(byteArrayOf()) { acc, bytes -> acc + bytes }
|
||||
.md5()
|
||||
|
|
|
|||
|
|
@ -8,12 +8,6 @@ plugins {
|
|||
kotlin("jvm")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain {
|
||||
(this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(Versions.jvmTarget))
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
|
||||
|
|
@ -40,22 +34,27 @@ tasks.withType<KotlinCompile>().configureEach {
|
|||
jvmTarget = Versions.jvmTarget
|
||||
apiVersion = Versions.kotlinLang
|
||||
languageVersion = Versions.kotlinLang
|
||||
}
|
||||
|
||||
kotlinOptions.freeCompilerArgs += listOf(
|
||||
freeCompilerArgs += listOf(
|
||||
// "-Xcontext-receivers",
|
||||
"-opt-in=kotlin.RequiresOptIn",
|
||||
"-opt-in=kotlin.ExperimentalStdlibApi",
|
||||
"-opt-in=kotlin.time.ExperimentalTime",
|
||||
"-opt-in=kotlin.RequiresOptIn",
|
||||
"-opt-in=kotlin.ExperimentalStdlibApi",
|
||||
"-opt-in=kotlin.time.ExperimentalTime",
|
||||
// "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||
// "-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
tasks.compileTestKotlin {
|
||||
kotlinOptions.freeCompilerArgs += "-opt-in=io.kotest.common.ExperimentalKotest"
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain {
|
||||
(this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(Versions.jvmTarget))
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<Test> {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,8 @@
|
|||
package dev.adamko.kafkatorio.lang
|
||||
|
||||
import com.github.gradle.node.NodePlugin
|
||||
import com.github.gradle.node.npm.task.NpmInstallTask
|
||||
import dev.adamko.kafkatorio.Versions
|
||||
import dev.adamko.kafkatorio.gradle.areJsonPropertiesUpToDate
|
||||
import dev.adamko.kafkatorio.jsonMapper
|
||||
import dev.adamko.kafkatorio.task.UpdatePackageJson
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import org.gradle.kotlin.dsl.support.useToRun
|
||||
import org.jetbrains.kotlin.util.suffixIfNot
|
||||
|
||||
plugins {
|
||||
id("com.github.node-gradle.node")
|
||||
|
|
@ -26,34 +17,34 @@ node {
|
|||
}
|
||||
|
||||
val updatePackageJson by tasks.registering(UpdatePackageJson::class) {
|
||||
group = NodePlugin.NODE_GROUP
|
||||
description = "Read the package.json file and update the version and name, based on the project."
|
||||
// group = NodePlugin.NODE_GROUP
|
||||
// description = "Read the package.json file and update the version and name, based on the project."
|
||||
|
||||
propertiesToCheck.put("version", "${project.version}")
|
||||
propertiesToCheck.put("version", providers.provider { "${project.version}" })
|
||||
|
||||
// check to see if the properties are already up-to-date
|
||||
outputs.upToDateWhen(areJsonPropertiesUpToDate(packageJsonFile, propertiesToCheck))
|
||||
// outputs.upToDateWhen(areJsonPropertiesUpToDate(packageJsonFile, propertiesToCheck))
|
||||
// onlyIf(!areJsonPropertiesUpToDate(packageJsonFile, propertiesToCheck))
|
||||
|
||||
doLast {
|
||||
val packageJsonContent = packageJsonFile.get().asFile.readText()
|
||||
val packageJson = jsonMapper.parseToJsonElement(packageJsonContent).jsonObject
|
||||
|
||||
val newJsonProps = propertiesToCheck.get().mapValues { (_, newVal) -> JsonPrimitive(newVal) }
|
||||
|
||||
val packageJsonUpdate = JsonObject(packageJson + newJsonProps)
|
||||
val packageJsonContentUpdated =
|
||||
jsonMapper
|
||||
.encodeToString(packageJsonUpdate)
|
||||
.suffixIfNot("\n")
|
||||
|
||||
logger.debug(packageJsonContentUpdated)
|
||||
|
||||
packageJsonFile.get().asFile.writer().useToRun {
|
||||
write(packageJsonContentUpdated)
|
||||
}
|
||||
|
||||
}
|
||||
// doLast {
|
||||
// val packageJsonContent = packageJsonFile.get().asFile.readText()
|
||||
// val packageJson = jsonMapper.parseToJsonElement(packageJsonContent).jsonObject
|
||||
//
|
||||
// val newJsonProps = propertiesToCheck.get().mapValues { (_, newVal) -> JsonPrimitive(newVal) }
|
||||
//
|
||||
// val packageJsonUpdate = JsonObject(packageJson + newJsonProps)
|
||||
// val packageJsonContentUpdated =
|
||||
// jsonMapper
|
||||
// .encodeToString(packageJsonUpdate)
|
||||
// .suffixIfNot("\n")
|
||||
//
|
||||
// logger.debug(packageJsonContentUpdated)
|
||||
//
|
||||
// packageJsonFile.get().asFile.writer().useToRun {
|
||||
// write(packageJsonContentUpdated)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
tasks.assemble { dependsOn(updatePackageJson) }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
package dev.adamko.kafkatorio.task
|
||||
|
||||
import dev.adamko.kafkatorio.gradle.filesChecksum
|
||||
import javax.inject.Inject
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.CacheableTask
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputDirectory
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.PathSensitive
|
||||
import org.gradle.api.tasks.PathSensitivity
|
||||
import org.gradle.api.tasks.SkipWhenEmpty
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.process.ExecOperations
|
||||
import org.gradle.work.Incremental
|
||||
import org.gradle.work.NormalizeLineEndings
|
||||
import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs
|
||||
|
||||
@CacheableTask
|
||||
abstract class DockerComposeExec @Inject constructor(
|
||||
private val executor: ExecOperations,
|
||||
private val objectFactory: ObjectFactory,
|
||||
) : DefaultTask() {
|
||||
|
||||
@get:InputDirectory
|
||||
@get:SkipWhenEmpty
|
||||
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||
@get:NormalizeLineEndings
|
||||
abstract val dockerComposeDir: DirectoryProperty
|
||||
|
||||
@get:Input
|
||||
abstract val command: Property<String>
|
||||
|
||||
@get:OutputFile
|
||||
val stateFile: RegularFileProperty = objectFactory.fileProperty().convention {
|
||||
temporaryDir.resolve("docker-files.md5")
|
||||
}
|
||||
|
||||
init {
|
||||
group = DOCKER_COMPOSE_GROUP
|
||||
logging.captureStandardOutput(LogLevel.LIFECYCLE)
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun exec() {
|
||||
executor.exec {
|
||||
workingDir = dockerComposeDir.asFile.get()
|
||||
commandLine = parseSpaceSeparatedArgs(command.get())
|
||||
}
|
||||
|
||||
val inputChecksum = dockerComposeDir.get().filesChecksum()
|
||||
stateFile.get().asFile.writeText("$inputChecksum")
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DOCKER_COMPOSE_GROUP: String = "docker-compose"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package dev.adamko.kafkatorio.task
|
||||
|
||||
import dev.adamko.kafkatorio.jsonMapper
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.internal.specs.ExplainingSpec
|
||||
|
||||
object JsonPropertiesUpToDateSpec : ExplainingSpec<Task> {
|
||||
|
||||
override fun isSatisfiedBy(element: Task?): Boolean = whyUnsatisfied(element) == null
|
||||
|
||||
|
||||
// Returns a description explaining why the task is outdated,
|
||||
// or null if the task is up to date
|
||||
override fun whyUnsatisfied(element: Task?): String? = with(element) {
|
||||
when (this) {
|
||||
null -> "task is null"
|
||||
|
||||
!is UpdatePackageJson ->
|
||||
"task ${this::class.simpleName} is not instance of ${UpdatePackageJson::class.simpleName}"
|
||||
|
||||
else -> {
|
||||
|
||||
val packageJsonContent = packageJsonFile.get().asFile.readText()
|
||||
val packageJson = jsonMapper.parseToJsonElement(packageJsonContent).jsonObject
|
||||
|
||||
val outdatedProperties = propertiesToCheck.get().mapNotNull { (key, expectedVal) ->
|
||||
val actualVal = packageJson[key]?.jsonPrimitive?.content
|
||||
when {
|
||||
expectedVal == actualVal -> null
|
||||
else -> "'$key' (expected: $expectedVal, actual: $actualVal)"
|
||||
}
|
||||
}
|
||||
|
||||
when {
|
||||
outdatedProperties.isEmpty() -> null
|
||||
outdatedProperties.size == 1 ->
|
||||
"package.json has outdated property: ${outdatedProperties.single()}"
|
||||
else ->
|
||||
"package.json has outdated properties: ${outdatedProperties.joinToString(", ")}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package dev.adamko.kafkatorio.task
|
||||
|
||||
import java.io.ByteArrayOutputStream
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.internal.specs.ExplainingSpec
|
||||
import org.gradle.api.tasks.Exec
|
||||
|
||||
/** Checks if a process is running. Windows only. */
|
||||
class ProcessRunningSpec(
|
||||
private val process: String,
|
||||
private val ignoreCase: Boolean = true,
|
||||
) : ExplainingSpec<Task> {
|
||||
|
||||
override fun isSatisfiedBy(element: Task?): Boolean = whyUnsatisfied(element) == null
|
||||
|
||||
override fun whyUnsatisfied(element: Task?): String? = with(element) {
|
||||
|
||||
when (this) {
|
||||
null -> "task is null"
|
||||
!is Exec -> "task ${this::class.simpleName} is not ${Exec::class.simpleName}"
|
||||
else -> {
|
||||
return ByteArrayOutputStream().use { outputStream ->
|
||||
|
||||
project.exec {
|
||||
commandLine("tasklist") // Windows only for now...
|
||||
standardOutput = outputStream
|
||||
}
|
||||
|
||||
if (outputStream.toString().contains(process, ignoreCase)) {
|
||||
"found $process in tasklist"
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +1,35 @@
|
|||
package dev.adamko.kafkatorio.task
|
||||
|
||||
import com.github.gradle.node.npm.task.NpmTask
|
||||
import javax.inject.Inject
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.FileSystemOperations
|
||||
import org.gradle.api.plugins.BasePlugin
|
||||
import org.gradle.api.tasks.CacheableTask
|
||||
import org.gradle.api.tasks.InputDirectory
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.PathSensitive
|
||||
import org.gradle.api.tasks.PathSensitivity
|
||||
import org.gradle.api.tasks.SkipWhenEmpty
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.work.Incremental
|
||||
import org.gradle.work.NormalizeLineEndings
|
||||
import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs
|
||||
|
||||
@CacheableTask
|
||||
abstract class TypescriptToLuaTask : NpmTask() {
|
||||
|
||||
@get:InputDirectory
|
||||
@get:SkipWhenEmpty
|
||||
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||
@Suppress("UnstableApiUsage")
|
||||
@get:NormalizeLineEndings
|
||||
abstract val sourceFiles: DirectoryProperty
|
||||
|
||||
@get:OutputDirectory
|
||||
abstract val outputDirectory: DirectoryProperty
|
||||
|
||||
@get:Inject
|
||||
abstract val fs: FileSystemOperations
|
||||
|
||||
init {
|
||||
super.setGroup(BasePlugin.BUILD_GROUP)
|
||||
|
|
@ -33,4 +40,17 @@ abstract class TypescriptToLuaTask : NpmTask() {
|
|||
super.args.set(parseSpaceSeparatedArgs("-- --outDir $temporaryDir"))
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun tstl() {
|
||||
fs.delete { delete(temporaryDir) }
|
||||
temporaryDir.mkdirs()
|
||||
|
||||
super.exec()
|
||||
|
||||
fs.sync {
|
||||
from(temporaryDir)
|
||||
into(outputDirectory)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,24 @@
|
|||
package dev.adamko.kafkatorio.task
|
||||
|
||||
import com.github.gradle.node.NodePlugin
|
||||
import dev.adamko.kafkatorio.jsonMapper
|
||||
import javax.inject.Inject
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.MapProperty
|
||||
import org.gradle.api.provider.ProviderFactory
|
||||
import org.gradle.api.tasks.CacheableTask
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.kotlin.dsl.support.useToRun
|
||||
import org.jetbrains.kotlin.util.suffixIfNot
|
||||
|
||||
@CacheableTask
|
||||
abstract class UpdatePackageJson : DefaultTask() {
|
||||
|
||||
@get:Input
|
||||
|
|
@ -14,10 +27,43 @@ abstract class UpdatePackageJson : DefaultTask() {
|
|||
@get:OutputFile
|
||||
abstract val packageJsonFile: RegularFileProperty
|
||||
|
||||
@get:Inject
|
||||
abstract val providers: ProviderFactory
|
||||
//
|
||||
// @get:Inject
|
||||
// abstract val fs: FileSystemOperations
|
||||
|
||||
init {
|
||||
group = NodePlugin.NODE_GROUP
|
||||
description = "Read the package.json file and update the version and name, based on the project."
|
||||
|
||||
outputs.upToDateWhen(JsonPropertiesUpToDateSpec)
|
||||
|
||||
super.doFirst {
|
||||
propertiesToCheck.disallowChanges()
|
||||
packageJsonFile.disallowChanges()
|
||||
}
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun exec() {
|
||||
val pj = packageJsonFile.asFile.get()
|
||||
|
||||
logger.info("updating package.json ${pj.canonicalPath}")
|
||||
val packageJson = jsonMapper.parseToJsonElement(pj.readText()).jsonObject
|
||||
|
||||
val newJsonProps = propertiesToCheck.get().mapValues { (_, newVal) -> JsonPrimitive(newVal) }
|
||||
|
||||
val packageJsonUpdate = JsonObject(packageJson + newJsonProps)
|
||||
val packageJsonContentUpdated =
|
||||
jsonMapper
|
||||
.encodeToString(packageJsonUpdate)
|
||||
.suffixIfNot("\n")
|
||||
|
||||
logger.debug(packageJsonContentUpdated)
|
||||
|
||||
packageJsonFile.get().asFile.writer().useToRun {
|
||||
write(packageJsonContentUpdated)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue