Using Travis CI to deploy to Maven repositories and GitHub Releases
This post outlines the steps needed to simultaneously deploy to Maven repositories and to GitHub Releases. Every time a tagged commit is pushed, a Travis CI build will be triggered automatically and start the release process. This blog post uses Sonatype Nexus as an example for a Maven repository manager.
Preparing GitHub Releases
Sergey Mashkov has written a
Maven plugin that allows us
to create a new release on our project’s releases page and upload our build
artifacts to a release. The following sections describe how we need to configure
pom.xml in order to use this plugin.
The plugin uses the
scm settings to find out for which project the new release
should be created. Right now, there’s still a bug in the plugin which restricts
the format for our git URIs. The only working format is
scm:git:ssh://firstname.lastname@example.org/... work, but a
pull request has
been created that adds this functionality.
So add an
scm section to your pom that looks like this:
The second step is to include the plugin in our pom. Right now the plugin is
only available from bintray.com so we
need to add it as a plugin repository. We only want to create a new release on
GitHub when we are building a new release. Hence we configure the plugin in an
extra release profile section. This leads to the plugin being executed only if
Maven is started with
-Prelease and only if the deploy goal is invoked. For
more information on how to configure the plugin options please refer to its
and the pitfalls below.
Preparing for Maven releases
If you don’t already have a repository where you want to deploy to, you need to
create a release and a snapshot repository and add them to
distributionManagement. You might also want to create a separate user that has
access only to your target repositories. This user will be used to upload the
Putting it all together
So far we have configured the GitHub release plugin to deploy our artifacts to
the GitHub Releases page and setup Maven releases. Now it’s time to glue the
parts together. In order to do this we have to create a
settings.xml for use
with Maven, a
.travis.yml that manages our Travis CI builds and we have to
configure some environment variables in Travis CI itself. Furthermore we need a
small shell script that orchestrates our release.
Create a new
settings.xml file in your repository, e.g in a
directory. The content of this file should look like the following snippet. The
<server> ids have to match the ids in
<distributionManagement> and the
<serverId>of the GitHub release plugin exactly. Do not use static
credentials here! You don’t want everyone who stumbles upon your repository on
GitHub to have write access to your Nexus/Artifactory and GitHub. We will use
Travis CI’s capability to inject environment variables into builds; the
environment variables will be configured soon.
We need a small shell script that orchestrates our releases. This script sets the
correct version, creates a release and uploads it to our Maven repository and
to GitHub. To release the correct version the
TRAVIS_TAG environment variable
will be used.. Travis CI uses this variable to inject the value of the git tag
into the build.
The script first sets the
<version> in the pom exactly to our git tag’s
value. So your tag always matches the version you want to release, e.g.
1.5.1. The second part creates the release. We need to reference the
Maven settings in our repository here so that Travis CI has access rights to the Maven
repositories and GitHub Releases. The important part here is to activate the
release profile. This tells Maven to not only create and upload a Maven
release but also to create a new GitHub Release.
Name this script
release.sh, put it inside the
.travis/ directory and make
it executable (
Travis CI uses a file named
.travis.yml at the root of a GitHub repository.
The snipped contains the necessary steps.
In a normal build we just want to execute a simple
clean verify. The
goal will execute unit and integration tests. To make subsequent builds faster,
we want to cache the m2 repositories during builds.
The most important part is the deploy section. Here we configure Travis CI to run
release.sh script if and only if a tag has been pushed (
tags: true) on
Configuring Travis CI itself
Now we need to teach Travis CI the values of the environment variables used in our Maven settings. To do this navigate to the Travis CI settings for your project:
NEXUS_PASSWORD for your newly
created user. You also need to configure
GITHUB_TOKEN. But even though the field is called
password, what your really want to configure here is your GitHub API token.
Otherwise, the GitHub release plugin will not be able to upload artifacts. You
can obtain your personal access token here.
The token needs access to the repo scope.
And that’s it. Now you can simply create a new tag in your repository
git tag -a 1.1 -m "Release 1.1"), push it to GitHub and Travis CI will
trigger the release process. Happy releasing!
Some advice so that you do not encounter the same problems we did:
Do not forget to make
release.shexecutable otherwise the Travis CI build will fail with a rather unhelpful message:
Script failed with status 127.
serverIdin the GitHub release plugin’s configuration refers to a
<server>entry in Maven’s
Do not be tempted to use your GitHub account password to configure the server settings for the GitHub release plugin. Even though the field is called password it’s really an API token that is needed here.
Do not change the value of
<tagName>when configuring the GitHub release plugin. Using anything different from the project’s version (i.e. the git tag’s value), will lead to recursive release builds. This happens because the release plugin will create and push a new tag if it does not already exist. Pushing a tag invokes another Travis CI build which will create a new tag and so on.