Travis CI ♥ Perl

Travis CI is a hosted continuous integration service for the open source community.

Essentially you set up a git post-commit hook that causes your tests to get run on every commit, against a number of different Perl versions, with databases and other services available if needed. And it's all free!

If you visit https://travis-ci.org/ you can get a feel for the interface and the tests that are being run. For a particular commit you get a build, for example WebService::Nestoria::Search build 1, which has a sub-build per Perl version, for example WebService::Nestoria::Search build 1.1 (perl 5.16). As you can see you get the full output from the Ubuntu VM that's running your tests, so if anything does go wrong it's pretty simple to debug.

For the rest of this post I'm going to describe the integration process, in particular hitting on how to make it work with Dist::Zilla-based projects.

Travis CI Basics

If you're using Github this couldn't be easier. Log into Travis CI with your Github account, go to your Travis CI profile, and flip your projects from Off to On. That causes a Github-side post-commit hook to be set up so that every time you 'git push' up to Github a Travis build will run.

Then you need to set up your .travis.yml file and commit it to your repository. Here's an example from a "normal" (non-Dist::Zilla) distribution:


language: perl
perl:
  - "5.16"
  - "5.14"
  - "5.12"
  - "5.10"

That's it, that's the whole file! Travis knows from 'language: perl' that it should look for a Makefile.PL or Build.PL, install the dependencies, and then run the tests.

Once you commit that you should be able to head back to Travis CI and see the "My Repositories" tab and see that your tests are either running or have run.

Travis CI + Dist::Zilla

At the time of writing Travis CI does not support Perl distributions that don't have either a Makefile.PL or a Build.PL file. However there are a few different options for how to support a project that only has a dist.ini file...

Add this functionality to Travis CI

Travis is open source, you can see (and fork) it here: https://github.com/travis-ci

I tried adding Dist::Zilla support and failed, mostly due to my lack of Ruby :-) I suspect if somebody headed on IRC and talked to rjbs and miyagawa a solution could be found, since they both got involved on Github when I made my attempt and were very helpful in pointing out my errors and showing me towards the ways below.

Tell Travis CI to do the "right" thing for your project only

The .travis.yml file is incredibly flexible, up to and including allowing you to run arbitrary commands before and instead of the test process. That means if you make your .travis.yml file look like this...


language: perl
perl:
   - "5.16"
   - "5.14"
   - "5.12"
   - "5.10"

before_install:
# Prevent "Please tell me who you are" errors for certain DZIL configs
- git config --global user.name "TravisCI"

install:
# Deal with all of the DZIL dependancies, quickly and quietly
- cpanm --quiet --notest --skip-satisfied Dist::Zilla
- dzil authordeps | grep -vP '[^\w:]' | xargs -n 5 -P 10 cpanm --quiet --notest --skip-satisfied

- export RELEASE_TESTING=1 AUTOMATED_TESTING=1 AUTHOR_TESTING=1 HARNESS_OPTIONS=j10:c HARNESS_TIMER=1
- dzil listdeps | grep -vP '[^\w:]' | cpanm --verbose

script:
- dzil smoke --release --author

... then your dist.ini-based module will be tested correctly, by causing it to run the appropriate cpanm and dzil commands to both install dependencies and run the tests themselves.

The Dist::Zilla plugin TravisYML (Dist::Zilla::TravisCI) will generate the file above automatically as part of your 'dzil build' if you want to do it that way.

The downside is that installing Dist::Zilla every time is very slow so your tests will take a long time. Luckily there's another way...

3. Use Git::CommitBuild and Travis CI branch whitelisting

The Dist::Zilla plugin Git::CommitBuild (Dist::Zilla::Plugin::Git::CommitBuild causes your build to be committed on a separate branch each time you run 'dzil build', or a command which implies 'build' such as 'dzil test' or 'dzil release'.

Add the plugin to your dist.ini like so:


[Git::CommitBuild]
release_branch  = build/%b
release_message = Release build of v%v (on %b)

With that you get this:


alex@yuzu:~/Documents/Git/App-highlight$ git branch
  build/master
* master

alex@yuzu:~/Documents/Git/App-highlight$ ls
bin Changes dist.ini lib README.pod t

alex@yuzu:~/Documents/Git/App-highlight$ git checkout build/master
Switched to branch 'build/master'

alex@yuzu:~/Documents/Git/App-highlight$ ls
bin Changes dist.ini lib LICENSE Makefile.PL MANIFEST META.json META.yml README README.pod t

As you can see the 'build/master' branch does have a Makefile.PL file, so Travis CI will be able to run its normal Perl testing against it. All that's left is to update your .travis.yml to tell Travis to run the tests on that branch only, like so:


language: perl
perl:
   - "5.16"
   - "5.14"
   - "5.12"
   - "5.10"

branches:
only:
- /^build/

You also need your .travis.yml file to exist on the build/master branch. To do that you need to update your dist.ini's GatherFiles and PruneCruft plugin options like so:


[GatherDir]
include_dotfiles = 1

[PruneCruft]
except = \.travis.yml

And with your next commit (and push to github if that's where your Travis CI hook is set up) a Travis build should be kicked off!

Useful Links

Travis CI:

Examples:

3 Comments

Thanks for writing this. Inspired by this article, I decided to set up Travis-CI for one of my current projects.

Although I don't use Dist::Zilla, the author-side dependencies for my build system are complex enough that I wouldn't want Travis-CI to go to the effort of installing all that. However, there's generally no need to - tests can be run with prove -lv t provided all the run-time and testing dependencies are installed. So I ended up with a .travis.yml file looking like this:

language: perl
script: HARNESS_IS_VERBOSE=1 prove -v -Ilib t
install:
  - cpanm Test::Requires Test::Fatal Moo
perl:
  - "5.16"
  - "5.14"
  - "5.12"
  - "5.10"

The other complication is that I use Mercurial, with hosting on bitbucket.org, but I've already written about how to mirror a Mercurial repo on github.com. :-)

So anyway, here's what I ended up with:

Very nice! I've set this up for a couple of my projects and I'll see how it goes. :)

Travis-CI also has support for perl 5.8 and 5.18.

Leave a comment

About Alex Balhatchet

user-pic CTO at Lokku Ltd.