首页 文章

Gradle:如何将规则创建的ZipTask作为maven发布工件

提问于
浏览
1

我想从RuleSource中创建一个maven出版物,该出版物将通过 maven-publish 插件发布 . 发布的工件是从规则创建的一系列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

有什么问题,我该如何解决?

1 回答

  • 0

    我不完全理解为什么这是"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是首先运行任务的mutator(@Defaults阶段应该在@Mutate之前运行)并保存任务,所以我们不需要在以后要求它们 . 规则可以包括静态最终字段,因此我们在此处使用列表 .

    然后我们运行发布增强器 . 您使用的代码不起作用 . 它适用于配置部分,但不适用于groovy类 . 所以我准备了发布,然后只是从缓冲区添加了工件 .

    我跑了 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'
    

    所以它似乎正在发挥作用 .

相关问题