Publish Android Library Artifacts to  private Amazon S3 Maven repository
Tags: android, aws, gradle
Published: 2021-01-04 09:16:59

Publishing an android library benefits an organization or community in a lot of ways. This post is more behind the scenes on how-to publish library artifacts to a private amazon s3 bucket. So without further ado let's jump right into it.

## Overview

In this post we'll be focusing on publishing library artifacts to amazon s3 bucket so as a prerequisite I assume that we already have an android library ready.

## Setting up a private Amazon S3 Maven repository

Let's start with setting up a private amazon s3 bucket. Head over to [amazon s3 console](https://console.aws.amazon.com/s3) and select s3 from services tab.

![Screenshot 2021-01-04 at 3.38.25 AM](https://dev-to-uploads.s3.amazonaws.com/i/5t8z4uftmirs9p0mtppw.png)
 
Then select create bucket and follow the instructions, remember the bucket name needs to be unique so we can use something like our library package name like com.organization.library. 
Now our bucket is ready and we can use it to serve dependencies.

## Gradle script to upload artifacts 

Create a file called `gradle/gradle-library-push.gradle` which will be used to push our artifacts to s3 bucket with gradle-maven plugin when using `./gradlew publish` command.

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

// update these next lines to fit your specification
group = 'com.android.library'
version = '1.0'

// Add sources as an artifact
task sourceJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier "source"
}

// Loop over all variants
android.libraryVariants.all { variant ->
    variant.outputs.all { output ->
        // This creates a publication for each variant
        publishing.publications.create(variant.name, MavenPublication) {
            // The sources artifact from earlier
            artifact sourceJar

            // Variant dependent artifact, e.g. release, debug
            artifact source: output.outputFile, classifier: output.name

            // Go through all the dependencies for each variant and add them to the POM
            // file as dependencies
            pom.withXml {
                def dependencies = asNode().appendNode('dependencies')

                // Filter out anything that's not an external dependency. You shouldn't
                // be publishing artifacts that depend on local (e.g. project) dependencies,
                // but who knows...
                configurations.getByName(variant.name + "CompileClasspath").allDependencies
                        .findAll { it instanceof ExternalDependency }
                        .each {
                            def dependency = dependencies.appendNode('dependency')

                            dependency.appendNode('groupId', it.group)
                            dependency.appendNode('artifactId', it.name)
                            dependency.appendNode('version', it.version)
                        }
            }
        }
    }
}

// Ensure that the publish task depends on assembly
tasks.all { task ->
    if (task instanceof AbstractPublishToMaven) {
        task.dependsOn assemble
    }
}

// Configure the destination repository with
// S3 URL and access credentials
publishing {
    repositories {
        maven {
            //aws bucket link
            url "YOUR_S3_BUCKET_URL"
            //aws credentials
            credentials(AwsCredentials) {
                accessKey "YOUR_ACCESS_KEY"
                secretKey "YOUR_SECRET_KEY"
            }
        }
    }
}

// Top-level build file where you can add configuration
options common to all sub-projects/modules.
buildscript {
    ext.kotlin_version = '1.4.10'
    repositories {
        google()
        jcenter()
        maven {
            url = uri("https://plugins.gradle.org/m2/")
        }
    }
}
```

Then we will include it in our library's build.gradle file.
`apply from: rootProject.file('gradle/gradle-library-push.gradle')`
Now that we have our gradle script and amazon bucket ready, let's get ready for action. Execute the following command from terminal `./gradlew library:publish`

## Using new dependency in projects.

Include the following in your root build.gradle file 
```
allprojects {
    repositories {
        google()
        jcenter()
        maven {
            url "YOUR_S3_BUCKET_URL"
            credentials(AwsCredentials) {
                accessKey "YOUR-ACCESS-KEY"
                secretKey "YOUR-SECRET-KEY"
            }
        }
    }
}
```


## References

1. https://github.com/codepath/android_guides/wiki/Building-your-own-Android-library#setting-up-a-private-amazon-s3-maven-repository

2. https://medium.com/@porten/publishing-android-library-artifacts-to-amazon-s3-buckets-8db4231e844f