简体   繁体   中英

Gradle Artifactory Plugin - How to publish artifacts from multiple modules in a project?

I have a project which has a SharedCode (Java) module and secondly an Android (Android library) module which depends on the SharedCode module. I want to publish a jar artifact from the SharedCode module and an aar artifact from the Android module. I can't figure out how to compose my build.gradle files so that both modules publish to Artifactory when the artifactoryPublish task is run. At the moment only the SharedCode module publishes its artifact to Artifactory.

My build.gradle files are as below. Note that the maven-publish aspect of my build.gradle files appears to be correct because when I run the publishToMavenLocal task I see the artifacts from both modules in my local Maven folder (ie '~/.m2/repository' ).

Firstly, the build.gradle file in my SharedCode module is as follows:

apply plugin: 'java'
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.artifactory'

group = "${projectGroupId}"
version = "${projectVersionName}"

dependencies {
    compile 'com.google.guava:guava:18.0'
}

publishing {
    publications {
        SharedCode(MavenPublication) {
            groupId "${projectGroupId}"
            artifactId 'SharedCode'
            version "${projectVersionName}"
            from components.java
        }
    }
}

artifactory {
    contextUrl = "${artifactory_url}"
    publish {
        repository {
            repoKey = 'libs-release-local'
            username = "${artifactory_username}"
            password = "${artifactory_password}"
        }
        defaults {
            publications('SharedCode')
            publishArtifacts = true
            properties = ['qa.level': 'basic', 'dev.team': 'core']
            publishPom = true
        }
    }
}

Secondly, the build.gradle file in my Android module is as follows:

apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.artifactory'

group = "${projectGroupId}"
version = "${projectVersionName}"

android {
    // android stuff here...
}

dependencies {
    compile project(':SharedCode')
}

publishing {
    publications {
        Android(MavenPublication) {
            groupId "${projectGroupId}"
            artifactId 'Android'
            version "${projectVersionName}"
            artifact "$buildDir/outputs/aar/Android-release.aar"
        }
    }
}

artifactory {
    contextUrl = "${artifactory_url}"
    publish {
        repository {
            repoKey = 'libs-release-local'
            username = "${artifactory_username}"
            password = "${artifactory_password}"
        }
        defaults {
            publications('Android')
            publishArtifacts = true
            properties = ['qa.level': 'basic', 'dev.team': 'core']
            publishPom = true
        }
    }
}

If I run the artifactoryPublish task at the root, project level or at the SharedCode module level then I see output as follows:

18:23:38: Executing external task 'artifactoryPublish'...
Publication named 'SharedCode' does not exist for project ':Android' in task ':Android:artifactoryPublish'.
:SharedCode:generatePomFileForSharedCodePublication
:SharedCode:artifactoryPublish
Deploying artifact: http://localhost:8081/artifactory/libs-release-local/com/mycompany/sdk/SharedCode/0.0.2/SharedCode-0.0.2.jar
Deploying artifact: http://localhost:8081/artifactory/libs-release-local/com/mycompany/sdk/SharedCode/0.0.2/SharedCode-0.0.2.pom
Deploying build descriptor to: http://localhost:8081/artifactory/api/build Build successfully deployed.
Browse it in Artifactory under http://localhost:8081/artifactory/webapp/builds/client-sdk/1457375019604

BUILD SUCCESSFUL

Note that only the SharedCode artifact is published in this case.

If I run the artifactoryPublish task at the Android module level, then I see output as follows:

18:25:25: Executing external task 'artifactoryPublish'...
Publication named 'SharedCode' does not exist for project ':Android' in task ':Android:artifactoryPublish'.
:Android:artifactoryPublish
Deploying build descriptor to: http://localhost:8081/artifactory/api/build
Build successfully deployed. Browse it in Artifactory under http://localhost:8081/artifactory/webapp/builds/client-sdk/1457375127269

BUILD SUCCESSFUL

Note that no artifacts are published in this case.

Update: As of version 4.6.0 of the com.jfrog.artifactory Gradle plugin, publishing artifacts in a multi-module project just does not work. From personal experience, you're best just abandoning this plugin and using the standardmaven-publish plugin for both Java library modules and Android library modules.

--- What follows below is my original answer before I posted the above update ---

So I've finally got this all working! Special thanks to @RaGe for helping me along the way. The key points to note are that the artifactory block needs to be in the project's root-level build.gradle file and not in the build.gradle file of the individual modules. Also, you need to add artifactoryPublish.skip=true to the project's root-level build.gradle file. See this GitHub repo for a full-on yet minimal-as-possible example:

https://github.com/adil-hussain-84/SO-35851251-Multiproject-Artifactory-Publish

In case the link ever stops working I'll paste the contents of the build.gradle files here also. Firstly, the project's root-level build.gradle file:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.5.0'
        classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:4.0.1'
    }
}

allprojects {
    apply plugin: 'com.jfrog.artifactory'

    repositories {
        jcenter()
    }

    group = "${projectGroupName}"
    version = "${projectVersionName}"
}

artifactoryPublish.skip=true

artifactory {
    contextUrl = "${artifactory_url}"
    publish {
        repository {
            repoKey = 'libs-release-local'
            username = "${artifactory_username}"
            password = "${artifactory_password}"
        }
        defaults {
        publications('SomePublication')
            publishArtifacts = true
            properties = ['qa.level': 'basic', 'dev.team': 'core']
            publishPom = true
        }
    }
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.8'
}

Secondly, the build.gradle file of the Android module:

apply plugin: 'com.android.library'
apply plugin: 'maven-publish'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 23
        versionCode Integer.parseInt("${projectVersionCode}")
        versionName "${projectVersionName}"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile project(':SharedCode')
    compile 'com.android.support:appcompat-v7:23.2.1'

    testCompile 'junit:junit:4.12'
}

publishing {
    publications {
        SomePublication(MavenPublication) {
            artifact "$buildDir/outputs/aar/Android-release.aar"

            //The publication doesn't know about our dependencies, so we have to manually add them to the pom
            pom.withXml {
                def dependenciesNode = asNode().appendNode('dependencies')

                //Iterate over the compile dependencies (we don't want the test ones), adding a <dependency> node for each
                configurations.compile.allDependencies.each {
                    def dependencyNode = dependenciesNode.appendNode('dependency')
                    dependencyNode.appendNode('groupId', it.group)
                    dependencyNode.appendNode('artifactId', it.name)
                    dependencyNode.appendNode('version', it.version)
                }
            }
        }
    }
}

Thirdly and finally, the build.gradle file of the SharedCode (Java) module:

apply plugin: 'java'
apply plugin: 'maven-publish'

dependencies {
    compile 'com.google.guava:guava:18.0'
}

publishing {
    publications {
        SomePublication(MavenPublication) {
            from components.java
        }
    }
}

That's it!

Going by artifactory multi-project examples on their github repo, it would seem that only the root project needs to have an artifactory{...} configuration section as opposed to in every sub-project as you have done.

Moreover when you declare publications('SharedCode') in the root project, artifactory plugin seems to be looking for a publication called sharedCode in every subproject.

I would try:

  • Remove the artifactory{...} section from the android build.gradle

  • Rename the android publication to sharedCode as well (or something more generic in both projects)

Version 4.2.0 of the Gradle Artifactory Plugin was released last week and added multiple Artifactory repositories deployment. Now you can simply define an artifactory closure with a different repository for different modules of the project.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM