How do we share our libraries internally?
In 2015, our Android team released v3 of Hootsuite’s app with a new UI following Material Design guidelines. We also gave users the Publisher feature, Instagram integration and enhanced Twitter Search. The development of these features relied on many popular open source libraries and tools, such as RxAndroid, Retrofit, Google Design, Robolectric, and many more. With the success of these libraries, our Android development team was inspired to build our own libraries to allow other teams to consume. A great idea, with a surprising complication: How do we share our library internally?
Our need was to be able to publish libraries to a private Maven repository like Artifcatory. We tweaked @chrisbanes‘s solution and made it available to our developers to enable them to write libraries independently and share them between teams.
In this post, I’m going to guide you in setting up your library to share your own Maven repository.
The Template Library Project
Most Android library projects share a similar directory structure, so we prepared a Library Template that will act as the reference for this guide. We encourage you to fork this project if you’re starting fresh.
Push it to Maven using Gradle
Setting up the library project focuses on the three files:
Publishing to a Remote Repository
maven_push.gradle in the project is a revised version of the maven_push.gradle from @chrisbanes. The original version already gave the ability to publish the library to a repository of the developer’s choice. Developers don’t need to modify the
maven_push.gradle, but I’d like to elaborate on the configurable sections.
uploadArchives gradle task is extended to use values from the project’s
An example of the values in the
From gradle.properties, developers can also specify the URLs of the release and snapshot repositories. Publishing to a snapshot repository is simply done by changing the value of the
VERSION_NAME to include the
-SNAPSHOT postfix. If the postfix is not present, the library will be deployed to the release repository. The following is an example of library setup to publish to a snapshot repository.
Authenticating with the Remote Repositories
With the details of the library filled in, the next step is to setup the location of the remote repositories and the credentials needed to authenticate with them. When you take a look back at the
maven_push.gradle file. You’ll notice that the
uploadArchives gradle task needs a username and password for the remote servers:
maven_upload.gradle authentication snippet:
The URLs to the release and snapshot repositories should be placed in the
gradle.properties of the project. The username and password, should instead be placed in
~/.gradle/gradle.properties to keep the credentials private and prevent from checking into the project by accident. The following is an example of the repository credentials being separate from the library details:
A tip to share from our experience at Hootsuite is to automate the publishing of your libraries using a continuous integration tool like Jenkins. Place the credential information in
~/.gradle/gradle.properties on the Jenkins server and create a job that checks out the library project from Git and runs the following command from inside the project:
> ./gradlew uploadArchives
In this manner, developers only need to setup the Jenkins server and not have to distribute the credentials to each developer’s computer.
Versioning Sets Healthy Boundaries
Every time developers publish to a repository, they release it with a version number. As the developer of a library, versioning is a way to mark major checkpoints in their library’s development. These checkpoints allow the developer to continue iterating on the library with new features and fixes without impacting consumers. When the library is ready to release its next phase of features, it stamps it with a new version. By using specific versions of libraries, consumers expect no changes that could suddenly impact their app.
Versioning enables the development of consuming apps and libraries to be independent of one another. For a team, having multiple libraries and versions available are opportunities for faster and more independent development. Each library’s versioning establishes a contract and boundaries that help identify the capabilities and limits.
Tip: Use the Local Maven Repository for Development
In our experience in development, there is a lot of trial and error when integrating libraries to projects. We often find the need to quickly change the library’s code and then rebuild the project again to get the latest fixes from the library. Imagine if every minor change to the library needed to deploy remotely to a repository, which in turn is downloaded and updated in the project. The turnaround time to getting the updates would be atrocious. Why not just publish the library to a local repository and reference that version during development.
In our version of the
maven_push.gradle, we extended the
installArchives gradle task to install the library to the developer’s local Maven repository. This local Maven repository can be referenced as a valid Maven repository for other projects to consume from. If the library project has already been setup by following the previous sections, no extra work is needed.
When a change is made to the library and the developer wants verify the changes, they need only to run the following command line and then refresh the consuming project to get the changes:
> ./gradlew installArchives
This has been a huge time saver and developers on the team are able to iterate more quickly on their libraries.
@davidgraig, @benhergert, and @paulrc for their constant encouragement and support for building reusable libraries. Special thanks goes to @chrisbanes for creating the first version that made this all possible.
Open Sourcing a library is not always an option for developers in enterprises. Allowing developers to publish their libraries to a private repository to be shared by others in the same organization goes hand in hand with protecting intellectual property. This further should motivate developers to think more about Library Oriented Programming when developing any project or app.
About the Author
Simon Tse is an Android developer on the mobile team at Hootsuite. He enjoys testing the limits of new technologies and ideas in his apps. Follow him on Twitter @simtse.