Skip to content

Commit

Permalink
Initial commit: basic rake tasks for running with different gemfiles
Browse files Browse the repository at this point in the history
  • Loading branch information
jferris committed Nov 11, 2010
0 parents commit ff75e90
Show file tree
Hide file tree
Showing 16 changed files with 418 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .bundle/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
BUNDLE_DISABLE_SHARED_GEMS: "1"
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.swp
tmp
pkg
.swo
*~

5 changes: 5 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
source "http://rubygems.org"
gem "cucumber"
gem "aruba"
gem "rake"
gem "rspec"
38 changes: 38 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
GEM
remote: http://rubygems.org/
specs:
aruba (0.2.4)
background_process
cucumber (~> 0.9.3)
background_process (1.2)
builder (2.1.2)
cucumber (0.9.4)
builder (~> 2.1.2)
diff-lcs (~> 1.1.2)
gherkin (~> 2.2.9)
json (~> 1.4.6)
term-ansicolor (~> 1.0.5)
diff-lcs (1.1.2)
gherkin (2.2.9)
json (~> 1.4.6)
term-ansicolor (~> 1.0.5)
json (1.4.6)
rake (0.8.7)
rspec (2.1.0)
rspec-core (~> 2.1.0)
rspec-expectations (~> 2.1.0)
rspec-mocks (~> 2.1.0)
rspec-core (2.1.0)
rspec-expectations (2.1.0)
diff-lcs (~> 1.1.2)
rspec-mocks (2.1.0)
term-ansicolor (1.0.5)

PLATFORMS
ruby

DEPENDENCIES
aruba
cucumber
rake
rspec
19 changes: 19 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
require 'rubygems'
require 'bundler/setup'
require 'rake/gempackagetask'
require 'cucumber/rake/task'

eval("$specification = #{IO.read('appraisal.gemspec')}")
Rake::GemPackageTask.new($specification) do |package|
package.need_zip = true
package.need_tar = true
end

Cucumber::Rake::Task.new(:cucumber) do |t|
t.fork = true
t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'progress')]
end

desc "Default: run the cucumber scenarios"
task :default => :cucumber

26 changes: 26 additions & 0 deletions appraisal.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Gem::Specification.new do |s|
s.name = %q{appraisal}
s.version = '0.1'
s.summary = %q{Find out how much your Ruby gems are worth}
s.description = %q{appraisal integrates with bundler and rake to test your library against different versions of dependencies in repeatable scenarios called "appraisals."}

s.files = Dir['[A-Z]*', 'lib/**/*.rb', 'features/**/*']
s.require_path = 'lib'
s.test_files = Dir['features/**/*']

s.has_rdoc = false

s.authors = ["Joe Ferris"]
s.email = %q{jferris@thoughtbot.com}
s.homepage = "http://github.com/thoughtbot/appraisal"

s.add_development_dependency('cucumber')
s.add_development_dependency('aruba')

s.add_runtime_dependency('rake')
s.add_runtime_dependency('bundler')

s.platform = Gem::Platform::RUBY
s.rubygems_version = %q{1.2.0}
end

57 changes: 57 additions & 0 deletions features/appraisals.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Feature: run a rake task through several appraisals

Background:
Given a directory named "projecto"
When I cd to "projecto"
And I write to "Gemfile" with:
"""
source "http://rubygems.org"
gem "rake"
gem "factory_girl"
"""
When I add "appraisal" from this project as a dependency
And I write to "Appraisals" with:
"""
appraise "1.3.2" do
gem "factory_girl", "1.3.2"
end
appraise "1.3.0" do
gem "factory_girl", "1.3.0"
end
"""
When I write to "Rakefile" with:
"""
require 'rubygems'
require 'bundler/setup'
require 'appraisal'
task :version do
require 'factory_girl'
puts "Loaded #{Factory::VERSION}"
end
task :default => :version
"""
When I successfully run "rake appraisal:install --trace"

@disable-bundler
Scenario: run a specific task with one appraisal
When I successfully run "rake appraisal:1.3.0 version --trace"
Then the output should contain "Loaded 1.3.0"

@disable-bundler
Scenario: run a specific task with all appraisals
When I successfully run "rake appraisal version --trace"
Then the output should contain "Loaded 1.3.0"
And the output should contain "Loaded 1.3.2"
And the output should not contain "Invoke version"

@disable-bundler
Scenario: run the default task with one appraisal
When I successfully run "rake appraisal:1.3.0 --trace"
Then the output should contain "Loaded 1.3.0"

@disable-bundler
Scenario: run the default task with all appraisals
When I successfully run "rake appraisal --trace"
Then the output should contain "Loaded 1.3.0"
And the output should contain "Loaded 1.3.2"

4 changes: 4 additions & 0 deletions features/step_definitions/dependency_steps.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
When /^I add "([^"]*)" from this project as a dependency$/ do |gem_name|
append_to_file('Gemfile', %{\ngem "#{gem_name}", :path => "#{PROJECT_ROOT}"})
end

4 changes: 4 additions & 0 deletions features/support/env.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require 'aruba'

PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')).freeze

4 changes: 4 additions & 0 deletions lib/appraisal.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require 'appraisal/task'

Appraisal::Task.new

46 changes: 46 additions & 0 deletions lib/appraisal/appraisal.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'appraisal/gemfile'
require 'appraisal/command'
require 'fileutils'

module Appraisal
# Represents one appraisal and its dependencies
class Appraisal
attr_reader :name, :gemfile

def initialize(name, source_gemfile)
@name = name
@gemfile = source_gemfile.dup
end

def gem(name, *requirements)
gemfile.gem(name, *requirements)
end

def write_gemfile
::File.open(gemfile_path, "w") do |file|
file.puts("# This file was generated by Appraisal")
file.puts
file.write(gemfile.to_s)
end
end

def install
Command.new("bundle install --gemfile=#{gemfile_path}").run
end

def gemfile_path
unless ::File.exist?(gemfile_root)
FileUtils.mkdir(gemfile_root)
end

::File.join(gemfile_root, "#{name}.gemfile")
end

private

def gemfile_root
"gemfiles"
end
end
end

53 changes: 53 additions & 0 deletions lib/appraisal/command.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
module Appraisal
# Executes commands with a clean environment
class Command
BUNDLER_ENV_VARS = %w(RUBYOPT BUNDLE_PATH BUNDLE_BIN_PATH BUNDLE_GEMFILE).freeze

def self.from_args(gemfile)
command = ([$0] + ARGV.slice(1, ARGV.size)).join(' ')
new(command, gemfile)
end

def initialize(command, gemfile = nil)
@original_env = {}
@gemfile = gemfile
@command = command
end

def run
announce
with_clean_env { Kernel.system(@command) }
end

def exec
announce
with_clean_env { Kernel.exec(@command) }
end

private

def with_clean_env
unset_bundler_env_vars
ENV['BUNDLE_GEMFILE'] = @gemfile
yield
ensure
restore_env
end

def announce
puts ">> BUNDLE_GEMFILE=#{@gemfile} #{@command}"
end

def unset_bundler_env_vars
BUNDLER_ENV_VARS.each do |key|
@original_env[key] = ENV[key]
ENV[key] = nil
end
end

def restore_env
@original_env.each { |key, value| ENV[key] = value }
end
end
end

27 changes: 27 additions & 0 deletions lib/appraisal/dependency.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module Appraisal
# Dependency on a gem and optional version requirements
class Dependency
attr_reader :name, :requirements

def initialize(name, requirements)
@name = name
@requirements = requirements
end

def to_s
gem_name = %{gem "#{name}"}
if requirements.nil? || requirements.empty?
gem_name
else
"#{gem_name}, #{inspect_requirements}"
end
end

private

def inspect_requirements
requirements.map { |requirement| requirement.inspect }.join(", ")
end
end
end

41 changes: 41 additions & 0 deletions lib/appraisal/file.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require 'appraisal/appraisal'
require 'appraisal/gemfile'

module Appraisal
# Loads and parses Appraisal files
class File
attr_reader :appraisals, :gemfile

def self.each(&block)
new.each(&block)
end

def initialize
@appraisals = []
@gemfile = Gemfile.new
@gemfile.load('Gemfile')
run(IO.read(path))
end

def each(&block)
appraisals.each(&block)
end

def appraise(name, &block)
@appraisals << Appraisal.new(name, gemfile).tap do |appraisal|
appraisal.instance_eval(&block)
end
end

private

def run(definitions)
instance_eval definitions, __FILE__, __LINE__
end

def path
'Appraisals'
end
end
end

42 changes: 42 additions & 0 deletions lib/appraisal/gemfile.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require 'appraisal/dependency'

module Appraisal
# Load bundler Gemfiles and merge dependencies
class Gemfile
attr_reader :dependencies

def initialize
@dependencies = {}
end

def load(path)
run(IO.read(path))
end

def run(definitions)
instance_eval(definitions, __FILE__, __LINE__)
end

def gem(name, *requirements)
@dependencies[name] = Dependency.new(name, requirements)
end

def source(source)
@source = source
end

def to_s
%{source "#{@source}"\n} <<
dependencies.values.map { |dependency| dependency.to_s }.join("\n")
end

def dup
Gemfile.new.tap do |gemfile|
gemfile.source @source
dependencies.values.each do |dependency|
gemfile.gem(dependency.name, *dependency.requirements)
end
end
end
end
end
Loading

0 comments on commit ff75e90

Please sign in to comment.