All Downloads are FREE. Search and download functionalities are using the official Maven repository.

pcimcioch.gitlabci.dsl.GitlabCiDsl.kt Maven / Gradle / Ivy

There is a newer version: 1.6.0
Show newest version
package pcimcioch.gitlabci.dsl

import com.charleskorn.kaml.Yaml
import com.charleskorn.kaml.YamlConfiguration
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationStrategy
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.builtins.serializer
import pcimcioch.gitlabci.dsl.default.DefaultDsl
import pcimcioch.gitlabci.dsl.include.IncludeDsl
import pcimcioch.gitlabci.dsl.job.JobDsl
import pcimcioch.gitlabci.dsl.serializer.ValueSerializer
import pcimcioch.gitlabci.dsl.stage.StagesDsl
import pcimcioch.gitlabci.dsl.workflow.WorkflowDsl
import java.io.FileWriter
import java.io.Writer
import kotlin.collections.set

@Serializable(with = GitlabCiDsl.GitlabCiDslSerializer::class)
class GitlabCiDsl : DslBase() {
    private val jobs: MutableList = mutableListOf()
    private var stages: StagesDsl? = null
    private var default: DefaultDsl? = null
    private var workflow: WorkflowDsl? = null
    private var include: IncludeDsl? = null

    fun job(name: String, block: JobDsl.() -> Unit) = addAndReturn(jobs, JobDsl(name)).apply(block)
    operator fun JobDsl.unaryPlus() = [email protected](this)

    fun stages(block: StagesDsl.() -> Unit) = ensureStages().apply(block)
    fun stages(vararg elements: String) = stages(elements.toList())
    fun stages(elements: Iterable) = ensureStages().apply { elements.forEach { stage(it) } }

    fun default(block: DefaultDsl.() -> Unit) = ensureDefault().apply(block)

    fun workflow(block: WorkflowDsl.() -> Unit) = ensureWorkflow().apply(block)

    fun include(block: IncludeDsl.() -> Unit) = ensureInclude().apply(block)
    fun include(vararg elements: String) = include(elements.toList())
    fun include(elements: Iterable) = ensureInclude().apply { elements.forEach { local(it) } }

    fun pages(block: JobDsl.() -> Unit) = job("pages") {
        artifacts("public")
        only("master")
    }.apply(block)

    override fun validate(errors: MutableList) {
        addErrors(errors, "", workflow, stages, default, include)
        addErrors(errors, "", jobs)
    }

    private fun ensureStages() = stages ?: StagesDsl().also { stages = it }
    private fun ensureDefault() = default ?: DefaultDsl().also { default = it }
    private fun ensureWorkflow() = workflow ?: WorkflowDsl().also { workflow = it }
    private fun ensureInclude() = include ?: IncludeDsl().also { include = it }

    private fun asMap(): Map {
        val map = mutableMapOf()

        workflow?.also { map["workflow"] = it }
        include?.also { map["include"] = it }
        stages?.also { map["stages"] = it }
        default?.also { map["default"] = it }
        jobs.forEach { map[it.name] = it }

        return map
    }

    object GitlabCiDslSerializer : ValueSerializer>(MapSerializer(String.serializer(), DslBase.serializer()), GitlabCiDsl::asMap)
    companion object {
        init {
            addSerializer(GitlabCiDsl::class, serializer())
        }
    }
}

fun gitlabCi(validate: Boolean = true, writer: Writer? = null, block: GitlabCiDsl.() -> Unit) {
    val dsl = GitlabCiDsl().apply(block)

    if (validate) {
        val errors = mutableListOf()
        dsl.validate(errors)
        if (errors.isNotEmpty()) {
            throw IllegalArgumentException(errors.joinToString(
                    "\n",
                    "Configuration validation failed\n",
                    "\nValidation can be disabled by calling 'gitlabCi(validate = false) {}'"))
        }
    }

    if (writer != null) {
        serializeToYaml(GitlabCiDsl.serializer(), dsl, writer)
    } else {
        FileWriter(".gitlab-ci.yml").use {
            serializeToYaml(GitlabCiDsl.serializer(), dsl, it)
        }
    }
}

internal fun  serializeToYaml(strategy: SerializationStrategy, value: T, writer: Writer) {
    val config = YamlConfiguration(encodeDefaults = false)
    val yaml = Yaml(configuration = config)

    val yamlString = yaml.stringify(strategy, value)
    writer.write(yamlString)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy