Artículo 3: Integración de Jackson para el análisis YAML con TDD en un plugin Gradle
Publié le 25 September 2025
Introducción
En el desarrollo de plugins Gradle, la gestión de configuraciones complejas es una tarea común. En lugar de sobrecargar el DSL con cientos de propiedades, suele ser más limpio y mantenible definir la configuración en un archivo externo, como el YAML. Este artículo te guía a través de la integración de la potente biblioteca Jackson para analizar archivos YAML en objetos Kotlin, adoptando un enfoque TDD riguroso para garantizar la robustez de nuestro plugin.site-baker.
1. El Contexto : Nuestro Plugin `site-baker
Nuestro plugin`site-baker`está diseñado para automatizar la generación y el despliegue de un sitio estático. Necesita leer un archivo de configuración YAML (managed-jbake-context.yml) para obtener información como las rutas de los fuentes, los destinos de despliegue y los identificadores de Git.
La configuración YAML que queremos analizar se parece a esto:
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. Modelado de la configuración en Kotlin
Antes de parsear, debemos definir la estructura de nuestros datos en Kotlin. Jackson utilizará estas clases para mapear automáticamente el contenido 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)
La función`parseSiteConfiguration`es nuestro punto de entrada para la deserialización. Ella utiliza`ObjectMapper`de Jackson, configurado con`YAMLFactory`pour el formato YAML y`registerKotlinModule()`para el soporte de las especificidades de Kotlin (como los valores predeterminados de las propiedades).
3. Integración de Jackson en el `build.gradle.kts
Para usar Jackson, debemos agregar las dependencias necesarias en el`build.gradle.kts`de nuestro módulo`plugin` :
// 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
}
Utilizamos`jackson-module-kotlin`para el soporte de Kotlin y`jackson-dataformat-yaml`para la gestión del formato YAML.
4. El Enfoque TDD : Probar el Análisis YAML
Ahora, apliquemos el TDD para validar nuestra lógica de análisis.
4.1. Prueba unitaria: Mapear el YAML a un objeto Kotlin
Comenzamos con una prueba unitaria en`SiteBakerPluginTest.kt`para comprobar que la función`parseSiteConfiguration`puede transformar correctamente una cadena YAML en un objeto`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)
}
Esta prueba lee el contenido del archivo`managed-jbake-context.yml`(que debe existir para que la prueba sea válida) y realiza afirmaciones sobre el objeto`SiteConfiguration`resultante. Valida que los valores clave del YAML están correctamente mapeados.
4.2. Test Funcional : Validar la Lectura del Archivo de Configuración
Para asegurarnos de que el plugin pueda leer el archivo de configuración a través de su DSL y que el análisis funcione en un entorno Gradle real, agregamos una prueba funcional en`SiteBakerPluginFunctionalTest.kt`.
Esta prueba es crucial porque simula la ejecución del plugin en un proyecto real. Debe serhermético, es decir que debe crear él mismo el archivo`managed-jbake-context.yml`con un contenido controlado, para garantizar la reproducibilidad y el aislamiento del test.
// 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"))
}
Este test funcional verifica que el archivo de configuración copiado en el directorio temporal de la prueba contiene los datos esperados. Aunque este test no parsea directamente el YAML a un objeto Kotlin, valida la presencia del archivo y de su contenido, lo cual es un paso previo esencial para el parsing por el plugin.
5. Visualización del Flujo de Análisis
El siguiente diagrama ilustra el flujo de datos y las interacciones durante el análisis de la configuración YAML:
Conclusión
Siguiendo un enfoque TDD, hemos integrado con éxito la biblioteca Jackson para analizar archivos de configuración YAML en objetos Kotlin dentro de nuestro plugin Gradle. Este método nos ha permitido:
-
Modelar claramentenuestra configuración con clases de datos Kotlin.
-
Validar la lógica de análisiscon pruebas unitarias específicas.
-
Asegurar la integraciónen un entorno Gradle real gracias a pruebas funcionales herméticas.
Esta base sólida nos brinda una gran confianza para extender nuestro plugin con funcionalidades que se basen en esta configuración, al mismo tiempo que garantiza la mantenibilidad y la robustez del código. El parsing YAML ahora es una característica fiable y probada de nuestro plugin.site-baker.