Okuma süresi : 12 dakika

Hedef kitle: karmaşık yapılandırmaları yönetmek isteyen orta seviye Gradle geliştiricileri

Giriş

Gradle eklenti geliştirme yaparken, karmaşık yapılandırma yönetimi yaygın bir görevdir. DSL’yi yüzlerce özellikle yükmelmek yerine, yapılandırmayı YAML gibi harici bir dosyada tanımlamak genellikle daha temiz ve sürdürülebilirdir. Bu makale, güçlü Jackson kütüphanesini kullanarak YAML dosyalarını Kotlin nesnelerine dönüştürmeyi entegre etme konusunda size rehberlik eder ve eklentimizin sağlamlığını garanti altına almak için katı bir TDD yaklaşımı benimser.site-baker.

1. Bağlam : Bizim Eklentimiz `site-baker

Eklentimiz`site-baker`bir statik sitesinin üretimini ve dağıtımını otomatikleştirmek için tasarlanmıştır. Bir YAML yapılandırma dosyasını okuması gerekir.managed-jbake-context.yml) kaynak yolları, dağıtım hedefleri ve Git kimlikleri gibi bilgileri elde etmek için.

Ayrıştırıcı olarak istediğimiz YAML yapılandırması şu şekilde:

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’de Yapılandırma Modellemesi

Parsing öncesi, Kotlin’te veri yapımızı tanımlamalıyız. Jackson, bu sınıfları kullanarak YAML içeriğini otomatik olarak eşleyecek.

// 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)

Fonksiyon`parseSiteConfiguration`bu, deserileşme için giriş noktamız. Kullanır`ObjectMapper`Jackson’ın, yapılandırılmış ile`YAMLFactory`YAML formatı için ve`registerKotlinModule()`Kotlin’in özelliklerini (özelliklerin varsayılan değerleri gibi) desteklemek için.

3. Jackson’ın `build.gradle.kts’e entegrasyonu

Jackson kullanmak için, gerekli bağımlılıkları eklememiz gerekiyor`build.gradle.kts`bizim modülünün`plugin`(empty)

// 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
}

Kullanıyoruz`jackson-module-kotlin`Kotlin desteği için ve`jackson-dataformat-yaml`YAML formatının yönetimi için.

4. TDD Yaklaşımı: YAML Parsing’ini Test Etme

Şimdi, ayrıştırma mantığımızı doğrulamak için TDD’yi uygulayalım.

4.1. Birim Testi: YAML’i Kotlin Nesnesine Eşleme

Bir birim testi ile başlıyoruz`SiteBakerPluginTest.kt`fonksiyonu kontrol etmek için`parseSiteConfiguration`YAML dizesini bir nesneye doğru bir şekilde dönüştürebilir`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)
}

Bu test dosyanın içeriğini okur`managed-jbake-context.yml`(testin geçerli olması için mevcut olmalıdır) ve nesne üzerinde iddialar yapar`SiteConfiguration`Sonuçlanan. YAML anahtar değerlerinin doğru şekilde eşlendiğini doğrular.

4.2. Fonksiyonel Test: Yapılandırma Dosyasının Okumasını Doğrula

Eklentinin DSL üzerinden yapılandırma dosyasını okuyabildiğini ve analiz işleminin gerçek bir Gradle ortamında çalıştığından emin olmak için, bir fonksiyonel test ekliyoruz`SiteBakerPluginFunctionalTest.kt`.

Bu test, gerçek bir projede pluginin çalıştırılmasını simüle ettiği için çok önemlidir. Olmalıhermetik, yani kendisi dosyayı oluşturmalıdır`managed-jbake-context.yml`kontrollü bir içerikle, testin tekrarlanabilirliğini ve izolasyonunu sağlamak için.

// 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"))
}

Bu fonksiyonel test, testin geçici dizinine kopyalanan yapılandırma dosyasının beklenen verileri içerdiğini doğrular. YAML’i doğrudan Kotlin nesnesine ayrıştırmazsa da, dosyanın varlığını ve içeriğini doğrular; bu, eklenti tarafından ayrıştırma öncesinde gereken temel bir adımdır.

5. Parsing Akışı Görselleştirme

Aşağıdaki diyagram, YAML yapılandırması ayrıştırılırken veri akışı ve etkileşimlerini gösterir :

@startuml
actor "Utilisateur Gradle" as User
participant "build.gradle.kts" as BuildScript
participant "SiteBakerPlugin" as Plugin
participant "SiteExtension" as Extension
participant "managed-jbake-context.yml" as ConfigFile
participant "parseSiteConfiguration()" as Parser
participant "SiteConfiguration (Objet Kotlin)" as KotlinObject

User -> BuildScript : Applique le plugin et configure le DSL
BuildScript -> Plugin : apply()
Plugin -> Extension : Crée et enregistre l'extension 'site'
User -> BuildScript : site { configPath = "..." }
BuildScript -> Extension : Définit configPath

Plugin -> ConfigFile : Lit le fichier (via configPath)
ConfigFile --> Plugin : Contenu YAML
Plugin -> Parser : Appelle parseSiteConfiguration(yamlString)
Parser -> KotlinObject : Mappe le YAML en objet SiteConfiguration
KotlinObject --> Plugin : Retourne l'objet configuré

@enduml

Sonuç

TDD yaklaşımını izleyerek, Jackson kütüphanesini YAML yapılandırma dosyalarını Kotlin nesnelerine ayrıştırmak için başarıyla Gradle eklentimizle entegre ettik. Bu yöntem, bize şunları sağladı:

  • Açıkça modellemekKotlin veri sınıflarıyla yapılandırma.

  • Parsing mantığını doğrulahedefli birim testleri ile

  • Entegrasyonu sağlamakgerçek Gradle ortamında, kapalı fonksiyonel testler sayesinde.

Bu sağlam temel, bu yapıya dayalı özelliklerle eklentimizi genişletirken bize büyük güven sağlarken, kodun sürdürülebilirliğini ve sağlamlığını da garanti altına alır. YAML ayrıştırma artık eklentimizin güvenilir ve test edilmiş bir özelliğidir.site-baker.

İlgili Makaleler