migrate docker-compose convention plugin out of buildSrc
This commit is contained in:
parent
105555bf6c
commit
f804c39a3b
32 changed files with 564 additions and 239 deletions
|
|
@ -1,8 +1,9 @@
|
|||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version embeddedKotlinVersion
|
||||
`kotlin-dsl`
|
||||
id("kafkatorio.conventions.kotlin-dsl")
|
||||
// kotlin("jvm") version embeddedKotlinVersion
|
||||
// `kotlin-dsl`
|
||||
`java-gradle-plugin`
|
||||
}
|
||||
|
||||
|
|
@ -13,17 +14,17 @@ dependencies {
|
|||
implementation("org.jetbrains.kotlin:kotlin-compiler-embeddable")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain {
|
||||
(this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(gradleJvmTarget))
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile>().configureEach {
|
||||
kotlinOptions {
|
||||
jvmTarget = gradleJvmTarget
|
||||
}
|
||||
}
|
||||
//kotlin {
|
||||
// jvmToolchain {
|
||||
// (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(gradleJvmTarget))
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//tasks.withType<KotlinCompile>().configureEach {
|
||||
// kotlinOptions {
|
||||
// jvmTarget = gradleJvmTarget
|
||||
// }
|
||||
//}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
package dev.adamko.geedeecee
|
||||
|
||||
import javax.inject.Inject
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.Directory
|
||||
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.incremental.md5
|
||||
import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs
|
||||
|
||||
|
||||
// look into using 'build context' for up-to-date check
|
||||
// https://stackoverflow.com/questions/38946683/how-to-test-dockerignore-file
|
||||
// https://github.com/pwaller/docker-show-context
|
||||
// https://snippets.khromov.se/see-which-files-are-included-in-your-docker-build-context/
|
||||
|
||||
|
||||
@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"
|
||||
|
||||
|
||||
private fun Directory.filesChecksum(): Long = asFileTree
|
||||
.files
|
||||
.map { it.readBytes() + it.absolutePath.toByteArray() }
|
||||
.fold(byteArrayOf()) { acc, bytes -> acc + bytes }
|
||||
.md5()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package dev.adamko.geedeecee
|
||||
|
||||
import javax.inject.Inject
|
||||
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(
|
||||
objects: ObjectFactory
|
||||
) : WriteProperties() {
|
||||
|
||||
@Internal
|
||||
// internal and not abstract so that it can delegate to `super.outputFile` in `init {}`
|
||||
val dotEnvFile: RegularFileProperty = objects.fileProperty()
|
||||
|
||||
init {
|
||||
group = GDCPlugin.GCD_TASK_GROUP
|
||||
super.setOutputFile(dotEnvFile)
|
||||
super.getLogging().captureStandardOutput(LogLevel.LIFECYCLE)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package dev.adamko.geedeecee
|
||||
|
||||
import javax.inject.Inject
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputDirectory
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.process.ExecOperations
|
||||
import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs
|
||||
|
||||
abstract class GDCCommandTask @Inject constructor(
|
||||
private val executor: ExecOperations
|
||||
) : DefaultTask() {
|
||||
|
||||
init {
|
||||
super.setGroup(GDCPlugin.GCD_TASK_GROUP)
|
||||
description = "Run a docker-compose command."
|
||||
|
||||
logging.captureStandardOutput(LogLevel.LIFECYCLE)
|
||||
}
|
||||
|
||||
@get:InputDirectory
|
||||
abstract val workingDir: DirectoryProperty
|
||||
|
||||
@get:Input
|
||||
abstract val separatedArgs: ListProperty<String>
|
||||
|
||||
@TaskAction
|
||||
fun dockerCompose() {
|
||||
val separatedArgs: List<String> = separatedArgs.get()
|
||||
|
||||
executor.exec {
|
||||
workingDir(this@GDCCommandTask.workingDir)
|
||||
commandLine(separatedArgs)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
fun `docker-compose`(args: String) {
|
||||
separatedArgs.addAll(
|
||||
parseSpaceSeparatedArgs("docker-compose $args")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,17 @@
|
|||
package dev.adamko.geedeecee
|
||||
|
||||
import javax.inject.Inject
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.file.ProjectLayout
|
||||
import org.gradle.api.provider.ProviderFactory
|
||||
import org.gradle.kotlin.dsl.create
|
||||
import org.gradle.api.logging.*
|
||||
import org.gradle.api.provider.*
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||
import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs
|
||||
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
abstract class GDCPlugin @Inject constructor(
|
||||
private val providers: ProviderFactory,
|
||||
private val layout: ProjectLayout,
|
||||
|
|
@ -16,27 +19,78 @@ abstract class GDCPlugin @Inject constructor(
|
|||
|
||||
|
||||
override fun apply(target: Project) {
|
||||
target.createSettings()
|
||||
target.plugins.apply(LifecycleBasePlugin::class)
|
||||
|
||||
val gdcSettings = target.createSettings()
|
||||
|
||||
val dockerComposeEnvUpdate by target.tasks.registering(DockerEnvUpdateTask::class) {
|
||||
dotEnvFile.set(gdcSettings.srcDir.file(".env"))
|
||||
|
||||
// properties(
|
||||
// "COMPOSE_PROJECT_NAME" to gdcSettings.composeProjectName,
|
||||
// "KAFKATORIO_VERSION" to gdcSettings.composeProjectVersion,
|
||||
// "REGISTRY_HOST" to providers.gradleProperty("dockerContainerRegistryHost"),
|
||||
// )
|
||||
}
|
||||
|
||||
val dockerComposeUp by target.tasks.registering(GDCCommandTask::class) {
|
||||
`docker-compose`("up -d")
|
||||
}
|
||||
val dockerComposeDown by target.tasks.registering(GDCCommandTask::class) {
|
||||
`docker-compose`("down")
|
||||
}
|
||||
val dockerComposeStop by target.tasks.registering(GDCCommandTask::class) {
|
||||
`docker-compose`("stop")
|
||||
}
|
||||
val dockerComposeBuild by target.tasks.registering(GDCCommandTask::class) {
|
||||
`docker-compose`("build")
|
||||
}
|
||||
val dockerComposeRemove by target.tasks.registering(GDCCommandTask::class) {
|
||||
`docker-compose`("rm --stop -v -f")
|
||||
}
|
||||
|
||||
dockerComposeUp.configure { dependsOn(dockerComposeBuild) }
|
||||
dockerComposeRemove.configure { dependsOn(dockerComposeDown) }
|
||||
|
||||
target.tasks.withType<GDCCommandTask>().configureEach {
|
||||
workingDir.convention(gdcSettings.srcDir)
|
||||
dependsOn(dockerComposeEnvUpdate)
|
||||
}
|
||||
|
||||
val assembleTasks = target.tasks.matching { LifecycleBasePlugin.ASSEMBLE_TASK_NAME == it.name }
|
||||
|
||||
assembleTasks.configureEach {
|
||||
dependsOn(dockerComposeEnvUpdate)
|
||||
}
|
||||
|
||||
dockerComposeUp.configure {
|
||||
dependsOn(assembleTasks)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun Project.createSettings(): GDCSettings =
|
||||
extensions.create<GDCSettings>(GDC_EXTENSION_NAME).apply {
|
||||
composeProjectName.convention(providers.provider { project.name })
|
||||
composeProjectVersion.convention(providers.provider { project.name })
|
||||
containerRegistryHost.convention(providers.gradleProperty("dockerContainerRegistryHost"))
|
||||
srcDir.convention(layout.projectDirectory.dir("docker"))
|
||||
|
||||
dotEnv.put("COMPOSE_PROJECT_NAME", composeProjectName)
|
||||
dotEnv.put("PROJECT_VERSION", providers.provider { project.version.toString() })
|
||||
dotEnv.put("REGISTRY_HOST", providers.gradleProperty("dockerContainerRegistryHost"))
|
||||
dotEnv.put("PROJECT_VERSION", composeProjectVersion)
|
||||
dotEnv.put("REGISTRY_HOST", containerRegistryHost)
|
||||
|
||||
enabled.convention(
|
||||
providers.exec {
|
||||
commandLine = parseSpaceSeparatedArgs("docker info")
|
||||
isIgnoreExitValue = true
|
||||
}.result.map {
|
||||
it.exitValue == 0
|
||||
}
|
||||
)
|
||||
enabled.convention(isDockerActive())
|
||||
}
|
||||
|
||||
|
||||
private fun isDockerActive(): Provider<Boolean> =
|
||||
providers.exec {
|
||||
commandLine = parseSpaceSeparatedArgs("docker info")
|
||||
isIgnoreExitValue = true
|
||||
}.result.map {
|
||||
it.exitValue == 0
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@ interface GDCSettings {
|
|||
@get:Input
|
||||
val composeProjectName: Property<String>
|
||||
|
||||
@get:Input
|
||||
val composeProjectVersion: Property<String>
|
||||
|
||||
@get:Input
|
||||
val containerRegistryHost: Property<String>
|
||||
|
||||
@get:Internal
|
||||
val srcDir: DirectoryProperty
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue