Tarea 3 - Build Systems: Plugins
Hasta ahora, has trabajado con plugins que implementan Plugin<Project>
, permitiendo aplicar configuraciones específicas a proyectos. Sin embargo, Gradle proporciona una interfaz más general llamada Plugin<PluginAware>
. Esta interfaz es útil cuando quieres que tu plugin pueda aplicarse tanto a un Project
como a Settings
, permitiendo configurar aspectos específicos dependiendo del tipo de objeto al que se aplique.
Diferencias clave:
Plugin<Project>
: Se aplica específicamente a proyectos Gradle, permitiendo configurar tareas, dependencias y extensiones a nivel de proyecto.Plugin<Settings>
: Se aplica al objetoSettings
, permitiendo configurar aspectos globales del build, como los repositorios de plugins y convenciones de configuración para subproyectos.Plugin<PluginAware>
: Es una interfaz más general que puede aplicarse tanto aProject
como aSettings
. Te permite escribir un plugin que adapte su comportamiento dependiendo del tipo de objeto al que se aplique.
Ejemplo de plugin adaptable
import org.gradle.api.Plugin
import org.gradle.api.PluginAware
import org.gradle.api.Project
import org.gradle.api.initialization.Settings
class AdaptivePlugin : Plugin<PluginAware> {
override fun apply(target: PluginAware) {
when (target) {
is Project -> {
// Configuraciones específicas para proyectos
target.tasks.register("hello") {
doLast {
println("Hello from the Project!")
}
}
}
is Settings -> {
// Configuraciones específicas para settings
target.gradle.rootProject {
println("Configuring settings for the build.")
}
}
else -> {
throw IllegalArgumentException("Plugin can only be applied to Project or Settings.")
}
}
}
}
En este ejemplo, el plugin AdaptivePlugin
verifica si el objeto al que se aplica es un Project
o Settings
y aplica configuraciones específicas en consecuencia.
Agregando dependencias y repositorios en el plugin
Es importante notar que los plugins implementados como clases no tienen acceso al catálogo de versiones de Gradle (libs.versions.toml
). Por lo tanto, debes especificar las versiones de las dependencias directamente en el plugin.
Para agregar una dependencia a un objeto Project
, puedes usar:
project.dependencies.add("implementation", "group:artifact:version")
Tarea
Supongamos que quieres hacer un bot de Telegram. Con el fin de hacer una buena separación entre la lógica de negocio y aplicación, decides separar el código en dos subproyectos: core
y bot
. El subproyecto core
contendrá la lógica para interactuar con la API de Telegram como enviar mensajes, recibir actualizaciones, etc. El subproyecto bot
contendrá la lógica de aplicación específica, como manejar la base de datos y recibir comandos por consola.
Para manejar la interacción con la API de Telegram, decides utilizar Kotlin Telegram Bot. Sin embargo, te das cuenta de que si el bot crece podrías tener que crear más módulos que interactúen con la API de Telegram. Por lo tanto, decides implementar un plugin de Gradle que permita configurar la dependencia de Kotlin Telegram Bot solamente en los subproyectos que lo necesiten.
P1. [2.5 pts] Manejo de repositorios y dependencias
Crea un plugin TelegramBotPlugin
que implemente Plugin<PluginAware>
. El plugin debe:
- Si se aplica a
Settings
: Configurar el repositorio de JitPack con la URLhttps://jitpack.io
. - Si se aplica a un
Project
: Agregar la dependenciaio.github.kotlin-telegram-bot.kotlin-telegram-bot:telegram:6.2.0
.
Dado que los plugins implementados como clases no tienen acceso al catálogo de versiones, debes especificar la versión 6.2.0
directamente en el plugin.
P2. [3.5] Plugin para configurar Detekt
Te das cuenta de que podrías necesitar varios plugins de Detekt en tu proyecto, pero los plugins no serán los mismos para todos los módulos. Por lo tanto, decides crear un plugin pre-compilado que permita especificar qué plugins de Detekt se deben aplicar a cada subproyecto de forma independiente.
-
[1 pt] Crea una extensión que te permita configurar una lista de plugins de Detekt.
-
[1 pt] Crea un plugin pre-compilado que registre la extensión y aplique el plugin
DetektPlugin
, para esto necesitarás definir la siguiente dependencia:[libraries]
# ...
detekt = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", version.ref = "detekt" } -
[1.5 pts] Haz que el plugin aplique los plugins de Detekt especificados en la extensión. Para esto, puedes hacer
"detektPlugins"(plugin)
dentro de un bloquedependencies
, dondeplugin
es un String que contiene el nombre del plugin de Detekt. Por ejemplo:dependencies {
"detektPlugins"("io.gitlab.arturbosch.detekt:detekt-formatting:1.18.1")
"detektPlugins"("com.faire:faire-detekt-rules:0.2.4")
}
Ejemplo de uso
plugins {
id("detekt.conventions")
}
detektConfig {
plugins = listOf(
"io.gitlab.arturbosch.detekt:detekt-formatting:1.18.1",
"com.faire:faire-detekt-rules:0.2.4"
)
}
Hint: Define el bloque dependencies
dentro de un bloque afterEvaluate
para que se aplique después de que se hayan configurado todas las dependencias.