阅读时间 : 12 分钟。

目标受众:希望管理复杂配置的中级 Gradle 开发者。

介绍

在开发Gradle插件时,管理复杂配置是一项常见任务。与其在DSL中堆砌数百个属性,不如将配置定义在外部文件中(如YAML)更为简洁且易于维护。本文将引导您使用强大的Jackson库将YAML文件解析为Kotlin对象,并采用严格的TDD方法以确保插件的健壮性。site-baker。

1. 上下文:我们的插件 `site-baker

我们的插件`site-baker`旨在自动化静态站点的生成和部署。它需要读取一个 YAML 配置文件 (managed-jbake-context.yml) 以获取诸如源代码路径、部署目标和 Git 标识符等信息。

我们希望解析的YAML配置看起来像这样:

bake:
  srcPath: "./site/jbake"
  destDirPath: "bake"
  cname: "cheroliv.com"
pushPage:
  from: "bake"
  to: "cvs"
  repo:
    name: "trainings"
    repository: "https://github.com/pages-content/pages-content.github.io.git"
    credentials:
      username: "USERNAME"
      password: "SECRET_TOKEN"
  branch: "main"
  message: "cheroliv.com"
# ... autres configurations (pushMaquette, supabase, etc.)

2. Kotlin 中的配置建模

在解析之前,我们需要用 Kotlin 定义数据的结构。Jackson 将使用这些类自动映射 YAML 内容。

// plugin/src/main/kotlin/com/cheroliv/site/baker/data/SiteConfiguration.kt
package com.cheroliv.site.baker.data

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.module.kotlin.readValue
import com.fasterxml.jackson.module.kotlin.registerKotlinModule

fun parseSiteConfiguration(yaml: String): SiteConfiguration {
    val mapper = ObjectMapper(YAMLFactory()).registerKotlinModule()
    return mapper.readValue(yaml)
}

data class GitPushConfiguration(
    val from: String = "",
    val to: String = "",
    val repo: RepositoryConfiguration = RepositoryConfiguration(),
    val branch: String = "",
    val message: String = "",
)

data class RepositoryConfiguration(
    val name: String = "",
    val repository: String = "",
    val credentials: RepositoryCredentials = RepositoryCredentials(),
) {
    companion object {
        const val ORIGIN = "origin"
        const val CNAME = "CNAME"
        const val REMOTE = "remote"
    }
}

data class RepositoryCredentials(val username: String = "", val password: String = "")

data class SiteConfiguration(
    val bake: BakeConfiguration = BakeConfiguration(),
    val pushPage: GitPushConfiguration = GitPushConfiguration(),
    val pushMaquette: GitPushConfiguration = GitPushConfiguration(),
    val pushSource: GitPushConfiguration? = null,
    val pushTemplate: GitPushConfiguration? = null,
    val supabase: SupabaseContactFormConfig? = null
)

data class BakeConfiguration(
    val srcPath: String = "",
    val destDirPath: String = "",
    val cname: String? = null,
)

// ... (autres data classes pour Supabase, si nécessaire)

函数`parseSiteConfiguration`这是我们的反序列化入口点。它使用`ObjectMapper`Jackson 的, 配置为`YAMLFactory`用于 YAML 格式和`registerKotlinModule()`用于支持 Kotlin 的特性(如属性的默认值)。

3. 在 build.gradle.kts 中集成 Jackson

要使用 Jackson,我们需要在 中添加必要的依赖项`build.gradle.kts`我们的模块的`plugin`[Empty string]

// plugin/build.gradle.kts
dependencies {
    // Jackson for YAML parsing
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.18.3")
    implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.3")

    // ... autres dépendances
}

我们使用`jackson-module-kotlin`用于 Kotlin 支持和`jackson-dataformat-yaml`用于管理 YAML 格式。

4. TDD方法:测试YAML解析

现在,让我们应用TDD来验证我们的解析逻辑。

4.1. 单元测试 : 将 YAML 映射为 Kotlin 对象

我们从单元测试开始,在`SiteBakerPluginTest.kt`为验证该函数`parseSiteConfiguration`可以正确地将 YAML 字符串转换为对象`SiteConfiguration`。

// plugin/src/test/kotlin/com/cheroliv/site/baker/SiteBakerPluginTest.kt
@Test
fun `can map configuration text to SiteConfiguration object`() {
    val yamlString = "../../managed-jbake-context.yml"
        .run(::File)
        .readText()
        .trimIndent()

    val config: SiteConfiguration = parseSiteConfiguration(yamlString)

    assertEquals("cheroliv.com", config.bake.cname)
    assertEquals("main", config.pushPage.branch)
    assertEquals("https://github.com/pages-content/pages-content.github.io.git", config.pushPage.repo.repository)
}

此测试读取文件的内容`managed-jbake-context.yml`(必须存在才能使测试有效)并对对象执行断言`SiteConfiguration`生成的。它验证 YAML 中的键值是否正确映射。

4.2. 功能测试:验证配置文件的读取

为了确保插件能够通过其 DSL 读取配置文件,并且在真实的 Gradle 环境中解析正常工作,我们添加了一个功能测试到`SiteBakerPluginFunctionalTest.kt`。

此测试至关重要,因为它在真实项目中模拟了插件的执行。它必须密封的, 也就是说,他必须自己创建该文件`managed-jbake-context.yml`� 带有受控内容,以确保测试的可重复性和隔离性。

// plugin/src/functionalTest/kotlin/com/cheroliv/site/baker/SiteBakerPluginFunctionalTest.kt
@Test
fun `config file contains good data`(){
    val configContent = configFile.readText(UTF_8)
    // Vérifications comme dans vos commentaires
    assertTrue(configContent.contains("bake"))
    assertTrue(configContent.contains("pushPage"))
    assertTrue(configContent.contains("repository"))
}

此功能测试验证复制到测试临时目录的配置文件包含预期的数据。尽管此测试不会直接将 YAML 解析为 Kotlin 对象,但它验证了文件及其内容的存在,这是插件解析之前必不可少的前置步骤。

5. 解析流可视化

下图说明了在解析YAML配置时的数据流和交互:

Diagram

结论

通过采用 TDD 方法,我们成功地在 Gradle 插件中集成了 Jackson 库,以将 YAML 配置文件解析为 Kotlin 对象。此方法使我们能够:

  • 清晰地建模我们的配置使用 Kotlin 数据类。

  • 验证解析逻辑带有有针对性的单元测试。

  • 确保集成在真实的 Gradle 环境中,通过密闭的功能测试。

这个坚实的基础让我们有信心在插件上扩展功能,这些功能建立在此配置之上,同时保证代码的可维护性和健壮性。YAML 解析现在已成为我们插件的一个可靠且经过测试的功能。site-baker。

相关文章