migrate buildSrc plugins to includedBuild plugins
This commit is contained in:
parent
805d4c8170
commit
f12a505d22
40 changed files with 159 additions and 112 deletions
|
|
@ -0,0 +1,81 @@
|
|||
package kafkatorio.tasks
|
||||
|
||||
import kafkatorio.extensions.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.provider.ProviderFactory
|
||||
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.kotlin.dsl.property
|
||||
import org.gradle.process.ExecOperations
|
||||
import org.gradle.work.NormalizeLineEndings
|
||||
import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs
|
||||
|
||||
@CacheableTask
|
||||
@Suppress("UnstableApiUsage")
|
||||
abstract class DockerComposeExec @Inject constructor(
|
||||
private val executor: ExecOperations,
|
||||
private val objects: ObjectFactory,
|
||||
private val providers: ProviderFactory,
|
||||
) : DefaultTask() {
|
||||
|
||||
@get:InputDirectory
|
||||
@get:SkipWhenEmpty
|
||||
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||
@get:NormalizeLineEndings
|
||||
abstract val dockerComposeDir: DirectoryProperty
|
||||
|
||||
@get:Input
|
||||
abstract val command: Property<String>
|
||||
|
||||
@get:Input
|
||||
val dockerIsActive: Property<Boolean> = objects.property<Boolean>().convention(
|
||||
providers.exec {
|
||||
commandLine = parseSpaceSeparatedArgs("docker info")
|
||||
isIgnoreExitValue = true
|
||||
}.result.map {
|
||||
it.exitValue == 0
|
||||
}
|
||||
)
|
||||
|
||||
@get:OutputFile
|
||||
val stateFile: RegularFileProperty = objects.fileProperty().convention {
|
||||
temporaryDir.resolve("docker-files.md5")
|
||||
}
|
||||
|
||||
init {
|
||||
group = DOCKER_COMPOSE_GROUP
|
||||
logging.captureStandardOutput(LogLevel.LIFECYCLE)
|
||||
|
||||
super.onlyIf { task ->
|
||||
require(task is DockerComposeExec)
|
||||
task.dockerIsActive.getOrElse(false)
|
||||
}
|
||||
}
|
||||
|
||||
@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,27 @@
|
|||
package kafkatorio.tasks
|
||||
|
||||
import javax.inject.Inject
|
||||
import kafkatorio.extensions.DOCKER_COMPOSE_TASK_GROUP
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.tasks.CacheableTask
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.WriteProperties
|
||||
|
||||
|
||||
@CacheableTask
|
||||
open class DockerEnvUpdateTask @Inject constructor(
|
||||
private val objects: ObjectFactory
|
||||
) : WriteProperties() {
|
||||
|
||||
@Internal
|
||||
val dotEnvFile: RegularFileProperty = objects.fileProperty()
|
||||
|
||||
init {
|
||||
group = DOCKER_COMPOSE_TASK_GROUP
|
||||
super.setOutputFile(dotEnvFile)
|
||||
super.getLogging().captureStandardOutput(LogLevel.LIFECYCLE)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package kafkatorio.tasks
|
||||
|
||||
import javax.inject.Inject
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.FileSystemOperations
|
||||
import org.gradle.api.tasks.JavaExec
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.work.DisableCachingByDefault
|
||||
|
||||
|
||||
@DisableCachingByDefault(because = "caching makes regenerating more difficult")
|
||||
abstract class GenerateTypeScriptTask @Inject constructor(
|
||||
private val fileOps: FileSystemOperations,
|
||||
) : JavaExec() {
|
||||
|
||||
@get:OutputDirectory
|
||||
abstract val output: DirectoryProperty
|
||||
|
||||
init {
|
||||
group = "kt2ts"
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun generate() {
|
||||
fileOps.delete { delete(temporaryDir) }
|
||||
temporaryDir.mkdirs()
|
||||
|
||||
super.exec()
|
||||
|
||||
fileOps.sync {
|
||||
from(temporaryDir)
|
||||
into(output)
|
||||
include("**/*.ts")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package kafkatorio.tasks
|
||||
|
||||
import kafkatorio.tasks.UpdatePackageJson.Companion.foldParseToJsonObject
|
||||
import kafkatorio.tasks.UpdatePackageJson.Companion.parseToJsonObject
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.internal.specs.ExplainingSpec
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.gradle.api.logging.Logging
|
||||
|
||||
|
||||
object JsonPropertiesUpToDateSpec : ExplainingSpec<Task> {
|
||||
|
||||
private val logger: Logger = Logging.getLogger(this::class.java)
|
||||
|
||||
override fun isSatisfiedBy(element: Task?): Boolean {
|
||||
val reason = whyUnsatisfied(element)
|
||||
|
||||
if (reason != null) {
|
||||
logger.lifecycle("JsonProperties not up to date:\n$reason")
|
||||
}
|
||||
|
||||
return reason == null
|
||||
}
|
||||
|
||||
|
||||
// Returns a description explaining why the task is outdated,
|
||||
// or null if the task is up to date
|
||||
override fun whyUnsatisfied(task: Task?): String? {
|
||||
require(task is UpdatePackageJson) { "$task is not a UpdatePackageJson task" }
|
||||
|
||||
val current = task.packageJsonFile.asFile.orNull?.parseToJsonObject()
|
||||
?: return "no package.json file"
|
||||
|
||||
val updates = task.expectedJsonUpdates.orNull?.toList()?.foldParseToJsonObject()
|
||||
?: return "no package.json updates"
|
||||
|
||||
val expected = JsonObject(current + updates)
|
||||
|
||||
if (current != expected) {
|
||||
return (current.keys + expected.keys)
|
||||
.asSequence()
|
||||
.distinct()
|
||||
.sorted()
|
||||
.mapNotNull {
|
||||
val currentVal = current[it]
|
||||
val expectedVal = expected[it]
|
||||
|
||||
if (currentVal == expectedVal) {
|
||||
null
|
||||
} else {
|
||||
"'$it' - expected:$expectedVal, actual:$currentVal"
|
||||
}
|
||||
}.joinToString(separator = "\n\t", prefix = "package.json is not up to date.\n\t")
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package kafkatorio.tasks
|
||||
|
||||
import kafkatorio.extensions.execCapture
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs
|
||||
|
||||
abstract class KafkaConsumerGroupsTask : DefaultTask() {
|
||||
|
||||
@get:Input
|
||||
val bootstrapServer: String = "localhost:9092"
|
||||
@get:Input
|
||||
val kafkaDockerContainerName: String = "kafka"
|
||||
|
||||
@get:Internal
|
||||
protected val bootstrapArg = "--bootstrap-server $bootstrapServer"
|
||||
|
||||
abstract class ResetAll : KafkaConsumerGroupsTask() {
|
||||
|
||||
@get:Input
|
||||
@Language("Shell Script")
|
||||
val resetCommand: String =
|
||||
"""
|
||||
/kafka/bin/kafka-consumer-groups.sh --execute --reset-offsets --all-topics --to-earliest $bootstrapArg
|
||||
""".trimIndent()
|
||||
|
||||
@TaskAction
|
||||
fun reset() {
|
||||
getAllGroups().forEach { group ->
|
||||
logger.lifecycle("Resetting group $group\n---")
|
||||
dockerExec("$resetCommand --group $group")
|
||||
logger.lifecycle("---")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DeleteAll : KafkaConsumerGroupsTask() {
|
||||
|
||||
@get:Input
|
||||
@Language("Shell Script")
|
||||
val deleteCommand: String =
|
||||
"""
|
||||
/kafka/bin/kafka-consumer-groups.sh --delete $bootstrapArg
|
||||
""".trimIndent()
|
||||
|
||||
@TaskAction
|
||||
fun reset() {
|
||||
val groups = getAllGroups().joinToString(" ") { group -> "--group $group" }
|
||||
dockerExec("$deleteCommand $groups")
|
||||
}
|
||||
}
|
||||
|
||||
@Internal
|
||||
protected fun getAllGroups(): List<String> = dockerExec(
|
||||
"""
|
||||
/kafka/bin/kafka-consumer-groups.sh --list $bootstrapArg
|
||||
""".trimIndent()
|
||||
).lines()
|
||||
.filter { it.trim().isNotBlank() }
|
||||
|
||||
|
||||
// fun reset(applicationId: String) = """
|
||||
// /kafka/bin/kafka-streams-application-reset.sh --application-id $applicationId --force --to-earliest
|
||||
// """.trimIndent()
|
||||
|
||||
protected fun dockerExec(
|
||||
@Language("Shell Script")
|
||||
cmd: String
|
||||
): String = project.execCapture {
|
||||
logging.captureStandardOutput(LogLevel.LIFECYCLE)
|
||||
commandLine = parseSpaceSeparatedArgs(""" docker exec $kafkaDockerContainerName $cmd """)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package kafkatorio.tasks
|
||||
|
||||
import java.io.ByteArrayOutputStream
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.internal.specs.ExplainingSpec
|
||||
import org.gradle.api.tasks.Exec
|
||||
import org.gradle.process.ExecOperations
|
||||
|
||||
/** Checks if a process is running. Windows only. */
|
||||
class ProcessRunningSpec(
|
||||
private val executor: ExecOperations,
|
||||
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? {
|
||||
return when (element) {
|
||||
null -> "task is null"
|
||||
!is Exec -> "task ${this::class.simpleName} is not ${Exec::class.simpleName}"
|
||||
else -> {
|
||||
return ByteArrayOutputStream().use { outputStream ->
|
||||
|
||||
executor.exec {
|
||||
commandLine("tasklist") // Windows only for now...
|
||||
standardOutput = outputStream
|
||||
}
|
||||
|
||||
if (outputStream.toString().contains(process, ignoreCase)) {
|
||||
null
|
||||
} else {
|
||||
"found $process in tasklist"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package kafkatorio.tasks
|
||||
|
||||
import com.github.gradle.node.npm.task.NpmTask
|
||||
import javax.inject.Inject
|
||||
import org.gradle.api.file.ConfigurableFileTree
|
||||
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.IgnoreEmptyDirectories
|
||||
import org.gradle.api.tasks.InputDirectory
|
||||
import org.gradle.api.tasks.Internal
|
||||
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.NormalizeLineEndings
|
||||
import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs
|
||||
|
||||
@CacheableTask
|
||||
abstract class TypescriptToLuaTask @Inject constructor(
|
||||
private val fs: FileSystemOperations
|
||||
) : NpmTask() {
|
||||
|
||||
@get:InputDirectory
|
||||
@get:SkipWhenEmpty
|
||||
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||
@get:NormalizeLineEndings
|
||||
@get:IgnoreEmptyDirectories
|
||||
abstract val sourceFiles: DirectoryProperty
|
||||
|
||||
@get:OutputDirectory
|
||||
abstract val outputDirectory: DirectoryProperty
|
||||
|
||||
init {
|
||||
super.setGroup(BasePlugin.BUILD_GROUP)
|
||||
super.setDescription("Convert Typescript To Lua")
|
||||
super.execOverrides { standardOutput = System.out }
|
||||
super.npmCommand.set(listOf("run", "build"))
|
||||
super.ignoreExitValue.set(false)
|
||||
super.args.set(parseSpaceSeparatedArgs("-- --outDir $temporaryDir"))
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun tstl() {
|
||||
fs.delete { delete(temporaryDir) }
|
||||
temporaryDir.mkdirs()
|
||||
|
||||
super.exec()
|
||||
|
||||
fs.sync {
|
||||
from(temporaryDir)
|
||||
into(outputDirectory)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
package kafkatorio.tasks
|
||||
|
||||
import com.github.gradle.node.NodePlugin
|
||||
import kafkatorio.*
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonObjectBuilder
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.provider.Property
|
||||
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 @Inject constructor(
|
||||
private val providers: ProviderFactory,
|
||||
) : DefaultTask(),
|
||||
ProviderFactory by providers {
|
||||
|
||||
/** Cumulative updates - will be combined one by one, then applied to [packageJsonFile] */
|
||||
@get:Input
|
||||
internal abstract val expectedJsonUpdates: ListProperty<String>
|
||||
|
||||
@get:OutputFile
|
||||
abstract val packageJsonFile: RegularFileProperty
|
||||
|
||||
|
||||
init {
|
||||
group = NodePlugin.NPM_GROUP
|
||||
description = "Update package.json properties"
|
||||
|
||||
outputs.upToDateWhen(JsonPropertiesUpToDateSpec)
|
||||
}
|
||||
|
||||
|
||||
@TaskAction
|
||||
fun exec() {
|
||||
val packageJsonFile = packageJsonFile.asFile.get()
|
||||
val expectedJsonUpdates: List<String> = expectedJsonUpdates.get().toList()
|
||||
|
||||
logger.lifecycle("updating package.json ${packageJsonFile.canonicalFile}")
|
||||
|
||||
val expectedJson = expectedJsonUpdates.fold(JsonObject(emptyMap())) { acc, update ->
|
||||
val updateJson = jsonMapper.parseToJsonElement(update).jsonObject
|
||||
JsonObject(acc + updateJson)
|
||||
}
|
||||
|
||||
val updatedPackageJson = JsonObject(
|
||||
packageJsonFile.parseToJsonObject() + expectedJson
|
||||
)
|
||||
|
||||
val packageJsonContentFormatted =
|
||||
jsonMapper
|
||||
.encodeToString(updatedPackageJson)
|
||||
|
||||
// change empty arrays/objects, because `npm install` also formats package.json,
|
||||
// but slightly differently to kxs.
|
||||
.replace(": {\n }", ": {}")
|
||||
.replace(": [\n ]", ": []")
|
||||
|
||||
.suffixIfNot("\n")
|
||||
|
||||
logger.info(packageJsonContentFormatted)
|
||||
|
||||
packageJsonFile.writer().useToRun {
|
||||
write(packageJsonContentFormatted)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Update [expectedJson] by merging [updateJsonProvider] with the existing value. */
|
||||
fun updateExpectedJson(
|
||||
expectedJsonUpdate: JsonObjectBuilder.() -> Unit
|
||||
) {
|
||||
val expectedJsonUpdateProvider = provider {
|
||||
buildJsonObject(expectedJsonUpdate).toString()
|
||||
}
|
||||
|
||||
expectedJsonUpdates.add(expectedJsonUpdateProvider)
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
private val jsonMapper = Json {
|
||||
prettyPrint = true
|
||||
prettyPrintIndent = " "
|
||||
}
|
||||
|
||||
|
||||
internal fun File.parseToJsonObject(): JsonObject =
|
||||
jsonMapper.parseToJsonElement(readText()).jsonObject
|
||||
|
||||
|
||||
internal fun Property<String>.parseToJsonObject(): JsonObject =
|
||||
jsonMapper.parseToJsonElement(get()).jsonObject
|
||||
|
||||
|
||||
internal fun List<String>.foldParseToJsonObject(): JsonObject =
|
||||
fold(JsonObject(emptyMap())) { acc, update ->
|
||||
val updateJson = jsonMapper.parseToJsonElement(update).jsonObject
|
||||
JsonObject(acc + updateJson)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue