implement switching back to prior env on post-commit, should fix #2

This commit is contained in:
John Bintz 2012-01-09 10:48:47 -05:00
parent 9354fed2dc
commit b30d56819e
16 changed files with 327 additions and 27 deletions

View File

@ -5,7 +5,11 @@ gemspec
gem 'guard'
gem 'guard-rspec'
gem 'guard-cucumber'
gem 'mocha'
gem 'fakefs'
gem 'rspec', '~> 2.6.0'
gem 'rake'
gem 'cucumber'

View File

@ -1,9 +1,18 @@
# A sample Guardfile
# More info at https://github.com/guard/guard#readme
group :rspec do
guard 'rspec', :cli => '-c', :version => 2 do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" }
end
end
group :cucumber do
guard 'cucumber' do
watch(%r{^features/.+\.feature$})
watch(%r{^features/support/.+$}) { 'features' }
watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
end
end

View File

@ -9,5 +9,24 @@ rescue LoadError
"#$! - no rspec"
end
task :default => :spec
begin
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
rescue LoadError
"#$! - no rspec"
end
begin
require 'cucumber'
require 'cucumber/rake/task'
Cucumber::Rake::Task.new(:cucumber) do |t|
t.cucumber_opts = "features --format pretty"
end
rescue LoadError
"#$! - no cucumber"
end
task :default => [ :spec, :cucumber ]

View File

@ -29,12 +29,20 @@ class PenchantCLI < Thor
end
method_options :deployment => false
method_options :switch_back => false
desc "gemfile ENV", "Switch the gemfile environment, or rebuild the current environment if not given"
def gemfile(env = get_current_env)
if env
if options[:switch_back]
puts "[penchant] Switching back, fallback: #{env}..."
Penchant::Gemfile.switch_back!(env)
else
puts "[penchant] Rebunding for #{env} environment#{options[:deployment] ? ", deployment mode" : ''}..."
Penchant::Gemfile.do_full_env_switch!(env, options[:deployment])
end
end
gemfile = Penchant::Gemfile.new
if !gemfile.has_gemfile?

18
features/cli.feature Normal file
View File

@ -0,0 +1,18 @@
Feature: CLI
Scenario: Switch back to the original pre-deployment environment
Given I have the file "tmp/Gemfile.erb" with the content:
"""
gem 'rake'
"""
And I have the file "tmp/Gemfile" with the content:
"""
# generated by penchant, environment: production, deployment mode (was local)
"""
When I run "bin/penchant gemfile other --switch-back" in the "tmp" directory
Then the file "tmp/Gemfile" should have the following content:
"""
# generated by penchant, environment: local
gem 'rake'
"""
And the output should include "fallback: other"

33
features/gemfile.feature Normal file
View File

@ -0,0 +1,33 @@
@fakefs
Feature: Gemfiles
Scenario: When rebuilding for deployment, save the original state
Given I have the file "Gemfile.erb" with the content:
"""
this is content
"""
And I have the file "Gemfile" with the content:
"""
# generated by penchant, environment: local
"""
When I rebuild the Gemfile for "production" mode with deployment
Then the file "Gemfile" should have the following content:
"""
# generated by penchant, environment: production, deployment mode (was local)
this is content
"""
Scenario: When unbundling from deployment with an original state, switch to that state
Given I have the file "Gemfile.erb" with the content:
"""
this is content
"""
And I have the file "Gemfile" with the content:
"""
# generated by penchant, environment: production, deployment mode (was local)
"""
When I rebuild the Gemfile asking to switch back to the previous state
Then the file "Gemfile" should have the following content:
"""
# generated by penchant, environment: local
this is content
"""

View File

@ -0,0 +1,5 @@
Given /^I have the file "([^"]*)" with the content:$/ do |file, string|
FileUtils.mkdir_p File.dirname(file)
File.open(file, 'wb') { |fh| fh.print string }
end

View File

@ -0,0 +1,3 @@
Then /^the file "([^"]*)" should have the following content:$/ do |file, string|
File.read(file).should == string
end

View File

@ -0,0 +1,3 @@
Then /^the output should include "([^"]*)"$/ do |text|
@output.should include(text)
end

View File

@ -0,0 +1,3 @@
When /^I rebuild the Gemfile asking to switch back to the previous state$/ do
Penchant::Gemfile.switch_back!("remote")
end

View File

@ -0,0 +1,3 @@
When /^I rebuild the Gemfile for "([^"]*)" mode with deployment$/ do |env|
Penchant::Gemfile.do_full_env_switch!(env, true)
end

View File

@ -0,0 +1,3 @@
When /^I run "([^"]*)" in the "([^"]*)" directory$/ do |command, dir|
@output = %x{bash -c 'opwd=$PWD; cd #{dir} && $opwd/#{command}'}
end

13
features/support/env.rb Normal file
View File

@ -0,0 +1,13 @@
require 'fakefs/safe'
require 'penchant'
Before('@fakefs') do
FakeFS.activate!
end
After do
FakeFS.deactivate!
FileUtils.rm_rf 'tmp'
end

View File

@ -2,21 +2,30 @@ require 'erb'
module Penchant
class Gemfile
attr_reader :path
attr_reader :path, :is_deployment
class << self
def do_full_env_switch!(env, deployment = false)
gemfile = Penchant::Gemfile.new
gemfile.run_dot_penchant!(env, deployment)
if !gemfile.has_gemfile_erb?
return false
end
def self.do_full_env_switch!(env, deployment = false)
return false if !(gemfile = pre_switch(env, deployment))
gemfile.switch_to!(env, deployment)
end
def self.switch_back!(fallback_env)
return false if !(gemfile = pre_switch(fallback_env))
gemfile.switch_back!(fallback_env)
end
def self.pre_switch(env, deployment = false)
gemfile = Penchant::Gemfile.new
return false if !gemfile.has_gemfile_erb?
gemfile.run_dot_penchant!(env, deployment)
gemfile
end
def current_env ; @env ; end
def initialize(path = Dir.pwd)
@path = path
end
@ -26,7 +35,7 @@ module Penchant
end
def has_gemfile?
File.file?('Gemfile')
File.file?(gemfile_path)
end
def has_dot_penchant?
@ -42,33 +51,52 @@ module Penchant
end
def environment
File.readlines(gemfile_path).first.strip[%r{environment: ([^, ]*)}, 1]
gemfile_header.strip[%r{environment: ([^, ]*)}, 1]
end
def deployment?
File.readlines(gemfile_path).first['deployment mode'] != nil
gemfile_header['deployment mode'] != nil
end
def switch_to!(gemfile_env = nil, deployment = false)
@env, @is_deployment = gemfile_env, deployment
template = File.read(gemfile_erb_path)
File.open(gemfile_path, 'wb') do |fh|
fh.puts "# generated by penchant, environment: #{@env || "none"}#{@is_deployment ? " , deployment mode" : ""}"
output = [ header, ERB.new(template).result(binding) ]
fh.print ERB.new(template).result(binding)
end
File.open(gemfile_path, 'wb') { |fh| fh.print output.join("\n") }
end
def run_dot_penchant!(env, deployment)
DotPenchant.run(env || environment, deployment) if has_dot_penchant?
end
def header
header = [ "# generated by penchant, environment: #{current_env}" ]
if is_deployment
header << ", deployment mode (was #{environment})"
end
header.join
end
def prior_environment
gemfile_header[%r{\(was (.+)\)}, 1]
end
def switch_back!(fallback_env)
switch_to!(prior_environment || fallback_env)
end
private
def file_in_path(file)
File.join(@path, file)
end
def template
File.read(gemfile_erb_path)
end
def env(check, &block)
instance_eval(&block) if check.to_s == @env.to_s
end
@ -76,6 +104,10 @@ module Penchant
def no_deployment(&block)
instance_eval(&block) if !@is_deployment
end
def gemfile_header
(has_gemfile? and File.readlines(gemfile_path).first) or ""
end
end
end

View File

@ -146,5 +146,149 @@ ERB
end
end
end
describe '#switch_to!' do
let(:template) { 'template' }
let(:gemfile_path) { 'gemfile path' }
let(:header) { 'header' }
let(:gemfile_out) { File.read(gemfile_path) }
before do
gemfile.stubs(:template).returns(template)
gemfile.stubs(:gemfile_path).returns(gemfile_path)
gemfile.expects(:header).returns(header)
end
it 'should write out the new gemfile' do
gemfile.switch_to!
gemfile_out.should include(template)
gemfile_out.should include(header)
end
end
describe '#header' do
subject { gemfile.header }
let(:env) { 'env' }
let(:prior_environment) { 'prior' }
before do
gemfile.stubs(:current_env).returns(env)
gemfile.stubs(:environment).returns(prior_environment)
end
context 'not deployment' do
before do
gemfile.stubs(:is_deployment).returns(false)
end
it { should == "# generated by penchant, environment: #{env}" }
end
context 'deployment' do
before do
gemfile.stubs(:is_deployment).returns(true)
end
it { should == "# generated by penchant, environment: #{env}, deployment mode (was #{prior_environment})" }
end
end
describe '#prior_environment' do
subject { gemfile.prior_environment }
let(:prior) { 'prior' }
before do
gemfile.stubs(:gemfile_header).returns("# header (was #{prior})")
end
it { should == prior }
end
describe '.switch_back!' do
let(:gemfile) { stub }
let(:fallback_env) { 'env' }
context 'pre_switch fails' do
before do
described_class.stubs(:pre_switch).returns(false)
gemfile.expects(:switch_back!).never
end
it 'should not switch back' do
described_class.switch_back!(fallback_env).should be_false
end
end
context 'pre_switch succeeds' do
before do
described_class.stubs(:pre_switch).returns(gemfile)
gemfile.expects(:switch_back!).with(fallback_env)
end
it 'should switch back' do
described_class.switch_back!(fallback_env)
end
end
end
describe '.pre_switch' do
subject { described_class.pre_switch(env, deployment) }
let(:env) { 'env' }
let(:deployment) { 'deployment' }
context 'no Gemfile.erb' do
before do
described_class.any_instance.expects(:has_gemfile_erb?).returns(false)
end
it { should be_false }
end
context 'Gemfile.erb' do
before do
described_class.any_instance.expects(:has_gemfile_erb?).returns(true)
described_class.any_instance.expects(:run_dot_penchant!).with(env, deployment)
end
it { should be_a_kind_of(described_class) }
end
end
describe '#switch_back!' do
let(:fallback_env) { 'fallback' }
let(:prior) { 'prior' }
context 'no prior' do
before do
gemfile.stubs(:prior_environment).returns(nil)
gemfile.expects(:switch_to!).with(fallback_env)
end
it 'should proxy through to switch_to!' do
gemfile.switch_back!(fallback_env)
end
end
context 'prior' do
before do
gemfile.stubs(:prior_environment).returns(prior)
gemfile.expects(:switch_to!).with(prior)
end
it 'should proxy through to switch_to!' do
gemfile.switch_back!(fallback_env)
end
end
end
end

View File

@ -1,4 +1,4 @@
#!/bin/bash
penchant gemfile remote
penchant gemfile remote --switch-back