Skip to content
This repository has been archived by the owner on Jan 15, 2024. It is now read-only.

Commit

Permalink
load dependencies and version bump to v0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
sethvargo committed Aug 17, 2012
1 parent bf87148 commit c391a8b
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 15 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Strainer CHANGELOG
==================

v0.1.0
------
- enable loading of cookbook dependencies

v0.0.4
------
- added `--fail-fast` option
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ To strain, simply run the `strain` command and pass in the cookbooks to strain:
# strains phantomjs and tmux
$ bundle exec strain phantomjs tmux

This will run `knife test` and `foodcritic` against both of the cookbooks. You can pass in as many cookbooks are you'd like.
This will first detect the cookbook dependencies, copy the cookbook and all dependencies into a sandbox. Then `knife test` and `foodcritic` will be run against both of the cookbooks. You can pass in as many cookbooks as you'd like.

As of `v0.0.3`, there's an option for `--fail-fast` that will fail immediately when any strain command returns a non-zero exit code:
Failing Quickly
---------------
As of `v0.0.4`, there's an option for `--fail-fast` that will fail immediately when any strain command returns a non-zero exit code:

$ bundle exec strain phantomjs --fail-fast

This can save time, especially when running tests locally. This is *not* recommended on continuous integration.

Custom Foodcritic Rules
-----------------------
I always advocate using both [Etsy Foodcritic Rules](https://github.com/etsy/foodcritic-rules) and [CustomInk Foodcritic Rules](https://github.com/customink/foodcritic-rules) in all your projects. I also advocate keeping them all as submodules in `[Chef Repo]/foodcritic/...`. This makes strainer unhappy...
Expand All @@ -50,4 +54,3 @@ Needs Your Help
This is a list of features or problem *you* can help solve! Fork and submit a pull request to make Strain even better!

- **Threading** - Run each cookbook's tests (or each cookbook tests test) in a separate thread
- **Dependencies** - Auto-detect dependent cookbooks and copy them over
14 changes: 7 additions & 7 deletions lib/strainer/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ def initialize(sandbox, options = {})

@cookbooks.each do |cookbook|
$stdout.puts
$stdout.puts Color.negative{ "# Straining '#{cookbook}'" }.to_s
$stdout.puts Color.negative{ "# Straining '#{cookbook.name}'" }

commands_for(cookbook).collect do |command|
commands_for(cookbook.name.to_s).collect do |command|
success &= run(command)

if fail_fast? && !success
Expand All @@ -30,11 +30,11 @@ def initialize(sandbox, options = {})
end

private
def commands_for(cookbook)
file = File.read( colanderfile_for(cookbook) )
def commands_for(cookbook_name)
file = File.read( colanderfile_for(cookbook_name) )

file = file.strip
file = file.gsub('$COOKBOOK', cookbook)
file = file.gsub('$COOKBOOK', cookbook_name)
file = file.gsub('$SANDBOX', @sandbox.sandbox_path)

lines = file.split("\n").reject{|c| c.strip.empty?}.compact
Expand All @@ -52,8 +52,8 @@ def commands_for(cookbook)
end || []
end

def colanderfile_for(cookbook)
cookbook_level = File.join(@sandbox.sandbox_path(cookbook), 'Colanderfile')
def colanderfile_for(cookbook_name)
cookbook_level = File.join(@sandbox.sandbox_path(cookbook_name), 'Colanderfile')
root_level = File.expand_path('Colanderfile')

if File.exists?(cookbook_level)
Expand Down
46 changes: 42 additions & 4 deletions lib/strainer/sandbox.rb
Original file line number Diff line number Diff line change
@@ -1,28 +1,42 @@
require 'chef'
require 'fileutils'

module Strainer
class Sandbox
attr_reader :cookbooks

def initialize(cookbooks = [], options = {})
@cookbooks = [cookbooks].flatten
@options = options
@cookbooks = load_cookbooks([cookbooks].flatten)

clear_sandbox
create_sandbox
end

def cookbook_path(cookbook)
path = File.join(cookbooks_path, cookbook)
path = File.join(cookbooks_path, cookbook.name.to_s)
raise "cookbook '#{cookbook}' was not found in #{cookbooks_path}" unless File.exists?(path)
return path
end

def sandbox_path(cookbook = nil)
File.expand_path( File.join(%W(colander cookbooks #{cookbook})) )
File.expand_path( File.join(%W(colander cookbooks #{cookbook.is_a?(::Chef::CookbookVersion) ? cookbook.name : cookbook})) )
end

private
# Load a specific cookbook by name
def load_cookbook(cookbook_name)
return cookbook_name if cookbook_name.is_a?(::Chef::CookbookVersion)
loader = ::Chef::CookbookLoader.new(cookbooks_path)
loader[cookbook_name]
end

# Load an array of cookbooks by name
def load_cookbooks(cookbook_names)
cookbook_names = [cookbook_names].flatten
cookbook_names.collect{ |cookbook_name| load_cookbook(cookbook_name) }
end

def cookbooks_path
@cookbooks_path ||= (@options[:cookbooks_path] || File.expand_path('cookbooks'))
end
Expand All @@ -45,7 +59,7 @@ def copy_globals
end

def copy_cookbooks
@cookbooks.each do |cookbook|
(cookbooks + cookbooks_dependencies).each do |cookbook|
FileUtils.cp_r(cookbook_path(cookbook), sandbox_path)
end
end
Expand All @@ -64,5 +78,29 @@ def place_knife_rb
# create knife.rb
File.open("#{chef_path}/knife.rb", 'w+'){ |f| f.write(contents) }
end

# Iterate over the cookbook's dependencies and ensure those cookbooks are
# also included in our sandbox by adding them to the @cookbooks instance
# variable. This method is actually semi-recursive because we append to the
# end of the array on which we are iterating, ensuring we load all dependencies
# dependencies.
def cookbooks_dependencies
@cookbooks_dependencies ||= begin
$stdout.puts 'Loading cookbook dependencies...'

loaded_dependencies = Hash.new(false)

dependencies = @cookbooks.dup

dependencies.each do |cookbook|
cookbook.metadata.dependencies.keys.each do |dependency_name|
unless loaded_dependencies[dependency_name]
dependencies << load_cookbook(dependency_name)
loaded_dependencies[dependency_name] = true
end
end
end
end
end
end
end
3 changes: 2 additions & 1 deletion strainer.gemspec
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Gem::Specification.new do |gem|
gem.version = '0.0.4'
gem.version = '0.1.0'
gem.authors = ['Seth Vargo']
gem.email = ['sethvargo@gmail.com']
gem.description = %q{Run isolated cookbook tests against your chef repository with Strainer.}
Expand All @@ -12,6 +12,7 @@ Gem::Specification.new do |gem|
gem.name = 'strainer'
gem.require_paths = ['lib']

gem.add_runtime_dependency 'chef', '~> 10.12.0'
gem.add_runtime_dependency 'term-ansicolor', '~> 1.0.7'

gem.add_development_dependency 'yard', '~> 0.8.2'
Expand Down

0 comments on commit c391a8b

Please sign in to comment.