require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper.rb')) require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'whiskey_disk')) require 'rake' describe 'requiring the main library' do before do Rake.application = @rake = Rake::Application.new load File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'tasks', 'deploy.rb')) end after do Rake.application = nil end it 'should make the deploy:setup rake task available' do Rake::Task.task_defined?('deploy:setup').should.be.true end it 'should make the deploy:now rake task available' do Rake::Task.task_defined?('deploy:now').should.be.true end end describe 'WhiskeyDisk' do describe 'ensuring that the parent path for the main repository checkout is present' do before do @parameters = { 'deploy_to' => '/path/to/main/repo' } WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters) WhiskeyDisk.reset end it 'should fail if the deployment path is not specified' do WhiskeyDisk::Config.stub!(:fetch).and_return({}) WhiskeyDisk.reset lambda { WhiskeyDisk.ensure_main_parent_path_is_present }.should.raise end it 'should attempt to create the parent path for the repository' do WhiskeyDisk.ensure_main_parent_path_is_present WhiskeyDisk.buffer.last.should.match(%r{mkdir -p /path/to/main}) WhiskeyDisk.buffer.last.should.not.match(%r{/path/to/main/repo}) end end describe 'ensuring that the parent path for the configuration repository checkout is present' do before do @parameters = { 'deploy_config_to' => '/path/to/config/repo' } WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters) WhiskeyDisk.reset end it 'should fail if the configuration deployment path is not specified' do WhiskeyDisk::Config.stub!(:fetch).and_return({}) WhiskeyDisk.reset lambda { WhiskeyDisk.ensure_config_parent_path_is_present }.should.raise end it 'should attempt to create the parent path for the repository' do WhiskeyDisk.ensure_config_parent_path_is_present WhiskeyDisk.buffer.last.should.match(%r{mkdir -p /path/to/config}) WhiskeyDisk.buffer.last.should.not.match(%r{/path/to/config/repo}) end end describe 'checking out the main repository' do before do @parameters = { 'deploy_to' => '/path/to/main/repo', 'repository' => 'git@ogtastic.com:whiskey_disk.git' } WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters) WhiskeyDisk.reset end it 'should fail if the deployment path is not specified' do WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters.merge('deploy_to' => nil)) WhiskeyDisk.reset lambda { WhiskeyDisk.checkout_main_repository }.should.raise end it 'should fail if the repository is not specified' do WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters.merge('repository' => nil)) WhiskeyDisk.reset lambda { WhiskeyDisk.checkout_main_repository }.should.raise end it 'should work from the main repository checkout parent path' do WhiskeyDisk.checkout_main_repository WhiskeyDisk.buffer.join(' ').should.match(%r{cd /path/to/main}) WhiskeyDisk.buffer.join(' ').should.not.match(%r{cd /path/to/main/repo}) end it 'should attempt to clone the main repository to the repository checkout path' do WhiskeyDisk.checkout_main_repository WhiskeyDisk.buffer.join(' ').should.match(%r{clone #{@parameters['repository']} repo}) end it 'should ignore errors from failing to clone an existing repository' do WhiskeyDisk.checkout_main_repository WhiskeyDisk.buffer.join(' ').should.match(%r{; true}) end end describe 'installing a post-receive hook on the checked out main repository' do before do @parameters = { 'deploy_to' => '/path/to/main/repo' } WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters) WhiskeyDisk.reset end it 'should fail if the deployment path is not specified' do WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters.merge('deploy_to' => nil)) WhiskeyDisk.reset lambda { WhiskeyDisk.install_hooks }.should.raise end # FIXME -- TODO: MORE HERE end describe 'checking out the configuration repository' do before do @parameters = { 'deploy_config_to' => '/path/to/config/repo', 'config_repository' => 'git@ogtastic.com:config.git' } WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters) WhiskeyDisk.reset end it 'should fail if the configuration deployment path is not specified' do WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters.merge('deploy_config_to' => nil)) WhiskeyDisk.reset lambda { WhiskeyDisk.checkout_configuration_repository }.should.raise end it 'should fail if the configuration repository is not specified' do WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters.merge('config_repository' => nil)) WhiskeyDisk.reset lambda { WhiskeyDisk.checkout_configuration_repository }.should.raise end it 'should work from the configuration repository checkout parent path' do WhiskeyDisk.checkout_configuration_repository WhiskeyDisk.buffer.join(' ').should.match(%r{cd /path/to/config}) WhiskeyDisk.buffer.join(' ').should.not.match(%r{cd /path/to/config/repo}) end it 'should attempt to clone the configuration repository to the repository checkout path' do WhiskeyDisk.checkout_configuration_repository WhiskeyDisk.buffer.join(' ').should.match(%r{clone #{@parameters['config_repository']} repo}) end it 'should ignore errors from failing to clone an existing repository' do WhiskeyDisk.checkout_configuration_repository WhiskeyDisk.buffer.join(' ').should.match(%r{; true}) end end describe 'updating the main repository checkout' do before do @parameters = { 'deploy_to' => '/path/to/main/repo' } WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters) WhiskeyDisk.reset end it 'should fail if the deployment path is not specified' do WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters.merge('deploy_to' => nil)) WhiskeyDisk.reset lambda { WhiskeyDisk.update_main_repository_checkout }.should.raise end it 'should work from the main repository checkout path' do WhiskeyDisk.update_main_repository_checkout WhiskeyDisk.buffer.join(' ').should.match(%r{cd /path/to/main/repo}) end it 'should attempt to fetch only the master branch from the origin if no branch is specified' do WhiskeyDisk.update_main_repository_checkout WhiskeyDisk.buffer.join(' ').should.match(%r{git fetch origin \+refs/heads/master:refs/remotes/origin/master}) end it 'should attempt to fetch the specified branch from the origin if a branch is specified' do WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters.merge({'branch' => 'production'})) WhiskeyDisk.reset WhiskeyDisk.update_main_repository_checkout WhiskeyDisk.buffer.join(' ').should.match(%r{git fetch origin \+refs/heads/production:refs/remotes/origin/production}) end it 'should attempt to reset the master branch from the origin if no branch is specified' do WhiskeyDisk.update_main_repository_checkout WhiskeyDisk.buffer.join(' ').should.match(%r{git reset --hard origin/master}) end it 'should attempt to reset the specified branch from the origin if a branch is specified' do WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters.merge({'branch' => 'production'})) WhiskeyDisk.reset WhiskeyDisk.update_main_repository_checkout WhiskeyDisk.buffer.join(' ').should.match(%r{git reset --hard origin/production}) end end describe 'updating the configuration repository checkout' do before do @parameters = { 'deploy_config_to' => '/path/to/config/repo' } WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters) WhiskeyDisk.reset end it 'should fail if the configuration deployment path is not specified' do WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters.merge('deploy_config_to' => nil)) WhiskeyDisk.reset lambda { WhiskeyDisk.update_configuration_repository_checkout }.should.raise end it 'should work from the main repository checkout path' do WhiskeyDisk.update_configuration_repository_checkout WhiskeyDisk.buffer.join(' ').should.match(%r{cd /path/to/config/repo}) end it 'should attempt to fetch only the master branch from the origin' do WhiskeyDisk.update_configuration_repository_checkout WhiskeyDisk.buffer.join(' ').should.match(%r{git fetch origin \+refs/heads/master:refs/remotes/origin/master}) end it 'should attempt to reset the master branch from the origin' do WhiskeyDisk.update_configuration_repository_checkout WhiskeyDisk.buffer.join(' ').should.match(%r{git reset --hard origin/master}) end end describe 'refreshing the configuration' do before do @parameters = { 'deploy_to' => '/path/to/main/repo', 'deploy_config_to' => '/path/to/config/repo', 'environment' => 'production', 'project' => 'whiskey_disk' } WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters) WhiskeyDisk.reset end it 'should fail if the main deployment path is not specified' do WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters.merge('deploy_to' => nil)) WhiskeyDisk.reset lambda { WhiskeyDisk.refresh_configuration }.should.raise end it 'should fail if the configuration deployment path is not specified' do WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters.merge('deploy_config_to' => nil)) WhiskeyDisk.reset lambda { WhiskeyDisk.refresh_configuration }.should.raise end it 'should use rsync to overlay the configuration checkout for the project in the configured environment onto the main checkout' do WhiskeyDisk.refresh_configuration WhiskeyDisk.buffer.last.should.match(%r{rsync.* /path/to/config/repo/whiskey_disk/production/ /path/to/main/repo/}) end end describe 'running post setup hooks' do before do @parameters = { 'deploy_to' => '/path/to/main/repo' } WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters) WhiskeyDisk.reset end it 'should fail if the deployment path is not specified' do WhiskeyDisk::Config.stub!(:fetch).and_return({}) WhiskeyDisk.reset lambda { WhiskeyDisk.run_post_setup_hooks }.should.raise end it 'should work from the main checkout directory' do WhiskeyDisk.run_post_setup_hooks WhiskeyDisk.buffer.join(' ').should.match(%r{cd /path/to/main/repo}) end it 'should attempt to run the post setup rake tasks' do WhiskeyDisk.run_post_setup_hooks WhiskeyDisk.buffer.join(' ').should.match(%r{rake.*deploy:post_setup}) end it 'should use the same environment when running the rake tasks' do WhiskeyDisk.run_post_setup_hooks WhiskeyDisk.buffer.join(' ').should.match(%r{to=#{@env}}) end end describe 'running post deployment hooks' do before do @parameters = { 'deploy_to' => '/path/to/main/repo' } WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters) WhiskeyDisk.reset end it 'should fail if the deployment path is not specified' do WhiskeyDisk::Config.stub!(:fetch).and_return({}) WhiskeyDisk.reset lambda { WhiskeyDisk.run_post_deploy_hooks }.should.raise end it 'should work from the main checkout directory' do WhiskeyDisk.run_post_deploy_hooks WhiskeyDisk.buffer.join(' ').should.match(%r{cd /path/to/main/repo}) end it 'should attempt to run the post deployment rake tasks' do WhiskeyDisk.run_post_deploy_hooks WhiskeyDisk.buffer.join(' ').should.match(%r{rake.*deploy:post_deploy}) end it 'should use the same environment when running the rake tasks' do WhiskeyDisk.run_post_deploy_hooks WhiskeyDisk.buffer.join(' ').should.match(%r{to=#{@env}}) end end describe 'flushing changes' do describe 'when running remotely' do before do @parameters = { 'domain' => 'www.domain.com', 'deploy_to' => '/path/to/main/repo' } WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters) WhiskeyDisk.reset WhiskeyDisk.stub!(:bundle).and_return('command string') WhiskeyDisk.stub!(:register_configuration) WhiskeyDisk.stub!(:run) end it 'should bundle the buffer of commands' do WhiskeyDisk.enqueue('x') WhiskeyDisk.enqueue('y') WhiskeyDisk.should.receive(:bundle).and_return('command string') WhiskeyDisk.flush end it 'should use "run" to run all the bundled commands at once' do WhiskeyDisk.should.receive(:run).with('command string') WhiskeyDisk.flush end end describe 'when running locally' do before do @parameters = { 'deploy_to' => '/path/to/main/repo' } WhiskeyDisk::Config.stub!(:fetch).and_return(@parameters) WhiskeyDisk.reset WhiskeyDisk.stub!(:bundle).and_return('command string') WhiskeyDisk.stub!(:system) end it 'should bundle the buffer of commands' do WhiskeyDisk.enqueue('x') WhiskeyDisk.enqueue('y') WhiskeyDisk.should.receive(:bundle).and_return('command string') WhiskeyDisk.flush end it 'should use "system" to run all the bundled commands at once' do WhiskeyDisk.should.receive(:system).with('command string') WhiskeyDisk.flush end end end describe 'bundling up buffered commands for execution' do before do WhiskeyDisk.reset end it 'should return an empty string if there are no commands' do WhiskeyDisk.bundle.should == '' end it 'should wrap each command with {} and join with &&s' do WhiskeyDisk.enqueue("cd foo/bar/baz || true") WhiskeyDisk.enqueue("rsync -avz --progress /yer/mom /yo/") WhiskeyDisk.bundle.should == "{ cd foo/bar/baz || true ; } && { rsync -avz --progress /yer/mom /yo/ ; }" end end describe 'when running a command string remotely' do before do @domain = 'ogc@ogtastic.com' WhiskeyDisk::Config.stub!(:fetch).and_return({ 'domain' => @domain }) WhiskeyDisk.reset WhiskeyDisk.stub!(:system) end it 'should accept a command string' do lambda { WhiskeyDisk.run('ls') }.should.not.raise(ArgumentError) end it 'should require a command string' do lambda { WhiskeyDisk.run }.should.raise(ArgumentError) end it 'should fail if the domain path is not specified' do WhiskeyDisk::Config.stub!(:fetch).and_return({}) WhiskeyDisk.reset lambda { WhiskeyDisk.run('ls') }.should.raise end it 'should pass the string to ssh with verbosity enabled' do WhiskeyDisk.should.receive(:system).with('ssh', '-v', @domain, "set -x; ls") WhiskeyDisk.run('ls') end end end