Search code examples
continuous-integrationchef-infraversioningcookbookberkshelf

Berkshelf unable to resolve cookbook version from Git tag


I manage my Chef cookbooks with Berkshelf and struggle with the upload part in the Continuous Integration pipeline.

Following some best practices found on the internet, I use thor-scmversionfor managing my cookbook versions. Therefore I added the VERSION file to .gitignore and have the cookbook version only as a tag in the git repository.

To get the current version of my cookbook in its metadata, I use the following helper in metadata.rb

require 'thor-scmversion'

def current_version
  version = IO.read(File.join(File.dirname(__FILE__), 'VERSION')) rescue nil
  version ||= ThorSCMVersion.versioner.from_path rescue nil
  version ||= '0.1.0'
  version
end

# ...
version          current_version
# ...

My problem arises, if I want to install the cookbook dependencies with berks install.

Lets assume I have a cookbook env_lampstack which has a dependency to a cookbookbook app_apache ~> 1.0.1. Therefore I use the following line in the env_lampstack's Berksfile:

cookbook 'app_apache', git: '...', branch: '1.0.1'

The cause of this is that when Berkshelf tries to resolve the dependencies, the .git folder gets removed from the cookbook's scratch directory before the meta information is read. Hence my helper method won't get the correct version from the git tag and Berkshelf throws an exception.

Given the following constraints:

  • I want my CI server (and no one else) to manage my cookbook versions

  • I cannot upload my cookbooks to a public supermarket and I don't want to set up one myself

I can figure out the following solutions:

  • I keep the VERSION file in the git repository - problem: I need to let my CI server push into the repository which is error prone

  • I create a metadata.json on the CI server and push this into my repository - problem: again - error prone

  • I upload EVERY version of every cookbook (every commit) to the Chef server, no matter if I "need" it or not - problem: the Chef server might get flooded with cookbooks or I have to move away from "trunk based" development and use feature branches and I have to take care of the upload order of the cookbooks again.

Is there any recommended workflow for handling this issue? What is the "Berkshelf Way" of managing cookbook versions and dependencies.

Any help would be highly appreciated - thanks a lot!


Solution

  • You'll need some kind of artifact repository for "released" cookbooks that have their metadata baked in already. This is usually a Chef Server org that isn't used for anything else but holding cookbooks, and then a berks-api service pointed at that. This will still leave you unable to use pre-release versions though.

    Personally I just hand-curate my metadata.rb rather than relying on scm data, and don't allow CI to modify it. Releases should generally be a human-initiated process.