我正在为Gradle编写一个自定义插件,允许用户将其构建生成的工件发布到公司Maven存储库。我希望用户能够使用标准maven-publish
插件上传他们的工件,但是他们不知道存储库的详细信息,即身份验证。
用户可以运行本地版本,但不能向存储库发布任何内容。在构建服务器上运行时,相同的用户提供的构建脚本将能够发布。用户可以下载插件并在本地使用它,但它不起作用。它会失败或者做一个模拟的无操作上传到本地/虚拟仓库/无论如何,这现在并不重要。在构建服务器上运行时,插件只会“知道”并正常工作。
正如我所说,我希望用户使用标准maven-publish
插件。对于用户的build.gradle:
repositories {
mavenCentral()
Organization.mavenCorporate() /* this would be it */
}
(Organization
部分不是必需的,这就是我看到它如何与Gradle的项目扩展一起使用,这些扩展似乎目前比常规更受欢迎。)
到目前为止,我已经能够在某种程度上使脚本的上述部分工作。当我运行使用我的插件的构建时,它会:
println Organization.mavenCorporate().name
时打印我的(当前硬编码的)存储库名称,因此我知道扩展正在运行。println project.repositories[0].name
时打印我的存储库名称,因此我知道项目知道存储库。该名称与上一个打印相同,并包含System.nanoTime()
,以确保它不会生成两次。此外,如果我打印默认对象的toString()
而不是其名称,则两个标识符都相同。但是,当构建尝试解析实际依赖项时,它会失败并显示以下消息:
Execution failed for task ':myproject:compileJava'.
> Could not resolve all dependencies for configuration ':myproject:compileClasspath'.
> Cannot resolve external dependency org.apache.logging.log4j:log4j-api:2.3 because no repositories are defined.
Required by:
project :myproject
> Cannot resolve external dependency org.apache.logging.log4j:log4j-web:2.3 because no repositories are defined.
Required by:
project :myproject
[...]
困扰我的是'因为没有定义存储库'部分。我希望它会因为很多不同的原因而失败,但不是这个原因。当我添加另一个不包含所需依赖项的存储库时,它会因另一种错误而失败。
我的插件是用Java编写的。我见过Gradle Plugin Portal的一个插件,其目的非常相似,但它是用Groovy编写的。它只是为project.repositories.metaClass
添加了一些方法。我不知道Groovy,但这看起来像一个快速而肮脏的解决方案,以避免以适当的方式处理Gradle的API。
截至目前,我有以下内容:
主要插件类:
public class MyPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
_printVersionInfo(project);
// this allows the use of Organization methods as Gradle DSL
project.getExtensions().create("Organization", Organization.class, project);
// this should add the repo to project's RepositoryManager
project.getRepositories().add(CustomRepository.getInstance(project));
}
[unrelated methods omitted]
}
自定义存储库类:
public class CustomRepository implements MavenArtifactRepository {
private static MavenArtifactRepository repo;
public static MavenArtifactRepository getInstance(Project project) {
if (repo == null) {
DefaultRepositoryHandler drh = (DefaultRepositoryHandler) project.getRepositories();
repo = drh.maven(new CustomRepoAction());
}
return repo;
}
[implemented methods from MavenArtifactRepository omitted for brevity; for debugging purposes, every method except getName() and getUrl() currently throws an UnsupportedOperationException]
}
扩展程序Organization
。仅包含mavenCorporate()
DSL方法,该方法返回使用与主插件类相同的MavenArtifactRepository
调用获得的CustomRepository.getInstance(project)
。
实现CustomRepoAction
的{{1}}类。仅包含Action<MavenArtifactRepository>
方法的实现,该方法设置作为参数传递的execute
的名称和网址。
我正在使用Java 8和Gradle 3.4。作为用户,我对Gradle相对较新,并且不熟悉Java 7和8的新功能。
<击>
我错过了什么吗?为什么Gradle不将MavenArtifactRepository
返回的MavenRepositoryArtifact
识别为存储库?我是否需要将存储库与项目,存储库处理程序或我不知道的任何类型的管理器对象绑定?
击>
Organization.mavenCorporate()
。我试过这样的事情:
DefaultRepositoryHandler
并且有效,将repositories {
mavenCentral()
maven Organization.mavenCorporateAction() /* instance of CustomRepoAction */
}
添加到项目的存储库中。但这并不能阻止用户访问存储库的内部,即密码。但是,MavenArtifactRepository
不允许我添加RepositoryHandler.maven(Action<? super MavenArtifactRepository> action)
的子类,我可以在其中控制此行为。
我是否需要实现MavenArtifactRepository
并使其成为项目的默认存储库处理程序?如果没有实现我自己的自定义RepositoryHandler
课程并且搞乱Gradle的内部结构,这是否可能?是否有一种清洁的方法来实现这一目标:
我希望用户能够使用标准
Project
插件 上传他们的工件,但没有他们知道存储库的 细节,即认证。
装饰,或任何暗示其他一切的默认行为变化很小或没有变化的东西?