2017-01-28 2 views
1

Je souhaite créer une publication maven à partir d'un RuleSource qui sera publié via le plugin maven-publish. Les artefacts de la publication sont les résultats d'une série de tâches Zip créées à partir de règles. Lorsque j'essaie d'ajouter les artefacts, j'obtiens une exception de règle circulaire.Gradle: comment créer un ZipTask créé par une règle en tant qu'artefact de publication maven

Voici ma très simple 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' 
} 

Le plugin testpub existe dans le répertoire buildSrc. Pour pouvoir l'appliquer comme ci-dessus, il faut déposer les propriétés suivantes:

// buildSrc/src/main/resources/META_INF/gradle-plugins/testpub.properties 
implementation-class=TestPubPlugin 

Voici le fichier plugin très simple:

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) 
         } 
        }  
       }   
      } 
     } 
    } 
} 

Le plugin crée un certain nombre de tâches appelé someTaskxx=[0..4]. Ils se contentent de compresser le répertoire src. Je veux ajouter les fichiers de sortie en tant qu'artifacts à la publication MavenPublication unique. Cependant, j'obtiens l'exception suivante:

* 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 

Qu'est-ce qui ne va pas et comment le réparer?

Répondre

0

Je ne comprends pas pourquoi c'est un "cycle", mais les méthodes de règles ont toujours une partie mutable (le sujet) et zéro ou plus immuable (les entrées). Dans votre deuxième méthode, vous passez le publishing comme sujet que vous souhaitez modifier et le tasks comme entrée. Je pensais que ça irait, mais évidemment ce n'est pas le cas.

Vous avez peut-être essayé de changer les arguments de la méthode, d'abord passer les tâches puis le PublishingExtension, mais vous ne pourrez probablement pas le changer (car les docs graduels disent qu'il est immuable).

Je ne sais pas exactement quel est votre cas d'utilisation et il pourrait y avoir une solution plus facile qui n'utilise pas les règles, ou le plugin du tout. Peut-être que vous pourriez poser une autre question avec l'exigence originale au lieu de ce problème spécifique.

Mais revenons à votre problème. La solution à votre problème pourrait être quelque chose comme ceci:

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) 
      } 
     } 
    } 
} 

Le hack est ici pour lancer le mutator des tâches première (@Defaults phase devrait fonctionner avant @Mutate) et enregistrer les tâches, donc nous ne besoin de les demander plus tard. Les règles peuvent inclure des champs finals statiques, donc nous utilisons une liste ici.

Ensuite, nous exécutons l'enhancer de publication. Le code que vous avez utilisé ne fonctionnera pas. Cela fonctionne dans la partie config, mais pas dans la classe groovy. J'ai donc préparé la publication et ensuite ajouté les artefacts du tampon.

j'ai couru gradlew publish et obtenu:

Execution failed for task ':publishMavenPublicationToMavenRepository'. 
> Failed to publish publication 'maven' to repository 'maven' 
    > Invalid publication 'maven': artifact file does not exist: 'build\someZip0.zip' 

Il semble donc qu'il fonctionne.