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'
Похоже, это работает.