Skip to content

fnichol/emeril

Repository files navigation

Emeril: Tag And Release Chef Cookbooks As A Library

Gem Version Build Status Code Climate Test Coverage Dependency Status Inline docs

Kick it up a notch! Emeril is a library that helps you release your Chef cookbooks from Rake, Thor, or a Ruby library. If rake release is all you are after, this should fit the bill.

tl;dr

How do you get started? Without much fanfare…

echo "gem 'emeril'" > Gemfile
bundle install
echo "require 'emeril/rake'" > Rakefile
bundle exec rake release

Bam!

Need more details? Read on…

Screencast

Here is a short screencast demonstating how Emeril can be used to release a cookbook to the Supermarket site.

Emeril screencast

How It Works

Emeril has 2 primary tasks and goals:

  1. Tag a Git commit with a semantic version tag with the form "v1.2.5" (by default)
  2. Optionally publish a versioned release of the cookbook to the Supermarket site

The Git tagging is currently accomplished via shell out, so Git must be installed on your system.

In order to bypass the deeply coupled cookbook_path assumptions that exist in the Knife plugins, the publishing task (implemented by the Publisher class) will create a temporary sandboxed copy of the primary cookbook files for use by the CookbookSiteShare Knife plugin. The following files are considered production cookbook files:

  • README.*
  • CHANGELOG.*
  • metadata.{json,rb}
  • attributes/**/*
  • definitions/**/*
  • files/**/*
  • libraries/**/*
  • providers/**/*
  • recipes/**/*
  • resources/**/*
  • templates/**/*

If the above list seems incomplete or incorrect, please submit an issue.

Installation

Add this line to your application's Gemfile:

gem 'emeril'

And then execute:

bundle

Or install it yourself as:

gem install emeril

Usage

Credentials Setup

Emeril currently uses the CookbookSiteShare to do most of the heavy lifting, so you will need a minimally configured knife.rb file with some required attributes set.

There are 2 configuration items you need:

  1. Your Supermarket site username, chosen at signup time.
  2. The file path to your Supermarket site user certificate. When you sign up to the Supermarket site, the site will provide this key to you as a *.pem file.

The easiest way to get setup is to add both of these items to your default knife.rb file located at $HOME/.chef/knife.rb. If you are setting this file up for the first time, give this a go (substituting your username, and key location):

mkdir -p $HOME/.chef
cat <<KNIFE_RB > $HOME/.chef/knife.rb
node_name     "fnichol"
client_key    File.expand_path('~/.chef/fnichol.pem')
KNIFE_RB

Rake Tasks

To add the default Rake task (rake release), add the following to your Rakefile:

require 'emeril/rake'

If you need to further customize the Emeril::Releaser object you can use the more explicit format with a block:

require 'emeril/rake_tasks'

Emeril::RakeTasks.new do |t|
  # turn on debug logging
  t.config[:logger].level = :debug

  # disable git tag prefix string
  t.config[:tag_prefix] = false

  # set a category for this cookbook
  t.config[:category] = "Applications"
end

If your cookbook is not on the Supermarket site, you can skip the publishing step with the block form:

require 'emeril/rake_tasks'

Emeril::RakeTasks.new do |t|
  t.config[:publish_to_supermarket] = false
end

Thor Tasks

To add the default Thor task (thor emeril:release), add the following to your Thorfile:

require 'emeril/thor'

If you need to further customize the Emeril::Releaser object you can use the more explicit format with a block:

require 'emeril/thor_tasks'

Emeril::ThorTasks.new do |t|
  # turn on debug logging
  t.config[:logger].level = :debug

  # disable git tag prefix string
  t.config[:tag_prefix] = false

  # set a category for this cookbook
  t.config[:category] = "Applications"
end

If your cookbook is not on the Supermarket site, you can skip the publishing step with the block form:

require 'emeril/thor_tasks'

Emeril::ThorTasks.new do |t|
  t.config[:publish_to_supermarket] = false
end

Ruby Library

The Ruby API is fairly straight forward, but keep in mind that loading or populating Chef::Config[:node_name] and Chef::Config[:client_key] is the responsibility of the caller, not Emeril.

For example, to load configuration from knife.rb and invoke the same code as the default Rake and Thor tasks, use the following:

# Populate Chef::Config from knife.rb
require 'chef/knife'
Chef::Knife.new.configure_chef

# Perform the git tagging and share to the Supermarket site
require 'emeril'
Emeril::Releaser.new(logger: Chef::Log).run

Frequently Asked Questions

  • "Why doesn't Emeril automatically bump version numbers?" Emeril assumes that you are using a Semantic Versioning scheme for your cookbooks. Consequently it is very hard to determine what the next version number should be when this number is coupled to the changes accompanying the release. The next release could contain a bug fix, a new feature, or contain a backwards incompatible change--all of which have a bearing on the version number.
  • "Okay, what if I supplied the version number, couldn't Emeril help me then?" Perhaps, but don't forget the other essential release artifact: a project changelog. While the maintenance schedule of the changelog is up to each author, it is sometimes desirable to combine the version bump and changelog items in one git commit. Emeril will tag and release your cookbook based on the last Git commit which is presumably your version-bump-and-changelog commit.
  • "What about adding support for X, Y, or Z?" That's possible, but Emeril has one primary focus: releasing your cookbook in an atomic and declarative fashion. We can get the job done with a small amount of code--less than 400 LOC. There are other tools that are more wholistic and workflow oriented and you are encouraged to check them out (noted below).
  • "That Chef dependency looks bulky, yo." Hmm, that's not a question. Do you you Knife? Congratulations, you have the Chef gem already! Are you using the ChefDK package? You are good to go!
  • "How do I change the category for my cookbook?" Emeril will maintain the category used on the Supermarket site across releases. By default, new cookbooks will be put in the "Other" category. Otherwise, check out the Rake and Thor sections for further configuration help.
  • "Why is Emeril complaining that I'm missing the name attribute in my metadata.rb?" You want to set this name attribute. It unambiguously sets the name of the cookbook and not the directory name that happens to contain the cookbook code. Modern tools such as Berkshelf require this for dependency resolution and the Foodcritic cookbook linting tool has rule FC045 to help catch this omission.

Alternatives

Development

Pull requests are very welcome! Make sure your patches are well tested. Ideally create a topic branch for every separate change you make. For example:

  1. Fork the repo
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Authors

Created and maintained by Fletcher Nichol (fnichol@nichol.ca)

License

MIT (see LICENSE.txt)