How To Set Up a Continuous Integration Process in the Cloud
Tags: build, cloud, english, bintray
Published: 2019-06-04 21:35:43

---
title: How To Set Up a Continuous Integration Process in the Cloud
published: true
tags: Build,Cloud,English,Bintray
canonical_url: 
---

> If it’s not on Maven Central, it doesn’t exist!

Having a library not on [Maven Central](http://search.maven.org) or at least on [Bintray](https://bintray.com) is not state of the art. I mean, we are in 2016 and most of the developers would like to use Maven, Gradle or other modern build systems for resolving library dependencies against artifact repositories automatically.

However, the challenge is not only to get a library into these repositories anyhow, but to get them in automatically through a continuous integration process.

I took the opportunity to set up such a process for a standardization organization, members of which are maintaining a reference implementation of a standard widely used in a whole industry.

The setup is not very complex, but nowhere I had found it written down at once. So I will do it here for all others who need a similar solution, hoping it is valuable for them. And, I do it also as documentation for the members of this committee.

# Tools and Services

I will use the following cloud services and tools:

1. [Github.com](https://github.com) for source code hosting and release control
2. [Travis-CI.org](https://travis-ci.org) for running compilation, tests, and library publishing
3. [Bintray.com](https://bintray.com/) for repository hosting and publishing to Maven Central
4. [Gradle](http://gradle.org/) as build system tool
5. [Stefan Oehme’s sobula Gradle plug-in](https://plugins.gradle.org/plugin/com.github.oehme.sobula.bintray-release) for releasing to Bintray

In fact, [Stefan’s article](http://mnmlst-dvlpr.blogspot.de/2014/12/my-lightweight-release-process.html#gpluscomments) was my starting point for this work and his Gradle plug-in the most helpful tool as releasing to Bintray trough their HTTP service API is the main challenge in this whole process. Thanks to his work resulting in his plug-in, I can implement the process without real programming efforts.

This article shows my experiences to set up a CI process for an organization. To set it up for a single developer is very similar and less complicated. I have it also done (before) for my [own libraries](https://bintray.com/kuniss/maven).

# GitHub

The first step is to setup an organization after having logged in to GitHub (a GitHub account is needed for that, of course). Goto your profile page and click the _Organization_ menu entry on the menu shown under Personal settings. There will appear a (may be empty) list of already created organizations. On the right upper corner there will be a button for creating a new organization.

[![GitHub dialog for creating an organization](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gitub1-create-new-org.png)](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gitub1-create-new-org.png)<figcaption>GitHub dialog for starting creation of an organization</figcaption>

Pushing this button will ask you for the organization’s name and a billing plan.

[![GitHub dialog for creating an organization](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gitub2-create-new-org.png)](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gitub2-create-new-org.png)<figcaption>GitHub dialog for creating an organization</figcaption>

As we are planning to utilize Travis-CI.org and Bintray we must give them access to our GitHub organization’s account. This may be done on the _OAuth applications_ dialog in the personal settings.

[![GitHub OAuth applications dialog](http://blog.grammarcraft.de/wp-content/uploads/2016/04/github3-authorize-applications.png)](http://blog.grammarcraft.de/wp-content/uploads/2016/04/github3-authorize-applications.png)<figcaption>GitHub OAuth applications dialog</figcaption>

To get the third party applications displayed it may be necessary to create accounts on Travis-CI.org and Bintray. You may log in there trough your GitHub account; look for appropriate GitHub icons on the the side’s login pages.

After that, click on the _bintray_ and _Travis CI_ links on that page. Check on the subsequent dialog that the particular application is allowed to access your organization. If not, push the appropriate button right from your organization on this page.

[![GitHub dialog for authorizing access for Travis CI third party application](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gitub4-give-travis-ci-access-to-org.png)](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gitub4-give-travis-ci-access-to-org.png)<figcaption>GitHub dialog for authorizing access for Travis CI third party application</figcaption>

Do the same for the second application, here Bintray.

[![GitHUb dialog authorizing access for Bintray](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gitub5-give-bintray-access-to-org.png)](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gitub5-give-bintray-access-to-org.png)<figcaption>GitHub dialog authorizing access for Bintray</figcaption>

Now all is prepared for setting up source code repositories for your organization. I had set up 5 repositories for the [committee reference implementation](https://github.com/JavaPOSWorkingGroup).

# Bintray

The GitHub integration on Bintray is done quite well. An organization would be visible on your’s users profile page. Unfortunately, either Stefan Oehme’s Gradle Bintray publishing plugin or Bintray’s service API itself is not able to handle an automatic publishing for organizations. However, for ordinary users it works well. Therefore, I have registered an own generic user for the organization. Its account will host the libraries we want to publish.

[![Bintray sign up dialog](http://blog.grammarcraft.de/wp-content/uploads/2016/04/bintray-sign-up.png)](http://blog.grammarcraft.de/wp-content/uploads/2016/04/bintray-sign-up.png)<figcaption>Bintray sign up dialog</figcaption>

For an automatic publishing several other preconditions must be met on Bintray. At first, we need a  Bintray API key. This key is used like a password to authorize Bintray API calls from the Travic CI service. This API key may be generated at the Bintray user profile when clicking on the _API Key_ menu.

[![Bintray API key dialog](http://blog.grammarcraft.de/wp-content/uploads/2016/04/bintray-gen-api-key.png)](http://blog.grammarcraft.de/wp-content/uploads/2016/04/bintray-gen-api-key.png)<figcaption>Bintray API key dialog</figcaption>

This key will later be copied to the project’s Travis CI configuration dialogs. However, that’s not all. For publishing to Maven Central from Bintray all Java libraries must be digitally signed. Bintray supports signing of published libraries trough their service APIs. However, the cryptographic key pair for that must be stored at Bintray.

## GPG Keys

For that, we need to generate a pair of public and private cryptographic keys. The easiest way to do that is using the Linux command line tool _gpg_. Fortunately, I’m developing under Linux. The command line for generating a new pair is

```
gpg --gen-key
```

which will guide you trough the key generation, interactively. During this process you must be prepare to enter some names which should be chosen judicious.

1. Your organization’s real name.
2. An email address of our organization which is related to the context of building libraries. This might be a generic one, e.g. builder@your-organization.org; but emails send to it should be caught by some one.
3. A pass-phrase to protect your key pair from misuse. This is something like a password to your keys to avoid some one else, not authorized, is misuse them. In fact this pass-phrase is stored later on at Travis CI to allow digital signing through the Bintray service using the private key stored at Bintray.

From this _gpg_ will create the generated key’s user ID. The pass-phrase will be requested to be entered in a special dialog box, not shown here.

[![Generating digital key pair using gpg](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gpp-gen-key.1.png)](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gpp-gen-key.1.png)<figcaption>Generating digital key pair using gpg</figcaption>

For being prepared for the future you should also create a key revocation certificate now. The command for that is

```
gpg --output revoke.asc --gen-revoke \<your key ID\>
```

[![Creating key revocation certificate using gpg](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gpg-revoke-cert.png)](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gpg-revoke-cert.png)<figcaption>Creating key revocation certificate using gpg</figcaption>

For storing the public and the private key on Bintray, you have to export them into an text file. Bintray needs it in an amored format

```
gpg --armor --output public.gpg --export \<your key ID\>
```

[![Exporting public key using gpg](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gpg-export-public-key.png)](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gpg-export-public-key.png)<figcaption>Exporting public key using gpg</figcaption>

The command for the private key is similar:

```
gpg --armor --output private.gpg --export-secret-key \<your key ID\>
```

Be prepared to enter the pass-phrase when export is requested.

The last step is to publish the public key to a public key server. This key server will be queried later on by the Maven Central service when the library gets published to Maven Central repository to check the digital signature.

The _gpg_ command for that is

```
gpg --keyserver \<public keyserver address\> --send-keys \<your key ID\>
```

On my side the key ID used for export did not work. I did not figured out why. So, I used the hexadecimal ID shown by the list-key command.

[![Sending public key to a public key server](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gpg-sending-key-to-keyserver.png)](http://blog.grammarcraft.de/wp-content/uploads/2016/04/gpg-sending-key-to-keyserver.png)<figcaption>Sending public key to a public key server</figcaption>

**Note:** Never use your ordinary cryptographic key pair, what you use in correspondences, for library signing. Even if the pass-phrase and the private key are stored at different service, Bintray and Travis-CI, some one who may have control over both, may compromise your keys! Just create a new one. You may have more than one key in use with _gpg_.

Both generated keys, the public and private one, now have to be added to Bintray.

[![Adding digital keys to Bintray](http://blog.grammarcraft.de/wp-content/uploads/2016/04/bintray-adding-keys.png)](http://blog.grammarcraft.de/wp-content/uploads/2016/04/bintray-adding-keys.png)<figcaption>Adding digital keys to Bintray</figcaption>

# Maven Central

To get a library [published to Maven Central](http://central.sonatype.org/pages/ossrh-guide.html), at first a Jira account at Sonatype is required. Then you may create a New Project ticket. At this ticket you will need to state

1. The group ID, the library will be published under. This is the most critical part, as this will be checked manually by a Sonatype employee. The ID must be unique and belonging to the requester. So, if it is a domain like “org.your-organization” you should be the owner of that domain.
2. The GitHub project page.
3. The GitHub source repository URL (ends on “.git”)

This is a on time task. You have it to do for your first library per group ID only. Subsequent libraries may published based on result of this first request.

You will get an e-mail answer when your request has been confirmed.

The Jira password is later required on Travis CI as Sonatype password for authorizing the library publishing to Maven Central.

# Travis CI

The Travis CI service is tightly integrated with GitHub. After having logged in to Travis CI using GitHub authorization just synchronize your accounts on your accounts page (there is a button for that on the right upper corner under your profile name). Pushing this button will show all source code repositories of your organization from GitHub on Travis CI.

[![Travis CI page showing GitHub repositories](http://blog.grammarcraft.de/wp-content/uploads/2016/04/travis-ci-sync-account-to-get-org-shown.png)](http://blog.grammarcraft.de/wp-content/uploads/2016/04/travis-ci-sync-account-to-get-org-shown.png)<figcaption>Travis CI page showing GitHub repositories</figcaption>

All repositories are disabled, currently. We will enable them project by project as each project needs its own configuration regarding Bintray API key and GPG pass-phrases and so on.

Enable the first project by pushing the project’s slider to the left, it becomes green. Click on the gear wheel right from the slider to get to the configuration page for this project.

[![Travis CI project configuration settings](http://blog.grammarcraft.de/wp-content/uploads/2016/04/travis-ci-add-env-vars.png)](http://blog.grammarcraft.de/wp-content/uploads/2016/04/travis-ci-add-env-vars.png)<figcaption>Travis CI project configuration settings</figcaption>

At first, push the slider “_Build only if .travis.yml is present_” to the left, enabling it. This will avoid the project is being built on every GitHub commit as long as the project is not prepared for Travis CI.

Furthermore, we have to set two environment variables for better build experiences. The slider “Display value in build logs” may be enabled here.

1. Set _TERM_ to _dumb_. This will shorten the logging output on Travis builds making it more readable.
2. Set _GRADLE\_OPTS_ to ‘-Xmx1024m -XX:MaxPermSize=512m -Dorg.gradle.daemon=true’ (including the single quotes) to speed up Gradle builds.

At last, we have to set the pass-phrase for library signing, the Bintray API key as authorization for publishing to Bintray, and the Sonatype password as authorization for publishing to Maven Central. Ensure that the slider “_Display value in build logs_” is not enabled (what is the default); otherwise, the secret values would get visible in the build logs.

1. Set ORG\_GRADLE\_PROJECT\_bintrayApiKey to the value copied from the API Key page on the Bintray profile.
2. Set ORG\_GRADLE\_PROJECT\_signingPassword to the pass-phrase the digital key pair was created with.
3. Set ORG\_GRADLE\_PROJECT\_sonatypPassword to the password the Sonatype account was registered with (the Jira password).

Don’t forget to put your configuration values into single quotes (as on GRADLE\_OPTS) if your passphrases or passwords contain empty spaces. Also, bash special characters like ‘\’ or ‘&’ has to be escaped becoming ‘\\’ or ‘\&’. Otherwise the Travis system will not forward them correctly and the build will fail.

# Gradle Build

Not a lot left now before automatic building and publishing can start. The build logic has to be put in place. At first, add the reference to Stefan Oehme’s [sobula](https://github.com/oehme/sobula) Gradle plugin to the build script.

```
plugins { id 'java'     id 'com.github.oehme.sobula.bintray-release' version '0.6.7' }
```

Now add your publishing configurations to the build script.

```
group = "your.sonatype.registered.group.id" description = "Your cool project description" contacts {     "builder@your-organization.org" {         moniker "Your Organization's Name"         roles "owner"         github "yourOrganizationsGithubUsername"     } } bintray.user = "yourOrganizationsBintrayUsername" bintray.pkg.version.mavenCentralSync.user = "yourSonatypeUsername"
```

The _group_ definition must be set to the group ID requested for Maven Central. Under _contacts_ you may enter the email address used for creating the cryptographic key ID. The _moniker_ is the human readable name of your organization. The _roles_ definition should be set to _owner_. The other definitions are self-explanatory, I guess. For an example, see this _[build.gradle](https://github.com/JavaPOSWorkingGroup/javapos-contracts/blob/master/build.gradle)_ file.

The last steps before your project gets automatically built are the following ones.

- Add a file _[releaseOnTag.sh](https://github.com/JavaPOSWorkingGroup/javapos-contracts/blob/master/.travis/releaseOnTag.sh)_ to a subdirectory _.travis_ in your project. The content of this file is the same for all projects.
- Add a file [travis.yml](https://github.com/JavaPOSWorkingGroup/javapos-contracts/blob/master/.travis.yml) to the root of our project. The content of this file is normally the same for all projects if you follow a standard project directory structure. It contains some configurations for the Travis CI runtime system. And, it calls the prior added _releaseOnTag.sh_ file.

Ensure, file executable permissions for the file _releaseOnTag.sh has been_ set; otherwise the Travis-CI server will not be able to execute this script. On Linux this is quite easy to be achieved on the command line

```
chmod +x releaseOnTag.sh
```

as well as on the Eclipse’s resource dialog for this file. However, on Windows this is quite a challenge as neither on the command line nor in Eclipse it can be done. You have to use any git client for that:

```
git update-index --chmod=+x releaseOnTag.sh
```

Your next commit to GitHub, after these changes, will force the first build of your project on Travis CI. From now on, every commit to GitHub will force an automatic build on Travis CI.

Even pull requests from other developers to your project will trigger automatic builds of this pull request on Travis CI. So, you will see immediately whether pull request builds and all test has been passed. This is really productive!

# License

An important thing to get it work must not be forgotten: You have to put an open source license file with name _LICENSE_ in the root of your project. This file is processed by the _sobula_ Gradle plug-in to figure out the license, the project is treated under. For Bintray and Maven Central any project hosted there must have an open source license.

The _sobula_ Gradle plug-in currently supports the following open source licenses:

1. [Eclipse Public License, Version 1.0](https://www.eclipse.org/legal/epl-v10.html)
2. [The MIT License](http://opensource.org/licenses/MIT)
3. [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
4. [GNU General Public License Version 2, June 1991](http://www.gnu.org/licenses/gpl-2.0)
5. [GNU Lesser General Public License Version 2.1, February 1999](http://www.gnu.org/licenses/lgpl-2.1)
6. [GNU General Public License Version 3, 29 June 2007](http://www.gnu.org/licenses/gpl-3.0)
7. [GNU Lesser General Public License Version 3, 29 June 2007](http://www.gnu.org/licenses/lgpl-3.0)
8. [GNU Affero General Public License Version 3, 19 November 2007](http://www.gnu.org/licenses/agpl-3.0.html)
9. [Common Public License (CPL), V1.0](http://www.ibm.com/developerworks/library/os-cpl.html)

Choose one of them and download the license file from the given links. The _sobula_ Gradle plug-in expects a text file; do not use HTML files. If the license you need is not supported, just fork the project, add your license under _[License.java](http://sobula/src/main/java/com/github/oehme/sobula/License.java)_ and start a pull request Don’t forget the unit tests!).

# Publishing

However, no release is published yet to Bintray and Maven Central. For that, you have draft a release on GitHub. This will force a build on Travis CI with a subsequent publishing of your library to Bintray if the _assemble_ task itself worked well. The publishing to Maven Central, however, will fail for the first time as your library must be added to [Bintray’s jCenter](https://bintray.com/bintray/jcenter) before it can be automatically published to Maven Central.

For adding your library to jCenter, go to your library’s dash board on your organization’s Bintray profile. On the right side there is a menu item _Maven Central_. Hover over it to see the hover tag where is a link you may request your library to be linked to jCenter as precondition to be synced to Maven Central. This is a one time task and seems to require some manual effort on Bintray side. You will get an mail answer when it is confirmed. It does not need to be repeated for subsequent versions.

From now on your continuous integration is running in the cloud. The only thing you have to do is committing your code changes to and drafting release on GitHub to get your library published on Bintray and Maven Central.

So, there is no excuse anymore, why an open source project does not have a continuous integration pipeline in the cloud …