gitlab ci for puppet control-repo – relocating Rakefile, Gemfile

What’s the problem?

Most of the useful bits of this post are, I imagine, relevant to Rakefiles and Gemfiles in general, not just GitLab CI.

In another post about GitLab CI, I noted that .gitlab-ci.yml can be moved from the repository root. Great. Keep Rootian Tidy.

For what I want to do, there’s at least three other files that will end up there: Rakefile, Gemfile, and Gemfile.lock

The first two are config that I, the developer, supply, the latter is created by bundle install. I’d also quite like to have separate Rakefiles for each step in the CI.

So, this is the one where I stumble around in a poorly lit room called ‘Ruby’ .. that is, because I didn’t bring the torch of experience.

One of a number of posts on GitLab CI, see the gitlab-runner tag.

What’s the solution?

Straight up, here’s the fixes. Commentary later in the post.

This example results in the repository getting linted in a pipeline.

You can

  • Give the CI yaml file a name you prefer (tell GitLab)
  • Give the Rakefile(s) different names.
  • Probably call the Gemfile something else .. but I didn’t easily find a way to rename Gemfile.lock, and doing so might cause confusion.
$ cat ci/definition.yml
  - /bin/bundle install --gemfile=ci/Gemfile

  stage: test
    - BUNDLE_GEMFILE=ci/Gemfile /bin/bundle exec rake --rakefile=ci/rakefile_lint lint
$ cat ci/Gemfile
source ""

gem "puppet-lint"
$ tail -1 .gitignore
  • There are other options for how to handle Gemfile.lock; commentary below, and read the bundle-install man page.
$ cat ci/rakefile_lint 
require 'puppet-lint/tasks/puppet-lint'

Workings and commentary

This all needs to work on the Centos 7 VM I stood up to run GitLab runner.

To get going with Ruby, I added the following packages:

  • ruby
  • rubygem-bundler
  • rubygem-rake

bundle install

This came from the man page.

$ man bundle-install
              The location of the Gemfile(5) that bundler  should  use.  This
              defaults to a gemfile in the current working directory. In gen‐
              eral, bundler will assume that the location of  the  Gemfile(5)
              is  also  the  project root, and will look for the Gemfile.lock
              and vendor/cache relative to it.

I then wanted to understand what other locations got used.  I started with Gemfile in the root.

$ /bin/bundle install
Fetching gem metadata from
Resolving dependencies...
Installing rake 12.3.2
Installing puppet-lint 2.3.6
Using bundler 1.7.8
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.

Gemfile.lock gets created along side. (See .gitignore below.)
Where do the other things go; because if they go alongside the Gemfile, that’s more mess. Turns out:

$ ls ~/bin
puppet-lint  rake
$ ls ~/.gem/ruby/gems/
puppet-lint-2.3.6  rake-12.3.2

Conclusion: move Gemfile, and pass that in the command line.
Gemfile.lock then also gets created in ci/

Gemfile.lock options

From the GitLab task output.

Reinitialized existing Git repository in /home/gitlab-runner/builds/XCHrAuVS/0/puppet/control-repo/.git/
Fetching changes...
   d65bf96..2796865  gitlabrunner2 -> origin/gitlabrunner2
Checking out 27968654 as gitlabrunner2...
Removing ci/Gemfile.lock
Skipping Git submodules setup

Other than performance, I’m not really sure what the potential side effects of this might be, but I’m going to leave it being recreated for every CI run.

Maybe I get fresh gems all the time, which means that if something changes and breaks my CI, I’ll know straight away.

I could version control the gems:

              Do not attempt to connect to, instead using  just  the
              gems  already  present  in Rubygems´ cache or in vendor/cache. Note
              that  if  a  more  appropriate  platform-specific  gem  exists   on
    , it will not be found.

Checking it into version control is definitely an option; from the man page:

       1.  A Gemfile.lock is required.

           To ensure that the same versions of the gems you  developed  with  and
           tested with are also used in deployments, a Gemfile.lock is required.

           This  is mainly to ensure that you remember to check your Gemfile.lock
           into version control.

But, if I do these things, I’ll be running the same gem versions for ever more.  I’m going to leave it being deleted and see what happens. I will read the rest of the man page at some point ..


$ git status
# HEAD detached at 3a28598
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#	Gemfile.lock

The previous section shows that the GitLab runner cleans out the repo and deletes this file.

Putting it in .gitignore makes this really easy:  I didn’t try it without.

bundle exec

Lint and / or other tools I wanted to run are designed to go searching for files to check.

Changing directory to ‘ci/’ first would break this, as they’d find nothing. So it had to be a mechanism that redirected bundle’s attention, but kept the working directory the same.

Hat tip: stack overflow.

Buried in the last answer was the clue I needed – the environment variable to specify an alternative location.

ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)

So, this completed the move of the Gemfile

BUNDLE_GEMFILE=ci/Gemfile /bin/bundle exec rake lint


Hat tip: Stuart Ellis – that was a case of googling until I found it !

By accident, I found two ways to specify this. As specified on Stuart’s site:

$ BUNDLE_GEMFILE=ci/Gemfile /bin/bundle exec rake --rakefile ci/rakefile_lint lint
manifests/site.pp - WARNING: string containing only a variable on line 71
manifests/site.pp - WARNING: string containing only a variable on line 80
manifests/site.pp - WARNING: variable not enclosed in {} on line 63
manifests/site.pp - WARNING: variable not enclosed in {} on line 72

.. or alternatively with an ‘=’

$ BUNDLE_GEMFILE=ci/Gemfile /bin/bundle exec rake --rakefile=ci/rakefile_lint lint
manifests/site.pp - WARNING: string containing only a variable on line 71
manifests/site.pp - WARNING: string containing only a variable on line 80
manifests/site.pp - WARNING: variable not enclosed in {} on line 63
manifests/site.pp - WARNING: variable not enclosed in {} on line 72

Leave a Reply

Please log in using one of these methods to post your comment: Logo

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

Facebook photo

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

Connecting to %s