Gradle: 如何将规则创建的 ZipTask 作为 maven 发布工件
Gradle: how to make rule-created ZipTask as maven publication artifact
我想从将通过 maven-publish
插件发布的 RuleSource 内部创建一个 Maven 发布。发布的工件是根据规则创建的一系列 Zip 任务的输出。当我尝试添加工件时,出现循环规则异常。
这是我的非常简单的build.gradle
:
buildscript {
repositories {
mavenCentral()
}
dependencies {
}
}
task wrapper(type: Wrapper) {
gradleVersion = '3.3'
}
apply plugin: 'groovy'
apply plugin: 'testpub'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.4.7'
}
testpub
插件存在于 buildSrc
目录中。为了能够像上面那样应用它,它需要以下属性文件:
// buildSrc/src/main/resources/META_INF/gradle-plugins/testpub.properties
implementation-class=TestPubPlugin
这是非常简单的插件文件:
import org.gradle.api.Project
import org.gradle.api.Plugin
import org.gradle.model.RuleSource
import org.gradle.api.Task
import org.gradle.model.Mutate
import org.gradle.model.Finalize
import org.gradle.api.tasks.bundling.Zip
import org.gradle.model.ModelMap
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
class TestPubPlugin implements Plugin<Project> {
void apply(Project project) {
project.configure(project) {
apply plugin: 'maven-publish'
publishing {
repositories {
maven {
url "someUrl"
}
}
}
}
}
static class TestPubPluginRules extends RuleSource {
@Mutate
public void createSomeTasks(final ModelMap<Task> tasks) {
5.times { suffix ->
tasks.create("someTask${suffix}", Zip) {
from "src"
destinationDir(new File("build"))
baseName "someZip${suffix}"
}
}
}
@Mutate
public void configurePublishingPublications(final PublishingExtension publishing, final ModelMap<Task> tasks) {
// Intention is to create a single publication whose artifacts are formed by the `someTaskx` tasks
// where x = [0..4]
publishing {
publications {
mavPub(MavenPublication) {
tasks.matching {it.name.startsWith('someTask')}.each { task ->
artifact(task)
}
}
}
}
}
}
}
该插件创建了许多名为 someTaskx
的任务,其中 x=[0..4]
。他们只是简单地压缩 src 目录。我想将输出文件作为工件添加到单个 MavenPublication。但是,我收到以下异常:
* What went wrong:
A problem occurred configuring root project 'testpub'.
> A cycle has been detected in model rule dependencies. References forming the cycle:
tasks
\- TestPubPlugin.TestPubPluginRules#createSomeTasks(ModelMap<Task>)
\- MavenPublishPlugin.Rules#realizePublishingTasks(ModelMap<Task>, PublishingExtension, File)
\- PublishingPlugin.Rules#tasksDependOnProjectPublicationRegistry(ModelMap<Task>, ProjectPublicationRegistry)
\- projectPublicationRegistry
\- PublishingPlugin.Rules#addConfiguredPublicationsToProjectPublicationRegistry(ProjectPublicationRegistry, PublishingExtension, ProjectIdentifier)
\- publishing
\- TestPubPlugin.TestPubPluginRules#configurePublishingPublications(PublishingExtension, ModelMap<Task>)
\- tasks
出了什么问题,我该如何解决?
我不完全理解为什么这是 "cycle",但规则方法总是有一个可变部分(主题)和零个或多个不可变部分(输入)。在第二种方法中,您将 publishing
作为要更改的主题传递,并将 tasks
作为输入传递。我以为这样就可以了,但显然不是。
您可能尝试过切换方法参数,先传递任务然后传递 PublishingExtension
,但您可能无法更改它(因为 gradle 文档说它是不可变的) .
我不确定您的用例到底是什么,可能有一个更简单的解决方案,它根本不使用规则或插件。也许你可以用原始需求问另一个问题而不是这个特定问题。
但是回到你的问题。您的问题的解决方案可能是这样的:
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.bundling.Zip
import org.gradle.model.Defaults
import org.gradle.model.ModelMap
import org.gradle.model.Mutate
import org.gradle.model.RuleSource
class TestPubPlugin implements Plugin<Project> {
void apply(Project project) {
project.configure(project) {
apply plugin: 'maven-publish'
publishing {
publications {
maven(MavenPublication) {
groupId 'com.example'
artifactId 'artifact'
}
}
repositories {
maven {
url "someUrl"
}
}
}
}
}
static class TestPubPluginRules extends RuleSource {
static final def buffer = []
@Defaults
public void createSomeTasks(final ModelMap<Task> tasks) {
5.times { suffix ->
tasks.create("someTask${suffix}", Zip) {
from "src"
destinationDir(new File("build"))
baseName "someZip${suffix}"
}
}
tasks.each { task ->
if (task.name.startsWith('someTask'))
buffer << task
}
}
@Mutate
public void configurePublishingPublications(PublishingExtension extension) {
MavenPublication p = extension.publications[0]
buffer.each { task ->
p.artifact(task)
}
}
}
}
这里的 hack 是首先 运行 任务的修改器(@Defaults 阶段应该 运行 在 @Mutate 之前)并保存任务,所以我们不需要请求它们之后。规则可以包含静态最终字段,所以我们在这里使用列表。
然后我们 运行 发布增强器。您使用的代码将不起作用。它适用于配置部分,但不适用于 groovy class。所以我准备了出版物,然后从缓冲区中添加了工件。
我运行gradlew publish
得到:
Execution failed for task ':publishMavenPublicationToMavenRepository'.
> Failed to publish publication 'maven' to repository 'maven'
> Invalid publication 'maven': artifact file does not exist: 'build\someZip0.zip'
所以它似乎有效。
我想从将通过 maven-publish
插件发布的 RuleSource 内部创建一个 Maven 发布。发布的工件是根据规则创建的一系列 Zip 任务的输出。当我尝试添加工件时,出现循环规则异常。
这是我的非常简单的build.gradle
:
buildscript {
repositories {
mavenCentral()
}
dependencies {
}
}
task wrapper(type: Wrapper) {
gradleVersion = '3.3'
}
apply plugin: 'groovy'
apply plugin: 'testpub'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.4.7'
}
testpub
插件存在于 buildSrc
目录中。为了能够像上面那样应用它,它需要以下属性文件:
// buildSrc/src/main/resources/META_INF/gradle-plugins/testpub.properties
implementation-class=TestPubPlugin
这是非常简单的插件文件:
import org.gradle.api.Project
import org.gradle.api.Plugin
import org.gradle.model.RuleSource
import org.gradle.api.Task
import org.gradle.model.Mutate
import org.gradle.model.Finalize
import org.gradle.api.tasks.bundling.Zip
import org.gradle.model.ModelMap
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
class TestPubPlugin implements Plugin<Project> {
void apply(Project project) {
project.configure(project) {
apply plugin: 'maven-publish'
publishing {
repositories {
maven {
url "someUrl"
}
}
}
}
}
static class TestPubPluginRules extends RuleSource {
@Mutate
public void createSomeTasks(final ModelMap<Task> tasks) {
5.times { suffix ->
tasks.create("someTask${suffix}", Zip) {
from "src"
destinationDir(new File("build"))
baseName "someZip${suffix}"
}
}
}
@Mutate
public void configurePublishingPublications(final PublishingExtension publishing, final ModelMap<Task> tasks) {
// Intention is to create a single publication whose artifacts are formed by the `someTaskx` tasks
// where x = [0..4]
publishing {
publications {
mavPub(MavenPublication) {
tasks.matching {it.name.startsWith('someTask')}.each { task ->
artifact(task)
}
}
}
}
}
}
}
该插件创建了许多名为 someTaskx
的任务,其中 x=[0..4]
。他们只是简单地压缩 src 目录。我想将输出文件作为工件添加到单个 MavenPublication。但是,我收到以下异常:
* What went wrong:
A problem occurred configuring root project 'testpub'.
> A cycle has been detected in model rule dependencies. References forming the cycle:
tasks
\- TestPubPlugin.TestPubPluginRules#createSomeTasks(ModelMap<Task>)
\- MavenPublishPlugin.Rules#realizePublishingTasks(ModelMap<Task>, PublishingExtension, File)
\- PublishingPlugin.Rules#tasksDependOnProjectPublicationRegistry(ModelMap<Task>, ProjectPublicationRegistry)
\- projectPublicationRegistry
\- PublishingPlugin.Rules#addConfiguredPublicationsToProjectPublicationRegistry(ProjectPublicationRegistry, PublishingExtension, ProjectIdentifier)
\- publishing
\- TestPubPlugin.TestPubPluginRules#configurePublishingPublications(PublishingExtension, ModelMap<Task>)
\- tasks
出了什么问题,我该如何解决?
我不完全理解为什么这是 "cycle",但规则方法总是有一个可变部分(主题)和零个或多个不可变部分(输入)。在第二种方法中,您将 publishing
作为要更改的主题传递,并将 tasks
作为输入传递。我以为这样就可以了,但显然不是。
您可能尝试过切换方法参数,先传递任务然后传递 PublishingExtension
,但您可能无法更改它(因为 gradle 文档说它是不可变的) .
我不确定您的用例到底是什么,可能有一个更简单的解决方案,它根本不使用规则或插件。也许你可以用原始需求问另一个问题而不是这个特定问题。
但是回到你的问题。您的问题的解决方案可能是这样的:
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.bundling.Zip
import org.gradle.model.Defaults
import org.gradle.model.ModelMap
import org.gradle.model.Mutate
import org.gradle.model.RuleSource
class TestPubPlugin implements Plugin<Project> {
void apply(Project project) {
project.configure(project) {
apply plugin: 'maven-publish'
publishing {
publications {
maven(MavenPublication) {
groupId 'com.example'
artifactId 'artifact'
}
}
repositories {
maven {
url "someUrl"
}
}
}
}
}
static class TestPubPluginRules extends RuleSource {
static final def buffer = []
@Defaults
public void createSomeTasks(final ModelMap<Task> tasks) {
5.times { suffix ->
tasks.create("someTask${suffix}", Zip) {
from "src"
destinationDir(new File("build"))
baseName "someZip${suffix}"
}
}
tasks.each { task ->
if (task.name.startsWith('someTask'))
buffer << task
}
}
@Mutate
public void configurePublishingPublications(PublishingExtension extension) {
MavenPublication p = extension.publications[0]
buffer.each { task ->
p.artifact(task)
}
}
}
}
这里的 hack 是首先 运行 任务的修改器(@Defaults 阶段应该 运行 在 @Mutate 之前)并保存任务,所以我们不需要请求它们之后。规则可以包含静态最终字段,所以我们在这里使用列表。
然后我们 运行 发布增强器。您使用的代码将不起作用。它适用于配置部分,但不适用于 groovy class。所以我准备了出版物,然后从缓冲区中添加了工件。
我运行gradlew publish
得到:
Execution failed for task ':publishMavenPublicationToMavenRepository'.
> Failed to publish publication 'maven' to repository 'maven'
> Invalid publication 'maven': artifact file does not exist: 'build\someZip0.zip'
所以它似乎有效。