palimpsest

my idiosyncratic ruby environment

A couple of people in my office hours at chefconf expressed interest in my knife/chef/ruby setup, so I said I’d write a blog post with a few more details. To be clear, this is me sharing my extremely opinionated setup with people who asked, and not me speaking as an employee of Chef. I expect to be dogfooding chefdk for cookbook development, but don’t currently have any substantive opinions about it. I suspect that confusing things will happen if you try to use the workflow described in this post along with chefdk, so please don’t try that.

My general approach for a workstation machine (meaning one where you intend to run knife) is not to install anything under ruby installed via the omnibus package for the chef-client. Instead, I do the following:

  1. Install my own ruby. Do not use the system ruby or chef’s ruby. Do not install gems as root.
  2. Install bundler with that ruby. bundler and its deps are the only gems I install directly with that ruby.
  3. Consider any cookbooks I’m developing, knife plugins I need to cooperate with each other, or ruby hacking a project with its own Gemfile.
  4. Vendor my gems for each project.

(Because someone will ask: when I install knife plugins, I do put chef in my Gemfile as a dependency, and I start by pinning to the version I have installed on my workstation. If that turns out to be problematic, I start rolling back versions.)

Yes, it’s fussy, but it allows me a lot of flexibility to delete and reinstall things that are not working. I even do bundle install --path ~/bundles/<application-name> so that I can delete all of my vendored gemsets at once, but that’s purely a personal preference. I like being able to do clean installs of collections of gems that aren’t working without disturbing ones that are, or being able to update to the latest omnibus install of the chef-client without breaking work in progress.

I arrived at this workflow over a year or so of trying to maintain a ruby environment suitable for developing cookbooks, running knife commands, and doing regular ruby development. That year happened to coincide with a lot of rapid change in Chef’s ecosystem, which meant that at any given time, at least one of these three not-unreasonable goals seemed impossible. Not using chef’s ruby for development made it a lot easier to update chef on my workstation. Bypassing the system ruby in favor of installing my own (originally with rvm, then rbenv, now ruby-build and chruby) meant that if I got exasperated enough to pave and rebuild my ruby environment from scratch, I could. Not trying to maintain a single set of gems suitable for running knife plugins and cookbook testing and anything else I might be doing with ruby was for me the biggest win, because it meant I didn’t have to worry every time I updated a dependency for one project that it would break something for another project.


I’m still moving in to this space, but if you have questions, please open an issue.