【问题标题】:How to centralize Gradle build settings?如何集中 Gradle 构建设置?
【发布时间】:2020-10-17 21:39:35
【问题描述】:

假设我正在使用palantir/gradle-git-version Gradle 插件,并在build.gradle.kts 中有以下代码来确定项目版本:

// If release branch, return after incrementing patch version.
// Else, return $lastTag-SNAPSHOT.
val projectVersion: String by lazy {
    val versionDetails: groovy.lang.Closure<VersionDetails> by extra
    with(versionDetails()) {
        if (!lastTag.matches("^(?:(?:\\d+\\.){2}\\d+)\$".toRegex())) {
            throw GradleException("Tag '$lastTag' doesn't match 'MAJOR.MINOR.PATCH' format")
        }
        // If it detached state, get branch name from GitLab CI env var
        val branch = branchName ?: System.getenv("CI_COMMIT_REF_NAME")
        if (branch?.startsWith("release/") == true) {
            val tokens = lastTag.split('.')
            "${tokens[0]}.${tokens[1]}.${tokens[2].toInt() + commitDistance}"
        } else "$lastTag-SNAPSHOT"
    }
}

这可行,但代码在所有项目中重复,除了极少数项目外,很难维护。

这只是一个示例,同样适用于其他在公司/团队中采用某些约定的 Gradle 任务,例如创建Dockerfile

有什么好的方法可以集中这些代码以便所有项目都可以使用它们?请注意,这样的代码通常不会独立存在,而是依赖于 Gradle 插件。

【问题讨论】:

  • 我当前的团队将构建的所有(公共)部分维护为应用到团队所有项目的 Gradle 插件。 Gradle 插件可以包含几乎相同的内容,您可以放入构建文件本身,从属性和任务声明到应用整个其他插件。我认为这也可能是这种情况下的一个选项 - 从版本处理开始,如果需要则扩展
  • @RolandKreuzer 我知道 Gradle 插件声明了新任务,但没有声明新属性;我也不清楚 Gradle 插件如何传递应用其他插件。您可以在删除专有信息后使用您引用的插件的 sn-p 发布答案吗?

标签: gradle build.gradle gradle-plugin gradle-kotlin-dsl


【解决方案1】:

有什么好的方法可以集中这些代码以便所有项目都可以使用它们?

您需要创建一个custom Gradle plugin 来保存您的项目约定。

如果您在本地安装了 Gradle,则可以使用 Build Init Plugin 创建骨架插件项目。本地安装 Gradle 后,在新项目目录中简单运行 gradle init 并按照提示创建插件项目。

作为一个具体示例(假设您生成了一个前面提到的插件项目),为了应用您的版本控制约定,插件可以是:

// Plugin's build.gradle.kts
dependencies {
    // Add dependency for plugin, GAV can be found on the plugins page:
    // https://plugins.gradle.org/plugin/com.palantir.git-version
    implementation("com.palantir.gradle.gitversion:gradle-git-version:0.12.3")
}

那么版本控制插件可以是:

import com.palantir.gradle.gitversion.VersionDetails
import groovy.lang.Closure
import org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project

class VersioningConventionsPlugin : Plugin<Project> {

    override fun apply(project: Project) {
        // Apply plugin to project as you would in the main Gradle build file.
        project.pluginManager.apply("com.palantir.git-version")

        // Configure version conventions
        val projectVersion: String by lazy {

            // Gradle generates some Kotlin DSL code on the fly, in a plugin implementation we don't have that.
            // So we must convert the DSL to the Gradle API.
            val versionDetails: Closure<VersionDetails> = project.extensions.extraProperties.get("versionDetails") as Closure<VersionDetails>

            with(versionDetails.call()) {
                if (!lastTag.matches("^(?:(?:\\d+\\.){2}\\d+)\$".toRegex())) {
                    throw GradleException("Tag '$lastTag' doesn't match 'MAJOR.MINOR.PATCH' format")
                }
                val branch = branchName ?: System.getenv("CI_COMMIT_REF_NAME")
                if (branch?.startsWith("release/") == true) {
                    val tokens = lastTag.split('.')
                    "${tokens[0]}.${tokens[1]}.${tokens[2].toInt() + commitDistance}"
                } else "$lastTag-SNAPSHOT"
            }
        }

        // Set the version as an extra property on the project
        // Accessible via extra["projectVersion"]
        project.extensions.extraProperties["projectVersion"] = projectVersion
    }
}

我给出了一个 Kotlin 示例,因为您的示例使用了 Kotlin DSL。完成约定插件的开发工作后,您将发布到诸如Gradle Plugins repository 之类的存储库。如果是公司内部插件,则将其发布到内部Nexus Repository 或类似网站。

关注maven-publish 插件的文档以获取有关发布的更多详细信息。 Gradle 插件可以像任何其他工件/JAR 一样发布。

【讨论】:

  • 那么,应用所示插件的项目将可以访问其构建文件中的变量projectVersion?还是仅在VersioningConventionsPlugin 内可用?最后,你从哪里得到这样一个“衍生”插件的想法,你可以参考一些文档吗?
  • 正确。至于这个想法,你说你想把逻辑集中到一个地方。这是我在回答中链接的 Gradle 插件文档的第一行:Gradle 插件打包了可重用的构建逻辑片段,可用于许多不同的项目和构建。
  • 对不起,你说projectVersion在下游项目中可用吗?
  • 我只回答了一个字:正确。但是为了扩展,在上面的示例中,我在 extra 属性上设置了 projectVersion。因此它适用于任何应用该插件的项目。
猜你喜欢
  • 1970-01-01
  • 2016-07-19
  • 2016-06-16
  • 2017-04-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-10
  • 1970-01-01
  • 2023-03-12
相关资源
最近更新 更多