diff --git a/Gemfile b/Gemfile index d2c4133..65ab311 100644 --- a/Gemfile +++ b/Gemfile @@ -5,4 +5,5 @@ gemspec group :test do gem 'rspec' gem 'capistrano-spec' -end \ No newline at end of file + gem 'pry-debugger' +end diff --git a/lib/capistrano-unicorn/capistrano_integration.rb b/lib/capistrano-unicorn/capistrano_integration.rb index 9fcaca8..450dc68 100644 --- a/lib/capistrano-unicorn/capistrano_integration.rb +++ b/lib/capistrano-unicorn/capistrano_integration.rb @@ -1,6 +1,7 @@ require 'tempfile' require 'capistrano' +require 'capistrano-unicorn/config' require 'capistrano/version' module CapistranoUnicorn @@ -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 diff --git a/lib/capistrano-unicorn/config.rb b/lib/capistrano-unicorn/config.rb new file mode 100644 index 0000000..d399864 --- /dev/null +++ b/lib/capistrano-unicorn/config.rb @@ -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 diff --git a/spec/capistrano_integration_spec.rb b/spec/capistrano_integration_spec.rb index e82eb97..07ebd8c 100644 --- a/spec/capistrano_integration_spec.rb +++ b/spec/capistrano_integration_spec.rb @@ -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 diff --git a/spec/config_spec.rb b/spec/config_spec.rb new file mode 100644 index 0000000..aa6f60b --- /dev/null +++ b/spec/config_spec.rb @@ -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 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 97808f0..88b7580 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,7 +1,8 @@ require 'capistrano-spec' require 'capistrano-unicorn' +require 'pry' RSpec.configure do |config| config.include Capistrano::Spec::Matchers config.include Capistrano::Spec::Helpers -end \ No newline at end of file +end