簡體   English   中英

如何使用 Kotlin 將導入的插件合並到 Gradle 中的自定義插件

[英]How to consolidate imported plugins to custom plugin in Gradle using Kotlin

我有一些微服務,它們將在所有微服務之間共享一些相同的配置,主要是 Jib、發布和發布。 不確定是否可以對依賴項執行相同的操作,但在每個依賴項中包含執行器和 log4j2 將是有益的。 這是我的一個項目的 build.gradle.kts。

import net.researchgate.release.BaseScmAdapter
import net.researchgate.release.GitAdapter
import net.researchgate.release.ReleaseExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("com.gorylenko.gradle-git-properties") version "1.5.1"
    id("com.google.cloud.tools.jib") version "1.6.1"
    id("io.spring.dependency-management") version "1.0.7.RELEASE"
    id("net.researchgate.release") version "2.8.1"
    id("org.sonarqube") version "2.7.1"
    id("org.springframework.boot") version "2.1.6.RELEASE"
    kotlin("jvm") version "1.2.71"
    kotlin("plugin.spring") version "1.2.71"
    jacoco
    `maven-publish`
}

java.sourceCompatibility = JavaVersion.VERSION_1_8

springBoot {
    buildInfo {
        group = project.properties["group"].toString()
        version = project.properties["version"].toString()
        description = project.properties["description"].toString()
    }
}

repositories {
    maven(url = uri(project.properties["nexus.url.gateway"].toString()))
    mavenCentral()
}

dependencies {
    // Kotlin
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")

    // Spring
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("org.springframework.boot:spring-boot-starter-log4j2")
    implementation("org.springframework.boot:spring-boot-starter-security")
    implementation("org.springframework.cloud:spring-cloud-config-server")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
}

dependencyManagement {
    imports {
        mavenBom("org.springframework.cloud:spring-cloud-dependencies:Greenwich.SR3")
    }
}

configurations.all {
    exclude(group = "ch.qos.logback", module = "logback-classic")
    exclude(group = "org.springframework.boot", module = "spring-boot-starter-logging")
}

tasks {
    withType<KotlinCompile> {
        kotlinOptions {
            freeCompilerArgs = listOf("-Xjsr305=strict")
            jvmTarget = "1.8"
        }
    }

    build { dependsOn(clean) }
    afterReleaseBuild { dependsOn(publish) }
    publish { dependsOn(build) }
    jibDockerBuild { dependsOn(build) }
    jacocoTestReport {
        reports {
            html.isEnabled = false
            xml.isEnabled = true
        }
    }
}

publishing {
    publications {
        create<MavenPublication>(project.name) {
            from(components["java"])
            pom {
                scm {
                    connection.set("scm:git:git@github.com:company/${project.name}.git")
                    developerConnection.set("scm:git:git@github.com:company/${project.name}.git")
                    url.set("https://github.com/company/${project.name}/")
                }
            }
            versionMapping {
                usage("java-api") {
                    fromResolutionOf("runtimeClasspath")
                }
                usage("java-runtime") {
                    fromResolutionResult()
                }
            }
        }
    }
    repositories {
        maven {
            val releasesRepoUrl = "${project.properties["nexus.url.publish"].toString()}/releases"
            val snapshotsRepoUrl = "${project.properties["nexus.url.publish"].toString()}/snapshots"
            url = uri(if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl)
            credentials {
                username = project.properties["nexus.user"].toString()
                password = project.properties["nexus.password"].toString()
            }
        }
    }
}

fun ReleaseExtension.git(configureFn : GitAdapter.GitConfig.() -> Unit) {
    (propertyMissing("git") as GitAdapter.GitConfig).configureFn()
}

release {
    scmAdapters = mutableListOf<Class<out BaseScmAdapter>> ( GitAdapter::class.java )

    git {
        requireBranch = "develop"
        pushToRemote = project.properties["release.git.remote"].toString()
        pushReleaseVersionBranch = "master"
        tagTemplate = "${project.name}.${project.version}"
    }
}

jib {
    from {
        image = "openjdk:8-jdk-alpine"
    }
    to {
        image = "host:port/${project.name}:${project.version}"
        auth {
            username = project.properties["nexus.user"].toString()
            password = project.properties["nexus.password"].toString()
        }
    }
    container {
        workingDirectory = "/"
        ports = listOf("8080")
        environment = mapOf(
                "SPRING_OUTPUT_ANSI_ENABLED" to "ALWAYS",
                "SPRING_CLOUD_BOOTSTRAP_LOCATION" to "/path/to/bootstrap.yml"
        )
        useCurrentTimestamp = true
    }
    setAllowInsecureRegistries(true)
}

I was able to get a custom plugin created and added to this project using git@github.com:klg71/kotlintestplugin.git and git@github.com:klg71/kotlintestpluginproject.git but I have no idea how to implement these existing plugins and他們的配置。 在應用 function 中的主插件 class 中,我可以調用 project.pluginManager.apply(PublishingPlugin::class.java),這會導致我可以在項目中顯示如何引用自定義插件的任務配置它並且它沒有成功發布到nexus服務器。 我可以將插件本身發布到 nexus 服務器並在微服務中引用它,但它會跳過運行任務,我認為這是由於未包含配置引起的。 此外,當嘗試應用/配置 Jib 插件時,嘗試導入時所有類都不可見。

所以上面的答案不是很長,為了保留我遇到的問題,我發布了一個新的答案。

插入

這部分答案將討論實際的自定義插件項目。 因為build.gradle.kts中的插件包裝器是運行時的,所以CustomPlugin.kt在編譯時無法訪問它。 我的老板比我聰明得多,盡管他從未與 gradle 合作過,但他還是很友善地向我指出了這一點。 盡管我在他面前看起來很愚蠢,但他仍然通過基本上遵循在 gradle 中應用插件的“傳統”方式讓我啟動並運行。

plugins { // This is a runtime script preventing plugins declared here to be accessible in CustomPlugin.kt but is used to actually publish/release this plugin itself
    id("net.researchgate.release") version "2.8.1"
    kotlin("jvm") version "1.3.0"
    `maven-publish`
}

repositories {
    maven { url = uri("https://plugins.gradle.org/m2/") } // This is required to be able to import plugins below in the dependencies
    jcenter()
}

dependencies {
    compile(kotlin("stdlib"))
    compile(kotlin("reflect"))

    // These must be declared here (at compile-time) in order to access in CustomPlugin.kt
    compile(group = "gradle.plugin.com.gorylenko.gradle-git-properties", name = "gradle-git-properties", version = "2.2.0")
    compile(group = "gradle.plugin.com.google.cloud.tools", name = "jib-gradle-plugin", version = "1.7.0")
    compile(group = "net.researchgate", name = "gradle-release", version = "2.8.1")
    compile(group = "org.asciidoctor", name = "asciidoctor-gradle-plugin", version = "1.5.9.2")
    compile(group = "org.jetbrains.dokka", name = "dokka-gradle-plugin", version = "0.9.18")
    compile(group = "org.sonarsource.scanner.gradle", name = "sonarqube-gradle-plugin", version = "2.8")

    implementation(gradleApi()) // This exposes the gradle API to CustomPlugin.kt
}

這使我可以訪問 jib 和CustomPlugin.kt中的所有其他內容。 插件jacocomaven-publish可以在插件項目中自動訪問,但仍然需要在引用該插件的微服務項目中添加。 不幸的是,我無法找到解決方法。

我在build.gradle.kts中包含了典型的 maven-publish 插件,以便將build.gradle.kts中的發布任務配置推送到 nexus,這樣我就可以從想要使用插件的微服務中的 nexus 中提取它。

publishing {
    publications {
        create<MavenPublication>(project.name) {
            from(components["java"])
            pom {
                scm {
                    connection.set("scm:git:git@github.com:diendanyoi54/${project.name}.git")
                    developerConnection .set("scm:git:git@github.com:diendanyoi54/${project.name}.git")
                    url.set("https://github.com/diendanyoi54/${project.name}/")
                }
            }
        }
    }
    repositories {
        maven {
            val baseUrl = "https://${project.properties["nexus.host"].toString()}:${project.properties["nexus.port.jar"].toString()}/repository"
            url = uri(if (version.toString().endsWith("SNAPSHOT")) "$baseUrl/maven-snapshots" else "$baseUrl/maven-releases")
            credentials {
                username = project.properties["nexus.user"].toString()
                password = project.properties["nexus.password"].toString()
            }
        }
    }
}

最后,您要確保包含將告訴微服務插件 class 所在位置的屬性文件。 在 Intellij 的 IDEA 中,當輸入實現類的路徑時,它會自動為我完成。 在此處輸入圖像描述 此文件的名稱應反映微服務的 build.gradle.kts中的apply(plugin = "string")

執行

這部分答案將反映將引用插件的微服務項目。 如上所述,由於某種原因,jacoco 和 maven-publish 仍然需要添加到 build.gradle.kts 中的插件塊中(我認為是因為它們是官方的 gradle 插件)。 在此處輸入圖像描述

要從發布它的 nexus 服務器引用插件,微服務必須在 buildscript 中引用它。

buildscript { // Custom plugin must be accessed by this buildscript
    repositories {
        maven {
            url = uri("https://${project.properties["nexus.host"].toString()}:${project.properties["nexus.port.jar"].toString()}/repository/maven-public")
            credentials {
                username = project.properties["nexus.user"].toString()
                password = project.properties["nexus.password"].toString()
            }
        }
    }
    dependencies { classpath("com.company:kotlin-consolidated-plugin:1.0.0-SNAPSHOT") }
}

最后,必須使用上面引用的屬性文件名應用插件。

apply(plugin = "com.company.kotlinconsolidatedplugin") // Custom plugin cannot reside in plugin declaration above

我創建了這些示例項目並將它們發布到 Github 所以隨意克隆或查看: git@github.com:diendanyoi54/kotlin-consolidated-plugin.ZBA9F11ECC3497BD9993B933EDC

git@github.com:diendanyoi54/kotlin-consolidated-plugin-implementation.git

我能夠成功地使用上面引用的 github 存儲庫示例來完成我需要的發布任務。 這是我的自定義插件build.gradle.kts

plugins {
    id("com.google.cloud.tools.jib") version "1.6.1"
    id("org.sonarqube") version "2.7.1"
    kotlin("jvm") version "1.3.0"
    `maven-publish`
}

dependencies {
    compile(kotlin("stdlib"))
    compile(kotlin("reflect"))
    implementation(gradleApi())
}

repositories {
    jcenter()
}

publishing {
    publications {
        create<MavenPublication>(project.name) {
            from(components["java"])
            pom {
                scm {
                    connection.set("scm:git:git@github.com:company/${project.name}.git")
                    developerConnection.set("scm:git:git@github.com:company/${project.name}.git")
                    url.set("https://github.com/company/${project.name}/")
                }
            }
        }
    }
    repositories {
        maven {
            val baseUrl = "https://${project.properties["nexus.host"].toString()}:${project.properties["nexus.port.jar"].toString()}/repository"
            url = uri(if (version.toString().endsWith("SNAPSHOT")) "$baseUrl/maven-snapshots" else "$baseUrl/maven-releases")
            credentials {
                username = project.properties["nexus.user"].toString()
                password = project.properties["nexus.password"].toString()
            }
        }
    }
}

這是 CustomPlugin.kt class。

package com.company.gradlemicroserviceplugin

//import com.google.cloud.tools.jib.gradle.JibExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.plugins.PublishingPlugin
import org.gradle.testing.jacoco.tasks.JacocoReport
import java.net.URI

open class CustomPlugin : Plugin<Project> {
    override fun apply(project: Project) {
//        applySonar(project)
        applyPublish(project)
//        applyJib(project)
    }

//    private fun applySonar(project: Project) {
//        project.pluginManager.apply("sonarqube")
//        val task = project.task("jacocoTestReport") as JacocoReport
//        task.reports = JacocoReport()
//        jacocoTestReport { This was nested in the tasks declaration in build.gradle.kts so the fields below are the fields I'm trying to set in task.reports
//            reports {
//                html.isEnabled = false
//                xml.isEnabled = true
//            }
//        }
//    }

    private fun applyPublish(project: Project) {
        project.pluginManager.apply(PublishingPlugin::class.java)

        val publishingExtension = project.extensions.findByType(PublishingExtension::class.java)
        val mavenPublication = publishingExtension?.publications?.create(project.name, MavenPublication::class.java)

        publishingExtension?.repositories?.maven {
            val baseUrl = "https://${project.properties["nexus.host"].toString()}:${project.properties["nexus.port.jar"].toString()}/repository"
            it.url = URI(if (project.version.toString().endsWith("SNAPSHOT")) "$baseUrl/maven-snapshots" else "$baseUrl/maven-releases")
            it.credentials { cred ->
                cred.username = project.properties["nexus.user"].toString()
                cred.password = project.properties["nexus.password"].toString()
            }
        }

        mavenPublication?.from(project.components.findByName("java"))
        mavenPublication?.pom?.scm {
            it.connection.set("scm:git:git@github.com:company/${project.name}.git")
            it.developerConnection.set("scm:git:git@github.com:company/${project.name}.git")
            it.url.set("https://github.com/company/${project.name}/")
        }
    }

//    private fun applyJib(project: Project) {
//        project.pluginManager.apply(JibPlugin::class.java)
//
//    }
}

在這方面肯定有改進的地方,但至少我在這里得到了一些工作。 build.gradle.kts中都有maven-publish邏輯,因為我將自定義插件推送到 nexus 並且maven-publish邏輯在CustomPlugin.kt class 中,因此引用此插件的微服務可以使用它。 但是,我無法成功設置JibSonar Jib不允許我訪問com.google.cloud.tools.jib.gradle中的任何內容,這使我無法使用與maven-publish中使用的方法相同的方法。 在此處輸入圖像描述 對於聲納,我認為我在按名稱檢索任務的正確軌道上,但我無法設置屬於 task.reports 的任何字段,因為它們都是最終的,這是聲納正確分析Kotlin所必需的。

應用內置插件

plugins {
java
id("jacoco")
}

您還可以使用較舊的 apply 語法:

apply(plugin = "checkstyle")

應用外部插件

plugins {
    id("org.springframework.boot") version "2.0.1.RELEASE"
}

我不擅長 kotlin 但這里有鏈接可以更好地理解缺少的 Gradle Kotlin DSL 的遷移指南

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM