Configuring Travis CI on a Puppet Module Repo

Recently we looked at enabling Travis CI on the Controlrepo. Today, we’re going to do the same for a module repo. We’re going to use much of the same logic and files, just tweaking things a bit to fit the slightly different file layout and perhaps changing the test matrix a bit. If you have not registered for Travis CI yet, go ahead and take care of that (public or private) before continuing.

The first challenge is to decide if you’re going to enable Travis CI with an existing module, or a new module. Since a new module is probably easier, let’s get the hard stuff out of the way.

Set up an existing module

I have an existing module rnelson0/certs which has no CI but does have working rspec tests, a great candidate for today’s efforts. Let’s make sure the tests actually work, it’s easy to make incorrect assumptions:

modules travis ci fig 1

We don’t have a Gemfile or anything, so let’s create a new branch and grab some working copies of those from garethr/puppet-module-skeleton. If you’ve cloned that already, you can grab the important files with cp ../puppet-module-skeleton/skeleton/{.gitignore,Rakefile,Gemfile,.rubocop.yml,.travis.yml,.rspec} ./ (replace with the correct path as needed) and then start editing them. The .gitignore, Rakefile, Gemfile, and .rubocop.yml can be customized as you require. If your module didn’t have these before, I suggest leaving them alone until you find a problem otherwise (if your module has ruby code, you may want to tweak the Rubocop configuration, for instance). We looked at a simple .travis.yml matrix last time, let’s review this more complicated matrix:

---
language: ruby
bundler_args: --without development system_tests
before_install: rm Gemfile.lock || true
rvm:
  - 1.8.7
  - 1.9.3
  - 2.0.0
  - 2.1.0
script: bundle exec rake test
env:
  - PUPPET_VERSION="~> 2.7.0"
  - PUPPET_VERSION="~> 3.2.0"
  - PUPPET_VERSION="~> 3.3.0"
  - PUPPET_VERSION="~> 3.4.0"
  - PUPPET_VERSION="~> 3.5.0" STRICT_VARIABLES=yes
  - PUPPET_VERSION="~> 3.6.0" STRICT_VARIABLES=yes
  - PUPPET_VERSION="~> 3.7.0" STRICT_VARIABLES=yes
  - PUPPET_VERSION="~> 3.7.0" STRICT_VARIABLES=yes FUTURE_PARSER=yes
matrix:
  exclude:
  # Ruby 1.9.3
  - rvm: 1.9.3
    env: PUPPET_VERSION="~> 2.7.0"

  # Ruby 2.0.0
  - rvm: 2.0.0
    env: PUPPET_VERSION="~> 2.7.0"

  # Ruby 2.1.0
  - rvm: 2.1.0
    env: PUPPET_VERSION="~> 2.7.0"
  - rvm: 2.1.0
    env: PUPPET_VERSION="~> 3.2.0"
  - rvm: 2.1.0
    env: PUPPET_VERSION="~> 3.3.0"
  - rvm: 2.1.0
    env: PUPPET_VERSION="~> 3.4.0"

There are a few things to notice here. One, instead of just matrix with an include key, we now have env and matrix with exclude values. Two, in env, there’s no v4.x version of puppet. Three, in matrix:exclude, there’s a bunch of v2.7 testing. Feel free to re-arrange this to suit your desires, you just need to make sure your code will pass on the first merge. For instance, I don’t care about Puppet 2 or Ruby 1.8.7 compatibility at all and I want my code to be compatible with Puppet 4 and the future parser, but it isn’t – yet. That leaves me with this config, with some stanzas commented out until I update the code:

---
language: ruby
bundler_args: --without development system_tests
before_install: rm Gemfile.lock || true
rvm:
  - 1.9.3
  - 2.0.0
  - 2.1.0
script: bundle exec rake test
env:
  - PUPPET_VERSION="~> 3.2.0"
  - PUPPET_VERSION="~> 3.3.0"
  - PUPPET_VERSION="~> 3.4.0"
  - PUPPET_VERSION="~> 3.5.0" STRICT_VARIABLES=yes
  - PUPPET_VERSION="~> 3.6.0" STRICT_VARIABLES=yes
  - PUPPET_VERSION="~> 3.7.0" STRICT_VARIABLES=yes
  - PUPPET_VERSION="~> 3.7.0" STRICT_VARIABLES=yes FUTURE_PARSER=yes
  #- PUPPET_VERSION="~> 4.0.0" STRICT_VARIABLES=yes
matrix:
  exclude:
  # Ruby 2.1.0
  - rvm: 2.1.0
    env: PUPPET_VERSION="~> 3.2.0"
  - rvm: 2.1.0
    env: PUPPET_VERSION="~> 3.3.0"
  - rvm: 2.1.0
    env: PUPPET_VERSION="~> 3.4.0"

I can now do some a dry run using bundler and rake. It’s a limited test, since I’m going to use a specific puppet version and have ruby 1.9.3 locally, but it will still validate at LEAST one version pairing for us:

[rnelson0@build02 puppet-certs:travisci±]$ bundle install --path vendor --without system_tests
<snip gem installation>
Your bundle is complete!
Gems in the group system_tests were not installed.
It was installed into ./vendor
[rnelson0@build02 puppet-certs:travisci±]$ bundle exec rake test
Warning: License identifier Apache Version 2.0 is not in the SPDX list: http://spdx.org/licenses/
Errors found in metadata.json

Whoops, that should be Apache-2.0! That’s okay, this is the kind of thing we want to catch. Keep running through until you fix your problems, or identify a way to eliminate what you believe to be warnings. In addition to the metadata fix, because of Rubocop I had to fix a few lines of my tests and disable two Rubocop settings I did not want to use:

[rnelson0@build02 puppet-certs:travisci±]$ cat >> .rubocop.yml
Style/BlockDelimiters:
  Enabled: False

Style/MultilineBlockLayout:
  Enabled: False
[rnelson0@build02 puppet-certs:travisci±]$ bundle exec rake test
---> syntax:manifests
---> syntax:templates
---> syntax:hiera:yaml
Running RuboCop...
Inspecting 5 files
.....

5 files inspected, no offenses detected
/usr/local/rvm/rubies/ruby-1.9.3-p551/bin/ruby -I/home/rnelson0/git/puppet-certs/vendor/ruby/1.9.1/gems/rspec-core-3.1.7/lib:/home/rnelson0/git/puppet-certs/vendor/ruby/1.9.1/gems/rspec-support-3.1.2/lib /home/rnelson0/git/puppet-certs/vendor/ruby/1.9.1/gems/rspec-core-3.1.7/exe/rspec --pattern spec/\{classes,defines,unit,functions,hosts,integration\}/\*\*/\*_spec.rb --color
......

Finished in 0.39732 seconds (files took 0.91754 seconds to load)
6 examples, 0 failures

Now we have a good chance of things passing. Make sure you have Travis CI enabled on this repo, then commit and push your code.

Pull Request Test

Once you’ve pushed your change, go to your repo and create a new pull request to start Travis CI. You can see my PR#13 and the corresponding Travis CI build. If we’ve done everything right and we have a bit of luck on our side, we just need to wait a few minutes and everything will go green. Of course, this matrix has 18 tests and we left some future parser test cases in place, so it will take a little while and some of us may run into issues. That’s okay, either fix your code if you can (and it’s trivial – we don’t want the PR to enable Travis CI to turn into a PR with 100 changed files) or disable some of the tests. Don’t worry about the disabled tests, as enabling Travis CI allows us to fix those issues in the future much easier than it would have been in the past.

After a few minutes, everything turned out green!

modules travis ci fig 2

Perfect, we can merge the PR! Now we’ve got everything in place to add versions to our matrix and re-enable any checks we disabled.

Summary

We looked at how to enable Travis CI on a single Puppet module today. Previously, we enabled Travis CI on our controlrepo. Go ahead and enable Travis CI on any other modules and controlrepos you maintain. This puts you and your teammates in a good position for future development, where testing and continuous integration happens automatically, every time. Start adding tests for Puppet 4 and any other hot newness you want to look at and refactor your code without as much risk of breaking production. Enjoy!

12 thoughts on “Configuring Travis CI on a Puppet Module Repo

  1. Pingback: Update your Puppet modules on the Forge quickly with Blacksmith | rnelson0
  2. Pingback: Getting a fresh start in a Git repository | rnelson0
  3. Pingback: Introduction to rspec-puppet | rnelson0
  4. Pingback: Puppet rspec tests with Hiera data | rnelson0
  5. Pingback: Beyond rspec-puppet: puppetlabs_spec_helper | rnelson0
  6. Pingback: Modern rspec-puppet practices | rnelson0
  7. Pingback: Allowing expected failures with Travis CI | rnelson0
  8. Pingback: #Puppetinabox moving to v4 in 2016 | rnelson0
  9. Hi,
    Thanks a lot for theses explanations. It’s very useful.
    I’m trying to do something like this but I’m facing a problem with private repos.
    I would like to check on travis a private puppet module with private dependencies.

    I found how to encrypt data with travis, I know that with APIKEY in my URL in fixtures.yml are OK (https://APIKEY@github.com/ORG/repo)
    but I can’t find how to encrypt the github APIKEY and use it in fixtures.yml file.

    As I can’t find information on this, I wonder if I am in the best way to do this…
    Do you have any clue for ma ?

    Thanks !

  10. Pingback: Getting started with Jenkins and Puppet | rnelson0

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s