Skip to content

Commit

Permalink
Split capistrano integration from configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxim-Filimonov committed Sep 11, 2013
1 parent 4471dc6 commit 9c355a5
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 173 deletions.
3 changes: 2 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ gemspec
group :test do
gem 'rspec'
gem 'capistrano-spec'
end
gem 'pry-debugger'
end
47 changes: 3 additions & 44 deletions lib/capistrano-unicorn/capistrano_integration.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require 'tempfile'

require 'capistrano'
require 'capistrano-unicorn/config'
require 'capistrano/version'

module CapistranoUnicorn
Expand All @@ -19,51 +20,9 @@ class CapistranoIntegration

def self.load_into(capistrano_config)
capistrano_config.load do
before(CapistranoIntegration::TASKS) do
# Environments
_cset(:unicorn_env) { fetch(:rails_env, 'production' ) }
_cset(:unicorn_rack_env) do
# Following recommendations from http://unicorn.bogomips.org/unicorn_1.html
fetch(:rails_env) == 'development' ? 'development' : 'deployment'
end

# Execution
_cset(:unicorn_user) { nil }
_cset(:unicorn_bundle) { fetch(:bundle_cmd, "bundle") }
_cset(:unicorn_bin) { "unicorn" }
_cset(:unicorn_options) { '' }
_cset(:unicorn_restart_sleep_time) { 2 }

# Relative paths
_cset(:app_subdir) { '' }
_cset(:unicorn_config_rel_path) { "config" }
_cset(:unicorn_config_filename) { "unicorn.rb" }
_cset(:unicorn_config_rel_file_path) \
{ unicorn_config_rel_path + '/' + unicorn_config_filename }
_cset(:unicorn_config_stage_rel_file_path) \
{ [ unicorn_config_rel_path, 'unicorn',
"#{unicorn_env}.rb" ].join('/') }

# Absolute paths
# If you find the following confusing, try running 'cap unicorn:show_vars' -
# it might help :-)
_cset(:app_path) { current_path + app_subdir }
_cset(:bundle_gemfile) { app_path + '/Gemfile' }
_cset(:unicorn_config_path) { app_path + '/' + unicorn_config_rel_path }
_cset(:unicorn_config_file_path) { app_path + '/' + unicorn_config_rel_file_path }
_cset(:unicorn_config_stage_file_path) \
{ app_path + '/' + unicorn_config_stage_rel_file_path }
_cset(:unicorn_default_pid) { app_path + "/tmp/pids/unicorn.pid" }
_cset(:unicorn_pid) do
extracted_pid = extract_pid_file
if extracted_pid
extracted_pid
else
logger.important "err :: failed to auto-detect pid from #{local_unicorn_config}"
logger.important "err :: falling back to default: #{unicorn_default_pid}"
unicorn_default_pid
end
end
before(CapistranoIntegration::TASKS) do
Config.load(self)
end

def local_unicorn_config
Expand Down
52 changes: 52 additions & 0 deletions lib/capistrano-unicorn/config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
module CapistranoUnicorn
class Config
def self.load(config)
config.instance_eval do
# Environments
_cset(:unicorn_env) { fetch(:rails_env, 'production' ) }
_cset(:unicorn_rack_env) do
# Following recommendations from http://unicorn.bogomips.org/unicorn_1.html
fetch(:rails_env) == 'development' ? 'development' : 'deployment'
end

# Execution
_cset(:unicorn_user) { nil }
_cset(:unicorn_bundle) { fetch(:bundle_cmd, "bundle") }
_cset(:unicorn_bin) { "unicorn" }
_cset(:unicorn_options) { '' }
_cset(:unicorn_restart_sleep_time) { 2 }

# Relative paths
_cset(:app_subdir) { '' }
_cset(:unicorn_config_rel_path) { "config" }
_cset(:unicorn_config_filename) { "unicorn.rb" }
_cset(:unicorn_config_rel_file_path) \
{ unicorn_config_rel_path + '/' + unicorn_config_filename }
_cset(:unicorn_config_stage_rel_file_path) \
{ [ unicorn_config_rel_path, 'unicorn',
"#{unicorn_env}.rb" ].join('/') }

# Absolute paths
# If you find the following confusing, try running 'cap unicorn:show_vars' -
# it might help :-)
_cset(:app_path) { current_path + app_subdir }
_cset(:bundle_gemfile) { app_path + '/Gemfile' }
_cset(:unicorn_config_path) { app_path + '/' + unicorn_config_rel_path }
_cset(:unicorn_config_file_path) { app_path + '/' + unicorn_config_rel_file_path }
_cset(:unicorn_config_stage_file_path) \
{ app_path + '/' + unicorn_config_stage_rel_file_path }
_cset(:unicorn_default_pid) { app_path + "/tmp/pids/unicorn.pid" }
_cset(:unicorn_pid) do
extracted_pid = extract_pid_file
if extracted_pid
extracted_pid
else
logger.important "err :: failed to auto-detect pid from #{local_unicorn_config}"
logger.important "err :: falling back to default: #{unicorn_default_pid}"
unicorn_default_pid
end
end
end
end
end
end
128 changes: 1 addition & 127 deletions spec/capistrano_integration_spec.rb
Original file line number Diff line number Diff line change
@@ -1,138 +1,12 @@
require "spec_helper"

describe CapistranoUnicorn::CapistranoIntegration, "loaded into a configuration" do
describe CapistranoUnicorn::CapistranoIntegration, "loaded tasks into capistrano" do
before do
@configuration = Capistrano::Configuration.new
@configuration.extend(Capistrano::Spec::ConfigurationExtension)
CapistranoUnicorn::CapistranoIntegration.load_into(@configuration)
end

context "testing variables" do
before do
# define _cset etc. from capistrano
@configuration.load 'deploy'

# capistrano-unicorn variables are set during a 'before'
# callback, so in order to be able to test the result, we need
# to ensure the callback is triggered.
@configuration.trigger :before
end

describe "app paths" do
cur_path = '/path/to/myapp'

before do
@configuration.set(:current_path, cur_path)
end

shared_examples_for "an app in path" do |app_path|
let(:shell) { :` } # ` } work around confused emacs ruby-mode

specify "app_path should default to #{app_path}" do
@configuration.fetch(:app_path).should == app_path
end

it "should default to a sensible pid file when auto-detection failed" do
@configuration.should_receive(shell).with(/unicorn -c /).and_return('') do |cmd|
$?.should_receive(:success?).and_return(false)
end
@configuration.logger.stub(:important)
@configuration.fetch(:unicorn_pid).should == app_path + "/tmp/pids/unicorn.pid"
end

shared_examples "auto-detect pid file from unicorn config" do
|pid_file, primary_exists, config_file|
which_config = primary_exists ? 'primary' : 'stage'
it "should auto-detect pid file from #{which_config} unicorn config" do
# Tempfile.new in Ruby 1.9.2 will call File.exist?
allow(File).to receive(:exist?).with(/tmp/)

File.should_receive(:exist?).with('config/unicorn.rb').and_return(primary_exists)
tmpfile = nil
@configuration.should_receive(shell).with(/unicorn -c /) do |cmd|
(cmd =~ /^unicorn -c "(.+)"$/).should be_true
tmpfile = $~[1]
tmpfile.should include("tmp")
File.read(tmpfile).should include(%!config_file = "#{config_file}"!)
$?.should_receive(:success?).and_return(true)
pid_file
end
@configuration.fetch(:unicorn_pid).should == pid_file
end
end

include_examples "auto-detect pid file from unicorn config", \
'/path/to/pid/from/config/file', true, "config/unicorn.rb"

include_examples "auto-detect pid file from unicorn config", \
'/path/to/pid/from/stage/config/file', false, "config/unicorn/production.rb"

specify "Gemfile should default correctly" do
@configuration.fetch(:bundle_gemfile).should == app_path + "/Gemfile"
end

specify "config/ directory should default correctly" do
@configuration.fetch(:unicorn_config_path).should == app_path + "/config"
end

specify "config file should default correctly" do
@configuration.fetch(:unicorn_config_file_path).should == app_path + "/config/unicorn.rb"
end

specify "per-stage config file should default correctly" do
@configuration.fetch(:unicorn_config_stage_file_path).should == app_path + "/config/unicorn/production.rb"
end

specify "per-stage config file should be set correctly for different environment" do
@configuration.set(:rails_env, 'staging')
@configuration.fetch(:unicorn_config_stage_file_path).should == app_path + "/config/unicorn/staging.rb"
end
end

context "app in current_path" do
it_should_behave_like "an app in path", cur_path
end

context "app in a subdirectory" do
subdir = 'mysubdir'

before do
@configuration.set(:app_subdir, '/' + subdir)
end

it_should_behave_like "an app in path", cur_path + '/' + subdir
end
end

describe "unicorn_env" do
it "should default to value of rails_env if set" do
@configuration.set(:rails_env, 'staging')
@configuration.fetch(:unicorn_env).should == \
@configuration.fetch(:rails_env)
end

it "should default to production if rails_env not set" do
@configuration.fetch(:unicorn_env).should == 'production'
end
end

describe "unicorn_rack_env" do
it "should default to deployment if rails_env not set" do
@configuration.fetch(:unicorn_rack_env).should == 'deployment'
end

it "should default to development if rails_env set to development" do
@configuration.set(:rails_env, 'development')
@configuration.fetch(:unicorn_rack_env).should == 'development'
end

it "should default to deployment if rails_env set to anything else" do
@configuration.set(:rails_env, 'staging')
@configuration.fetch(:unicorn_rack_env).should == 'deployment'
end
end
end

shared_examples_for "a task" do |task_name|
it "sets attributes in before_task hook" do
# Environments
Expand Down
134 changes: 134 additions & 0 deletions spec/config_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
require 'spec_helper'
describe CapistranoUnicorn::Config, "loaded into a configuration" do
before do
@configuration = Capistrano::Configuration.new
@configuration.extend(Capistrano::Spec::ConfigurationExtension)
CapistranoUnicorn::CapistranoIntegration.load_into(@configuration)
end

context "testing variables" do
before do
# define _cset etc. from capistrano
@configuration.load 'deploy'

# capistrano-unicorn variables are set during a 'before'
# callback, so in order to be able to test the result, we need
# to ensure the callback is triggered.
@configuration.trigger :before
end

describe "app paths" do
cur_path = '/path/to/myapp'

before do
@configuration.set(:current_path, cur_path)
end

shared_examples_for "an app in path" do |app_path|
let(:shell) { :` } # ` } work around confused emacs ruby-mode

specify "app_path should default to #{app_path}" do
@configuration.fetch(:app_path).should == app_path
end

it "should default to a sensible pid file when auto-detection failed" do
@configuration.should_receive(shell).with(/unicorn -c /).and_return('') do |cmd|
$?.should_receive(:success?).and_return(false)
end
@configuration.logger.stub(:important)
@configuration.fetch(:unicorn_pid).should == app_path + "/tmp/pids/unicorn.pid"
end

shared_examples "auto-detect pid file from unicorn config" do
|pid_file, primary_exists, config_file|
which_config = primary_exists ? 'primary' : 'stage'
it "should auto-detect pid file from #{which_config} unicorn config" do
# Tempfile.new in Ruby 1.9.2 will call File.exist?
allow(File).to receive(:exist?).with(/tmp/)

File.should_receive(:exist?).with('config/unicorn.rb').and_return(primary_exists)
tmpfile = nil
@configuration.should_receive(shell).with(/unicorn -c /) do |cmd|
(cmd =~ /^unicorn -c "(.+)"$/).should be_true
tmpfile = $~[1]
tmpfile.should include("tmp")
File.read(tmpfile).should include(%!config_file = "#{config_file}"!)
$?.should_receive(:success?).and_return(true)
pid_file
end
@configuration.fetch(:unicorn_pid).should == pid_file
end
end

include_examples "auto-detect pid file from unicorn config", \
'/path/to/pid/from/config/file', true, "config/unicorn.rb"

include_examples "auto-detect pid file from unicorn config", \
'/path/to/pid/from/stage/config/file', false, "config/unicorn/production.rb"

specify "Gemfile should default correctly" do
@configuration.fetch(:bundle_gemfile).should == app_path + "/Gemfile"
end

specify "config/ directory should default correctly" do
@configuration.fetch(:unicorn_config_path).should == app_path + "/config"
end

specify "config file should default correctly" do
@configuration.fetch(:unicorn_config_file_path).should == app_path + "/config/unicorn.rb"
end

specify "per-stage config file should default correctly" do
@configuration.fetch(:unicorn_config_stage_file_path).should == app_path + "/config/unicorn/production.rb"
end

specify "per-stage config file should be set correctly for different environment" do
@configuration.set(:rails_env, 'staging')
@configuration.fetch(:unicorn_config_stage_file_path).should == app_path + "/config/unicorn/staging.rb"
end
end

context "app in current_path" do
it_should_behave_like "an app in path", cur_path
end

context "app in a subdirectory" do
subdir = 'mysubdir'

before do
@configuration.set(:app_subdir, '/' + subdir)
end

it_should_behave_like "an app in path", cur_path + '/' + subdir
end
end

describe "unicorn_env" do
it "should default to value of rails_env if set" do
@configuration.set(:rails_env, 'staging')
@configuration.fetch(:unicorn_env).should == \
@configuration.fetch(:rails_env)
end

it "should default to production if rails_env not set" do
@configuration.fetch(:unicorn_env).should == 'production'
end
end

describe "unicorn_rack_env" do
it "should default to deployment if rails_env not set" do
@configuration.fetch(:unicorn_rack_env).should == 'deployment'
end

it "should default to development if rails_env set to development" do
@configuration.set(:rails_env, 'development')
@configuration.fetch(:unicorn_rack_env).should == 'development'
end

it "should default to deployment if rails_env set to anything else" do
@configuration.set(:rails_env, 'staging')
@configuration.fetch(:unicorn_rack_env).should == 'deployment'
end
end
end
end
Loading

0 comments on commit 9c355a5

Please sign in to comment.