我目前正在尝试改善我们的项目共享其配置的方式。我们所有的库和微服务都有很多不同的多模块gradle项目(即许多git repos)。
我的主要目标是:
我当前的解决方案是使用以下脚本的自定义gradle分发:
mavenLocal()
和我们的Nexus存储库添加到项目存储库中(非常类似于Gradle init script documentation example,不同之处在于它添加了存储库并对其进行了验证)build.gradle
文件几乎完全是用于依赖项的。 这是初始化脚本(已清除):
/**
* Gradle extension applied to all projects to allow automatic configuration of Corporate plugins.
*/
class CorporatePlugins {
public static final String NEXUS_URL = "https://example.com/repository/maven-public"
public static final String CORPORATE_PLUGINS = "com.example:corporate-gradle-plugins"
def buildscript
CorporatePlugins(buildscript) {
this.buildscript = buildscript
}
void version(String corporatePluginsVersion) {
buildscript.repositories {
maven {
url NEXUS_URL
}
}
buildscript.dependencies {
classpath "$CORPORATE_PLUGINS:$corporatePluginsVersion"
}
}
}
allprojects {
extensions.create('corporatePlugins', CorporatePlugins, buildscript)
}
apply plugin: CorporateInitPlugin
class CorporateInitPlugin implements Plugin<Gradle> {
void apply(Gradle gradle) {
gradle.allprojects { project ->
project.repositories {
all { ArtifactRepository repo ->
if (!(repo instanceof MavenArtifactRepository)) {
project.logger.warn "Non-maven repository ${repo.name} detected in project ${project.name}. What are you doing???"
} else if(repo.url.toString() == CorporatePlugins.NEXUS_URL || repo.name == "MavenLocal") {
// Nexus and local maven are good!
} else if (repo.name.startsWith("MavenLocal") && repo.url.toString().startsWith("file:")){
// Duplicate local maven - remove it!
project.logger.warn("Duplicate mavenLocal() repo detected in project ${project.name} - the corporate gradle distribution has already configured it, so you should remove this!")
remove repo
} else {
project.logger.warn "External repository ${repo.url} detected in project ${project.name}. You should only be using Nexus!"
}
}
mavenLocal()
// define Nexus repo for downloads
maven {
name "CorporateNexus"
url CorporatePlugins.NEXUS_URL
}
}
}
}
}
然后,通过将以下内容添加到root build.gradle文件中,配置每个新项目:
buildscript {
// makes our plugins (and any others in Nexus) available to all build scripts in the project
allprojects {
corporatePlugins.version "1.2.3"
}
}
allprojects {
// apply plugins relevant to all projects (other plugins are applied where required)
apply plugin: 'corporate.project'
group = 'com.example'
// allows quickly updating the wrapper for our custom distribution
task wrapper(type: Wrapper) {
distributionUrl = 'https://com.example/repository/maven-public/com/example/corporate-gradle/3.5/corporate-gradle-3.5.zip'
}
}
虽然这种方法行之有效,但允许可复制的构建(不同于我们以前的应用程序通过URL应用构建脚本-当时是不可缓存的),并且允许脱机工作,这确实使它有些不可思议,我想知道我是否可以做得更好。
这全部是由Gradle开发者Stefan Oehme阅读a comment on Github触发的,该声明表示构建应该可以在不依赖初始化脚本的情况下工作,即,初始化脚本应该只是装饰性的,并且可以像已记录的示例那样进行操作-防止未经授权的回购等。
我的想法是编写一些扩展功能,使我可以将Nexus repo和插件添加到内部版本中,就像它们内置在gradle中一样(类似于Gradle Kotlin DSL提供的扩展功能
gradleScriptKotlin()
和 kotlin-dsl()
)。因此,我在kotlin gradle项目中创建了扩展功能:
package com.example
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
fun RepositoryHandler.corporateNexus(): MavenArtifactRepository {
return maven {
with(it) {
name = "Nexus"
setUrl("https://example.com/repository/maven-public")
}
}
}
fun DependencyHandler.corporatePlugins(version: String) : Any {
return "com.example:corporate-gradle-plugins:$version"
}
计划在我的项目的
build.gradle.kts
中使用它们,如下所示:import com.example.corporateNexus
import com.example.corporatePlugins
buildscript {
repositories {
corporateNexus()
}
dependencies {
classpath(corporatePlugins(version = "1.2.3"))
}
}
但是,在
buildscript
块中使用时,Gradle无法看到我的函数(无法编译脚本)。尽管在正常的项目存储库/依赖项中使用它们仍然可以正常工作(它们可见且按预期运行)。如果可行,我希望将jar bundle 到我的自定义发行版中,这意味着我的init脚本可以执行简单的验证,而不是隐藏神奇的插件和回购配置。扩展功能不需要更改,因此在插件更改时不需要发布新的Gradle发行版。
我试过的
buildscript.dependencies
)中-不起作用(也许这在设计上不起作用,因为在同一块中引用的buildscript
中添加依赖项似乎不正确) buildSrc
中(该功能适用于常规项目deps / repos,但不适用于buildscript
,但不是真正的解决方案,因为它只是移动样板)lib
文件夹中所以我的问题实际上可以归结为:
buildScript
块可见自定义类/函数)? 最佳答案
如果您想从Gradle Kotlin DSL的所有优点中受益,您应该努力使用plugins {}
块来应用所有插件。参见https://github.com/gradle/kotlin-dsl/blob/master/doc/getting-started/Configuring-Plugins.md
您可以在设置文件中管理插件存储库和解析策略(例如其版本)。从Gradle 4.4开始,可以使用Kotlin DSL aka settings.gradle.kts
编写此文件。参见https://docs.gradle.org/4.4-rc-1/release-notes.html。
考虑到这一点,您便可以使用一个集中的Settings
脚本插件来进行设置并将其应用到您的生成settings.gradle.kts
文件中:
// corporate-settings.gradle.kts
pluginManagement {
repositories {
maven {
name = "Corporate Nexus"
url = uri("https://example.com/repository/maven-public")
}
gradlePluginPortal()
}
}
和:
// settings.gradle.kts
apply(from = "https://url.to/corporate-settings.gradle.kts")
然后,在项目构建脚本中,您可以简单地从公司资源库中请求插件:
// build.gradle.kts
plugins {
id("my-corporate-plugin") version "1.2.3"
}
如果您希望多项目构建中的项目构建脚本不重复插件版本,则可以通过在根项目中声明版本来使用Gradle 4.3。请注意,如果所有版本都使用相同的插件版本,则也可以使用
settings.gradle.kts
在pluginManagement.resolutionStrategy
中设置版本。另请注意,要使所有这些工作正常进行,您的插件必须使用其plugin marker artifact发布。使用
java-gradle-plugin
插件可以轻松完成此操作。
关于gradle - 使用Gradle Kotlin DSL在Gradle中进行样板项目配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43657807/