Gradle: как сделать созданный по правилам ZipTask как артефакт публикации maven

Я хочу создать публикацию Maven из RuleSource, которая будет опубликована через 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 ответ

Решение

Я не до конца понимаю, почему это "цикл", но у методов правил всегда есть одна изменяемая часть (субъект) и ноль или более неизменяемых (входные данные). Во втором методе вы передаете 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)
            }
        }
    }
}

Хак здесь состоит в том, чтобы сначала запустить мутатор задач (фаза @Defaults должна запускаться до @Mutate) и сохранить задачи, поэтому нам не нужно запрашивать их позже. Правила могут включать в себя статические конечные поля, поэтому мы используем список здесь.

Затем мы запускаем энхансер публикации. Код, который вы использовали, не будет работать. Это работает в части конфигурации, но не в классном классе. Итак, я подготовил публикацию, а затем просто добавил артефакты из буфера.

Я побежал 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' 

Похоже, это работает.

Другие вопросы по тегам