Dynamically append to ivy publication configuration

Hi,

I have a plugin and I am trying to dynamically modify the publishing { repositories { … } } configuration (from ivy-publish). The idea is that a user will configure publishing { publications { … } } without having to worry about setting up the repositories. How can this be done?

Here are things that I have attempted:

Custom plugin:

void configurePublishing(project) {
     logger.info("Configuring publishing.repositories");
            // method A
     /*project.plugins.withType(IvyPublishPlugin) {
      PublishingExtension myext = project.extensions.findByType(PublishingExtension);
      myext.getRepositories().add(project.repositories.getByName("local"));
      myext.getRepositories().add(project.repositories.getByName("prerelease-put"));
     }*/
            // method B
     project.plugins.withType(IvyPublishPlugin) {
         project.extensions.configure PublishingExtension, new ClosureBackedAction( {
             publications {
                 repositories(IvyPublication) {
      project.publishing.repositories.add project.repositories.getByName("local")
      project.publishing.repositories.add project.repositories.getByName("prerelease-put")
     }
             }
         })
     }
    }
    void configureTasks(project) {
     logger.info("Adding task 'publish-local'");
            Gradle gradle = project.getGradle();
      //gradle.afterProject {
      project.task('publish-local', group:'publishing',
     description: 'Publishes Ivy publication ivy to Ivy repository local',
    dependsOn:'publishIvyPublicationToLocalRepository') {
    doLast {
     println 'publishing to ' + publishing.repositories.getByName("local").url
    }
   }
        logger.info("Adding task 'publish-prerelease'");
   project.task('publish-prerelease', group:'publishing',
     description: 'Publishes Ivy publication ivy to Ivy repository prerelease',
    dependsOn:'publishIvyPublicationToPrerelease-putRepository') {
    doLast {
     println 'publishing to ' + publishing.repositories.getByName("prerelease-put").url
    }
   }
  //}
      project.gradle.taskGraph.whenReady {
   logger.info("Prepending logic to task 'publishIvyPublicationToPrerelease-putRepository'");
   project.tasks.getByName("publishIvyPublicationToPrerelease-putRepository").doFirst {
    if ((!project.ext.has("allowPublish") || !project.ext.allowPublish) && (!"true".equalsIgnoreCase(System.getProperty("allowPublish")))) {
        throw new GradleException("Publishing to artifactory is disabled for local builds. Please use jenkins.")
       }
      }
  }
    }

project that applies plugin configuration:

// plugin applied earlier...
  publishing {
    publications {
        ivy(IvyPublication) {
             from components.java
                   descriptor {
          withXml {
           // Remove default configurations in lieu of our own
           asNode().configurations[0].value().clear()
                        project.configurations.each { conf ->
             def appendConfig = [name: conf.name, visibility: conf.isVisible()? "public" : "private", description:conf.description]
            def appendExtends = conf.extendsFrom.collect({ it.name }).join(",")
              if (appendExtends.length() > 0) {
             appendConfig["extends"] = appendExtends
            }
                          asNode().configurations[0].appendNode('conf', appendConfig)
           }
    }
   }
             artifacts.each( { it.conf = "master, runtime" } )
        }
    }
      // Want this portion to be automatic
 /*repositories {
  add project.repositories.getByName("local")
  add project.repositories.getByName("prerelease-put")
 }*/
}

Method A gives the following complaint: > Caused by: org.gradle.api.InvalidUserDataException: Cannot configure the ‘publishing’ extension after it has been accessed.

I believe this is because of this comment at http://www.gradle.org/docs/current/javadoc/org/gradle/api/publish/PublishingExtension.html “Any use that accesses the publishing extension as an instance does require the publishing extension to be realised, forcing all configuration blocks to be evaluated.”

Method B appears to create duplicate tasks: > gradle tasks > … > Publishing tasks > ---------------- > generateDescriptorFileForIvyPublication - Generates the Ivy Module Descriptor XML file for publication ‘ivy’. > generateDescriptorFileForRepositoriesPublication - Generates the Ivy Module Descriptor XML file for publication ‘repositories’. > publish - Publishes all publications produced by this project. > publish-local - Publishes Ivy publication ‘ivy’ to Ivy repository ‘local’ > publish-prerelease - Publishes Ivy publication ‘ivy’ to Ivy repository ‘prerelease’ > publishIvyPublicationToLocalRepository - Publishes Ivy publication ‘ivy’ to Ivy repository ‘local’. > publishIvyPublicationToPrerelease-putRepository - Publishes Ivy publication ‘ivy’ to Ivy repository ‘prerelease-put’. > publishRepositoriesPublicationToLocalRepository - Publishes Ivy publication ‘repositories’ to Ivy repository ‘local’. > publishRepositoriesPublicationToPrerelease-putRepository - Publishes Ivy publication ‘repositories’ to Ivy repository ‘prerelease-put’.

Is there a gradle hook to modify configurations as they are created (aka my publishing { … } in the project)? Is what I am attempting to do even possible?

Putting method A into gradle.afterProject seemed to do the trick. Not sure if what I am doing is good practice though…