Maven-publish repositories in root project

Hi…

please bear with me, I am new to Gradle.

I have now managed to convert some larger multi project build from maven and it works fine. For publishing artifacts, I use the maven-publish plugin. Publishing works fine to out corporate repository when I define the publishing{repositories{maven {…}}} code in each subproject. This is a lot of duplication and I would rather like to define just the repositories in the root project.

I tried to import or not maven-publish, define the publishing{repositories{maven {…}}} block in the root or inside subproject block, but to no avail. When I do a gradle tasks for root project or one of the subprojects, the task publishJarPublicationToMyCorporateMavenLocalRepository does not show up.

Any idea what I do wrong here would be appreciated.

Ciao

…Jochen

Hi Jochen

Could you provide a very simple representation of your .gradle files (build.gradle, settings.gradle…) so we can pinpoint the problem?

Hi Francois…

sure. I created a very simple project using gradle 2.4 with one subproject (please find the gradle file content near the bottom of this message). You can just do a “gradle init —type java-library”, create a folder ‘sub’ move the src folder into it and put the below gradle file contents.

In the below form, a “gradle tasks” prints the publishing task just fine:

publishJarPublicationToMyCompanyDevMavenRepository - Publishes Maven publication ‘jar’ to Maven repository ‘myCompanyDevMaven’.

Now I would like to define the publishing{repositories{}}} definition block in the root project instead of each sub project (here only one for brevity).

Any idea?

Ciao

…Jochen

settings.gradle:

  include 'sub'
  rootProject.name = 'GradleDemo'

root project build.gradle:

  subprojects {
      repositories {
          jcenter()
      }
  }

sub project build.gradle:

  apply plugin: 'java'
  apply plugin: 'maven-publish'
  
  group = 'com.foo'
  version = '0.1.0' 
  
  dependencies {
      testCompile 'junit:junit:4.11'
  }
  
  publishing {
      publications {
          jar(MavenPublication) {
              from components.java
              artifactId "$rootProject.name-$project.name"
          }
      }
      repositories {
          maven {
              name 'myCompanyDevMaven'
              description 'MyCompany developer repository.'
              url(project.version.endsWith('-SNAPSHOT') ? 'some-snapshot-url' : 'some-release-url')
              credentials {
                  username = ''
                  password = ''
              }
          }
      }
  }

@Jochen Would you mind formatting your code? It’s very hard to read.

Ah I see, had to add some pre tags :-). Sorry for that.

Ciao

…Jochen

If you apply the maven-publish plug-in and your publishing{repositories{} } block in the root project’s subproject block, it should work.

Hi Francois…

sadly, it does not, I had tried this already. The additional tasks are not shown, neither in the root (gradle tasks) nor with gradle :sub:tasks.

Ciao

…Jochen

By looking at the source code from MavenPublishPlugin, the tasks shall be created by mutating the tasks container (using new rules mechanism). The rule based mechanism ensures that the mutate rule inputs (eg the PublishingExtension) are fully realized before the rule is executed. So the PublishingExtension shall be realized and therefore contain the repositories you added.
Maybe this does not work well with subprojects and ‘by type’ declarations. Anyone has a better idea?

Hi Francois…

thank you for looking into this. After a longer reading session I discovered this page in the Gradle docs:
https://docs.gradle.org/current/dsl/org.gradle.api.publish.PublishingExtension.html

At the very bottom it says

At this time, only repositories created by the ivy() factory method have any effect. Please see IvyPublication for information on how this can be used for publishing to Ivy repositories.

I am not absolutely sure, but as I use maven repositories this might well explain the problem, or what do you think?

For now I dropped back to groovy, defined a method in the root project like this:

def configurePublishingRepositories(repositoryHandler) {
    repositoryHandler.maven {
        name 'myCompanyMavenLocal'
        url myCompanyMavenLocalRepoUrl
    }
}

and call it in each subproject like this:

publishing {
    repositories {
        configurePublishingRepositories(delegate)
    }
}

This exposes DSL internals (delegate) and will probably give some coworkers a headache but at least it removes the duplication for now.

Ciao

…Jochen

1 Like

In my own use cases, I use the ivy-publish plugin.
I assumed it was purely identical with the maven-publish plugin.
It seems not to be the case at the moment.

But this seems weird anyway, because when you compare


and
https://github.com/gradle/gradle/blob/master/subprojects/maven/src/main/groovy/org/gradle/api/publish/maven/plugins/MavenPublishPlugin.java
the logic is the same:
a @Mutate Rule source is used the create the publication task for each pair (Ivy/Maven publication | Ivy/Maven repo)

now here I really can not say much as a Gradle newbie, but indeed the code looks like it should do similar things in both cases.