August 7th, 2014

Setting up Travis CI for Scala

Setting up continuous integration for your #Scala project, including publishing to Central, Bintray and Coveralls.

— Matthew Fellows —

Having recently embraced Scala, and wanting to do something to further my understanding of the Scala ecosystem, I created a couple of simple Open Source projects on GitHub. In retrospect, doing such a thing was and is more beneficial than practically anything  I could have done, except for pairing with another seasoned Scala developer. Even if no-one is actually going to use the software.

In creating an OSS project, there is actually a fair amount of boilerplate stuff that needs to happen: Bootstrapping the project, cross-compiling scala versions, documentation, publishing artifacts to Central/Bintray etc. In this post I’d like to talk specifically about Continuous Integration with the fantastic Travis CI. For the rest, Joe Barnes has a well written overview of the process in his OSS Scala Starter Kit, which I highly recommend as a starting point.

TL;DR

Travis CI is awesome, copy a Scala SBT build configuration from a working project (or this gist), and see your artifacts appear in maven.org and code coverage on Coveralls.

Travis, your new best mate

A reliable builder, Travis CI is a free continuous integration system for your Open Source projects hosted on GitHub (there is also a commercial version). Essentially, for each build it spins up a clean, sandboxed worker machine instance with all of the libraries/tools needed for you to run your build. The full power of Travis is beyond the scope of this article, but suffice to say it is very powerful and has pretty much most things covered. Builds can be triggered via Push/Pull requests (PR), manually triggered via the GUI, API or CLI.

Creating an Account is as simple as signing in with your GitHub account, and allowing access to your public repositories from Travis CI via GitHub WebHooks. You can manage which repositories Travis will integrate to at https://travis-ci.org/profile/<GitHub username>. You should do this now, I’ll wait for you…

Today’s Lesson

To keep things simple and focused, I will cover off how to:

  • Automatically build your Scala SBT Application on push to GitHub, including PR submissions
  • Run unit tests and publish your Code Coverage statistics to Coveralls.io
  • Publish build artifacts automatically to Sonatype Nexus (aka Maven Central) & the up-and-comer BinTray (choose your own adventure)

I will assume you’ve read the aforementioned OSS Starter Kit, have created a public repo in GitHub and use SBT for local build management.

Step 1: Setup integration point accounts

Create accounts at:

Step 2: Setup Travis

Once you have created the above accounts, download and install the Travis CLI tool. Not only will you use this to encrypt sensitive information like API keys, usernames and passwords, but it will be a handy debugging tool when you’re stuck:

It should have you authorize via GitHub. Next, we need to encrypt your credentials to allow remote publishing:

From your repository base, run the following commands replacing the placeholders with your own credentials:

the --add; updates your .travis.yml for you automatically.

Update your plugins.sbt file to include the following plugins and plugin resolvers:

Now, you have a choice – Publishing to Sonatype or Bintray.

Path 1: Configure Travis to publish to Maven Central + Coveralls

The following YAML and build.sbt configuration publishes to Central on successful build for non-PR builds, and only for the oraclejdk7 specific build. Note that on line 21 we execute a command line SBT command, this works perfectly for standard, single project builds. If you are publishing a multi-module (like Respite) and only want to publish certain modules, you may need to prefix it with the individual projects you’d like to publish e.g. sbt 'project respite-core' 'set credential...

Sonatype Nexus travis.yml:

Sonatype build.sbt:

Path 2: Configure Travis to publish to Bintray

Publishing to Bintray is a bit different, it will always require a unique version and the concept of a “SNAPSHOT” release (ala Maven) does not exist. A nice plugin exists that auto-increments from Git, however I prefer to use the Travis Build numbers to increment micro versions and manually update the major and minor (Aside: Read about Semantic Versioning if you’re not familiar with major.minor.micro release versioning).

The following YAML configuration follows that convention, and publishes to Bintray on successful build for non-PR builds, and only for the oraclejdk7 specific build:

Bintray .travis.yml:

and the Bintray build.sbt:

Credentials Helper: This little guy is a bit of a hack – he extracts your credentials from the CI Environment into a local file that is read by the Bintray plugin in order to publish. Pop him in the root of your project dir (or adjust the YAML config. as appropriate):

Step 3: Push to your repository!

Now you are all set to start pushing changes to your public repo! Whenever you push a change to your upstream repository, or a pull-request is submitted, Travis CI will automatically trigger a build.

We’ve just scratched the surface of Travis – you could have notifications sent to your Hipchat room, run browser tests, spin up local databases, deploy to Heroku etc. It’s pretty neat.

Last, a couple of tips:

  • Create a feature branch for the Travis CI build as you may need to make multiple changes to the .travis.yml file before you get it right – you’ll want to squash before moving to master!
  • Take advantage of the Travis CLI tool – it has interactive mode, access to logs etc. and is handy when you’re running your first few builds to see what’s happening
  • Although I haven’t tried it myself, if you have complex build steps, you could look at running Travis CI locally to get your build configuration right. A bit of Googling hints it was and may still be possible. An excercise for another post perhaps
  • Don’t forgot to get your ‘build status’ and code coverage badge-of-honour, and wear it proudly on your GitHub repo: https://github.com/mefellows/respite/ (hopefully it’s green!?). A little markdown and you’re on your way.

Handy Links

  • biercoff_enn

    Is it possible to publish to both services? What would travis look like in that case?

    Would that work ?

    after_success:
    – >
    test “${TRAVIS_PULL_REQUEST}” = ‘false’ &&
    test “${TRAVIS_JDK_VERSION}” = ‘oraclejdk7′ &&
    sbt ‘set credentials += Credentials(“Sonatype Nexus Repository Manager”, “oss.sonatype.org”, System.getenv(“SONATYPE_USER”), System.getenv(“SONATYPE_PASS”))’ publish
    test “${TRAVIS_PULL_REQUEST}” = ‘false’ &&
    test “${TRAVIS_JDK_VERSION}” = ‘oraclejdk7′ &&
    sh “$TRAVIS_BUILD_DIR/.travis.credentials.sh” &&
    sbt ‘set version := version.value + “.” + System.getenv(“TRAVIS_BUILD_NUMBER”)’ publish