Android Library - Publish Multiple Variants to Local Maven Repository using Gradle - android

I am using Android Gradle plugin 0.13.2, Android Studio 0.8.11, Gradle 2.1 and maven plugin.
I would like to install multiple variants (flavour + build type) of my Android Library to local Maven repository all with one command (task).
Currently Android Gradle plugin 0.13.2 allows me to set publishNonDefault flag to publishing all variants, but as the documentation states it will publish the variants with a classifier which is not compatible with Maven Repository.
My workaround right now is to use defaultPublishConfig "myVariant" and change it for every variant I have.
apply plugin: 'com.android.library'
apply plugin: 'maven'
android {
defaultPublishConfig "myVariant"
.
.
.
}
task installArchives(type: Upload) {
repositories.mavenInstaller {
configuration = configurations.getByName(Dependency.DEFAULT_CONFIGURATION)
pom.groupId = "com.company"
pom.artifactId = "mylibrary"
pom.version = "1.0.0-myVariant"
}
}
I would like to have a single task that would properly publish all variants to local Maven repository.

To solve this I had to create one Upload task for each variant and make them depend on each other and on a master task that starts the process.
apply plugin: 'com.android.library'
apply plugin: 'maven'
android {
.
.
.
}
// Master task that will publish all variants
def DefaultTask masterTask = project.tasks.create("installArchives", DefaultTask)
android.libraryVariants.all { variant ->
variant.outputs.each { output ->
// Configuration defines which artifacts will be published, create one configuration for each variant output (artifact)
def Configuration variantConfiguration = project.configurations.create("${variant.name}Archives")
project.artifacts.add(variantConfiguration.name, output.packageLibrary)
// Create one Upload type task for each configuration
def Upload variantTask = project.tasks.create("${variant.name}Install", Upload)
variantTask.configuration = variantConfiguration
variantTask.repositories.mavenInstaller {
pom.groupId = "com.yourcompany"
pom.artifactId = "yourLibrary"
pom.version = "1.0.0-${variant.name}" //Give a different version for each variant
pom.packaging = "aar"
}
// Make all tasks depend on each other and on master task
masterTask.dependsOn variantTask
masterTask = variantTask
}
}
The task installArchives will publish all variants to the local Maven repository.
./gradlew installArchives

Related

Upload archive for a library with flavors with gradle

I'm developing an SDK with multiple libraries and an example app to show how to use it. The libraries are uploaded in a local maven repo that the app uses to import them.
Everything works fine until I try to use different flavors for one of the libraries (and for the app).
When I have flavors, the uploadArchive task does not show any error but the library is not uploaded. All the other libraries are uploaded successfully.
I have found this: https://discuss.gradle.org/t/pom-files-for-multi-flavored-android-lib-not-published-on-uploadarchives-task/898
It is an old post but it does not have any answer.
Is it possible to upload one of the flavors of a library?
This is my archive.gradle file:
apply plugin: 'maven'
apply from: "../maven-repo.gradle"
uploadArchives {
repositories {
mavenDeployer {
def folder = "file://localhost" + myMavenRepoDir()
repository(url: folder)
pom.groupId = GROUP
pom.artifactId = POM_ARTIFACT_ID
pom.version = VERSION_NAME
pom.project {
name POM_NAME
packaging POM_PACKAGING
description POM_DESCRIPTION
}
}
}
}

Android AAR artifactory publish executes before assemble

I have an Android library project and I am trying to publish the AAR files to JFrog artifactory using gradle.
Once I have the AAR files and when I execute the build task, the publish is working as expected, the problem is that I am not able to do it as part of my build process if the AAR files are not there.
I want to publish the AAR files when ever a new one is available. I tried to put assembleIntegrated.finalizedBy (artifactoryPublish), but that didn’t help.
The publish task gets triggered before the AARs are generated.
mygradle.gradle -->
apply plugin: 'com.jfrog.artifactory'
apply plugin: 'maven-publish'
File AARFile1 = file("$buildDir/outputs/aar/my_aar_file1.aar")
File AARFile2 = file("$buildDir/outputs/aar/my_aar_file2.aar")
publishing {
publications {
AAR1(MavenPublication) {
groupId repoFolder
version libVersion
// Tell maven to prepare the generated "*.aar" file for publishing
if (AARFile1.exists()) {
artifactId libRelease
artifact(AARFile1)
} else {
println 'AAR1 files not found in' + AARFile1.absolutePath
}
}
AAR2(MavenPublication) {
groupId repoFolder
version libVersion
// Tell maven to prepare the generated "*.aar" file for publishing
if (AARFile2.exists()) {
artifactId libDebug
artifact(AARFile2)
} else {
println 'AAR2 files not found in' + AARFile2.absolutePath
}
}
}
}
artifactory {
contextUrl = "https://bintray.com/jfrog/artifactory:8080"
publish {
repository {
// The Artifactory repository key to publish to
repoKey = 'my_key'
username = 'my_username'
password = 'my_encrypt_password'
}
defaults {
// Tell the Artifactory Plugin which artifacts should be published to Artifactory.
if (AARFile1.exists() || AARFile2.exists()) {
publications('AAR1', 'AAR2')
publishArtifacts = true
// Properties to be attached to the published artifacts.
properties = ['qa.level': 'basic', 'dev.team':'Me' ]
// Publish generated POM files to Artifactory (true by default)
publishPom = true
}
}
}
}
I see the gradle tasks list as below:
executing tasks: [assembleIntegrated]
AAR1 files not found in /myfolder/.../my_lib_project/app/build/outputs/aar/my_aar_file1.aar
AAR2 files not found in /myfolder/.../my_lib_project/app/build/outputs/aar/my_aar_file2.aar
.
.
.
> Task :app:preBuild UP-TO-DATE
> Task :app:test UP-TO-DATE
> Task :app:check
> Task :app:build
> Task :app:artifactoryPublish
> Task :artifactoryDeploy
It happens, because you add files manually to the maven publication. When maven publish runs, these files are not exists. So, you should configure task dependencies manually. When you add a publication to your project, Gradle will generate some tasks with combination of your publication names, and repo names. Something like that: publish{publicationName}PublicationTo{RepositoryName}Repository. Thus, you should setup these task to depends on assembleIntegration task.
Or you can use android-maven-publish plugin, which do this work automatically.

Publishing multiple productFlavors and buildTypes to Artifactory

What is the best way to publish multiple Flavor to artifactory based on buildTypes?
Basically in the project I have 3 buildsTypes (dev, stage and production) and 2 productFlavors (androidPublic and androidPrivate) and I want to publish to the Artifactory
I'm using gitlabci to build my android project and I have basically 3 major stages: build, tests (unit and func), publish. Where the build stage is different from the publish stage, ie when I'm in the stage of publish my script gradle should consider that the artifacts are already generated.
Example: I build dev and two packages are generated
  - app-androidprivate-dev.apk
  - app-androidpublic-dev.apk
I want to send the two to the artifactory on stage Publish.
A short example of my build.gradle:
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.artifactory'
buildscript {
dependencies {
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.4.12"
}
}
publishing {
publications {
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
create("${variant.name.capitalize()}Apk", MavenPublication) {
groupId "app.android"
artifactId "app-${output.baseName}"
version '1.0.0'
artifact(output.outputFile)
}
}
}
}
repositories {
maven {
name 'artifactory'
url "${ARTIFACTORY_URL}/apks"
credentials {
username = "${ARTIFACTORY_USER}"
password = "${ARTIFACTORY_PWD}"
}
}
}
}
And on command line I run:
# gradle publishAndroidPrivateDebugApkPublicationToArtifactoryRepository -P....
# gradle publishAndroidPublicDebugApkPublicationToArtifactoryRepository -P....

Uploading a library to maven server

I am assigned a task of building a project using gradle and maven. The project consists of a main module and its supporting modules.
The supporting modules must be uploaded to artifact local maven repository as libraries and the main module will access them from there.
How do I upload the modules? How do I convert them to libraries?
Put this in your build.gradle of library/module
apply plugin: 'maven'
artifacts {
//put library path
archives file: file('build/aar/library.aar')
}
// Define maven repository path
def localRepoPath = "file://D:/m2repo"
uploadArchives {
repositories.mavenDeployer
{
repository(url: localRepoPath)
pom.artifactId = "your_artifact_id"
pom.groupId = 'com.your.groupid'
pom.version = android.defaultConfig.versionName
}
}
Run gradlew uploadArchives to deploy to local maven repo.

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 (i.e. '~/.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 standard maven-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.

Categories

Resources