Introdução

Público-alvo : Desenvolvedores Gradle intermediários que desejam gerenciar configurações complexas.

No desenvolvimento de plugins Gradle, a gestão de configurações complexas é uma tarefa comum. Em vez de sobrecarregar o DSL com centenas de propriedades, costuma ser mais limpo e manutenível definir a configuração em um arquivo externo, como o YAML. Este artigo guia você através da integração da poderosa biblioteca Jackson para analisar arquivos YAML em objetos Kotlin, adotando uma abordagem TDD rigorosa para garantir a robustez do nosso plugin.site-baker.

O Contexto: Nosso Plugin `site-baker

Nosso plugin`site-baker`é projetado para automatizar a geração e a implantação de um site estático. Ele precisa ler um arquivo de configuração YAML(managed-jbake-context.yml) para obter informações como os caminhos das fontes, os destinos de implantação e os identificadores Git.

A configuração YAML que queremos analisar é assim:

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. Modelagem da Configuração em Kotlin

Antes de analisar, devemos definir a estrutura dos nossos dados em Kotlin. Jackson usará estas classes para mapear automaticamente o conteúdo 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)

A função`parseSiteConfiguration`é o nosso ponto de entrada para a desserialização. Ela utiliza`ObjectMapper`de Jackson, configurado com`YAMLFactory`para o formato YAML e`registerKotlinModule()`para o suporte às especificidades do Kotlin (como os valores padrão das propriedades).

3. Integração de Jackson no `build.gradle.kts

Para usar o Jackson, devemos adicionar as dependências necessárias no`build.gradle.kts`do nosso 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 o suporte de Kotlin e`jackson-dataformat-yaml`para a gestão do formato YAML.

4. A Abordagem TDD: Testando o parsing YAML

Agora, vamos aplicar o TDD para validar nossa lógica de análise.

4.1. Teste Unitário: Mapear o YAML para Objeto Kotlin

Começamos com um teste unitário em`SiteBakerPluginTest.kt`para verificar que a função`parseSiteConfiguration`pode transformar corretamente uma string YAML em um 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)
}

Este teste lê o conteúdo do arquivo`managed-jbake-context.yml`(que deve existir para que o teste seja válido) e faz asserções sobre o objeto`SiteConfiguration`resultante. Ele valida que os valores-chave do YAML estão corretamente mapeados.

4.2. Teste Funcional: Validar a Leitura do Arquivo de Configuração

Para garantir que o plugin possa ler o arquivo de configuração via seu DSL e que a análise funcione em um ambiente Gradle real, adicionamos um teste funcional em`SiteBakerPluginFunctionalTest.kt`.

Este teste é crucial porque simula a execução do plugin em um projeto real. Deve serhermético, isto é, ele deve criar o arquivo por conta própria`managed-jbake-context.yml`com um conteúdo controlado, para garantir a reprodutibilidade e o isolamento do teste

// 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 teste funcional verifica que o arquivo de configuração copiado para o diretório temporário do teste contém os dados esperados. Embora este teste não faça o parsing diretamente do YAML em um objeto Kotlin, ele valida a presença do arquivo e do seu conteúdo, o que é um passo prévio essencial para o parsing pelo plugin.

5. Visualização do Fluxo de Parsing

O diagrama a seguir ilustra o fluxo de dados e as interações durante o parsing da configuração YAML :

Diagram

Conclusão

Ao seguir uma abordagem TDD, integramos com sucesso a biblioteca Jackson para analisar arquivos de configuração YAML em objetos Kotlin dentro do nosso plugin Gradle. Este método nos permitiu:

  • Modelar claramentenossa configuração com classes de dados Kotlin.

  • Validar a lógica de análisecom testes unitários direcionados.

  • Garantir a integraçãonum ambiente Gradle real graças a testes funcionais herméticos.

Esta base sólida nos oferece uma grande confiança para estender nosso plugin com funcionalidades que se baseiam nessa configuração, ao mesmo tempo em que garante a manutenibilidade e a robustez do código. O parsing YAML agora é um recurso confiável e testado do nosso plugin`site-baker`.

Articles connexes