1
0
Fork 0
mirror of https://github.com/capistrano/capistrano synced 2023-03-27 23:21:18 -04:00

Merge branch '3.1.x'

Conflicts:
	CHANGELOG.md
	README.md
	lib/capistrano/tasks/git.rake
	lib/capistrano/templates/deploy.rb.erb
This commit is contained in:
seenmyfate 2013-11-02 11:08:10 +00:00
commit 22a98f30a6
32 changed files with 378 additions and 55 deletions

View file

@ -2,9 +2,20 @@
Reverse Chronological Order: Reverse Chronological Order:
## `3.1.0` (not released)
* `deploy:restart` task is no longer run by default.
From this version, developers who restart the app on each deploy need to declare it in their deploy flow (@kirs)
* Fixed bug when `deploy:cleanup` was executed twice by default (@kirs)
* Config location can now be changed with `deploy_config_path` and `stage_config_path` options (@seenmyfate)
* `no_release` option is now available (@seenmyfate)
* Raise an error if developer tries to define `:all` role, which is reserved (@kirs)
* `deploy:fallback` hook was added to add some custom behaviour on failed deploy (@seenmyfate)
* Correctly infer namespace in task enhancements (@seenmyfate)
## `3.0.1` ## `3.0.1`
* capify' not listed as executable (@leehambley) * `capify` not listed as executable (@leehambley)
* Confirm license as MIT (@leehambley) * Confirm license as MIT (@leehambley)
* Move the git ssh helper to application path (@mpapis) * Move the git ssh helper to application path (@mpapis)

View file

@ -126,7 +126,7 @@ This method is widely used.
``` ruby ``` ruby
desc "Ask about breakfast" desc "Ask about breakfast"
task :breakfast do task :breakfast do
breakfast = ask(:breakfast, "What would you like your colleagues to get you for breakfast?") breakfast = ask(:breakfast, "What would you like your colleagues to bring you for breakfast?")
on roles(:all) do |h| on roles(:all) do |h|
execute "echo \"$(whoami) wants #{breakfast} for breakfast!\" | wall" execute "echo \"$(whoami) wants #{breakfast} for breakfast!\" | wall"
end end

View file

@ -0,0 +1,15 @@
Feature: The path to the configuration can be changed, removing the need to
follow Ruby/Rails conventions
Background:
Given a test app with the default configuration
And servers with the roles app and web
Scenario: Deploying with configuration in default location
When I run "cap test"
Then the task is successful
Scenario: Deploying with configuration in a custom location
But the configuration is in a custom location
When I run "cap test"
Then the task is successful

View file

@ -34,6 +34,7 @@ Feature: Deploy
Then the task will be successful Then the task will be successful
Scenario: Creating a release Scenario: Creating a release
Given I run cap "deploy:check:directories"
When I run cap "git:create_release" as part of a release When I run cap "git:create_release" as part of a release
Then the repo is cloned Then the repo is cloned
And the release is created And the release is created

View file

@ -0,0 +1,17 @@
Feature: Deploy failure
Background:
Given a test app with the default configuration
And a custom task that will simulate a failure
And a custom task to run in the event of a failure
And servers with the roles app and web
Scenario: Triggering the custom task
When I run cap "deploy:starting"
But an error is raised
Then the failure task will not run
Scenario: Triggering the custom task
When I run cap "deploy"
But an error is raised
Then the failure task will run

View file

@ -88,3 +88,22 @@ end
Then(/^it will not recreate the file$/) do Then(/^it will not recreate the file$/) do
# #
end end
Then(/^the task is successful$/) do
expect(@success).to be_true
end
Then(/^the failure task will run$/) do
failed = TestApp.shared_path.join('failed')
run_vagrant_command(test_file_exists(failed))
end
Then(/^the failure task will not run$/) do
failed = TestApp.shared_path.join('failed')
!run_vagrant_command(test_file_exists(failed))
end
When(/^an error is raised$/) do
error = TestApp.shared_path.join('fail')
run_vagrant_command(test_file_exists(error))
end

View file

@ -1,8 +1,12 @@
When(/^I run cap "(.*?)"$/) do |task| When(/^I run cap "(.*?)"$/) do |task|
TestApp.cap(task) @success = TestApp.cap(task)
end end
When(/^I run cap "(.*?)" as part of a release$/) do |task| When(/^I run cap "(.*?)" as part of a release$/) do |task|
TestApp.cap("deploy:new_release_path #{task}") TestApp.cap("deploy:new_release_path #{task}")
end end
When(/^I run "(.*?)"$/) do |command|
@success = TestApp.run(command)
end

View file

@ -23,3 +23,16 @@ Given(/^a custom task to generate a file$/) do
TestApp.copy_task_to_test_app('spec/support/tasks/database.cap') TestApp.copy_task_to_test_app('spec/support/tasks/database.cap')
end end
Given(/^the configuration is in a custom location$/) do
TestApp.move_configuration_to_custom_location('app')
end
Given(/^a custom task that will simulate a failure$/) do
safely_remove_file(TestApp.shared_path.join('failed'))
TestApp.copy_task_to_test_app('spec/support/tasks/fail.cap')
end
Given(/^a custom task to run in the event of a failure$/) do
safely_remove_file(TestApp.shared_path.join('failed'))
TestApp.copy_task_to_test_app('spec/support/tasks/failed.cap')
end

View file

@ -15,6 +15,10 @@ module RemoteCommandHelpers
def exists?(type, path) def exists?(type, path)
%{[ -#{type} "#{path}" ] && echo "#{path} exists." || echo "Error: #{path} does not exist."} %{[ -#{type} "#{path}" ] && echo "#{path} exists." || echo "Error: #{path} does not exist."}
end end
def safely_remove_file(path)
run_vagrant_command("rm #{test_file}") rescue Vagrant::Errors::VagrantError
end
end end
World(RemoteCommandHelpers) World(RemoteCommandHelpers)

View file

@ -30,6 +30,14 @@ module Capistrano
end end
end end
def exit_because_of_exception(ex)
if deploying?
exit_deploy_because_of_exception(ex)
else
super
end
end
private private
# allows the `cap install` task to load without a capfile # allows the `cap install` task to load without a capfile

View file

@ -34,6 +34,10 @@ module Capistrano
end end
def role(name, hosts, options={}) def role(name, hosts, options={})
if name == :all
raise ArgumentError.new("#{name} reserved name for role. Please choose another name")
end
servers.add_role(name, hosts, options) servers.add_role(name, hosts, options)
end end

View file

@ -23,7 +23,7 @@ module Capistrano
end end
def select?(options) def select?(options)
selector = Selector.new(options) selector = Selector.for(options)
selector.call(self) selector.call(self)
end end
@ -103,6 +103,14 @@ module Capistrano
@options = options @options = options
end end
def self.for(options)
if options.has_key?(:exclude)
Exclusive
else
self
end.new(options)
end
def callable def callable
if key.respond_to?(:call) if key.respond_to?(:call)
key key
@ -126,6 +134,17 @@ module Capistrano
->(server) { :all } ->(server) { :all }
end end
class Exclusive < Selector
def key
options[:exclude]
end
def call(server)
!callable.call(server)
end
end
end end
end end

View file

@ -43,6 +43,16 @@ module Capistrano
env.roles_for(names) env.roles_for(names)
end end
def release_roles(*names)
options = { exclude: :no_release }
if names.last.is_a? Hash
names.last.merge(options)
else
names << options
end
roles(*names)
end
def primary(role) def primary(role)
env.primary(role) env.primary(role)
end end

View file

@ -27,6 +27,14 @@ module Capistrano
set(:release_path, releases_path.join(timestamp)) set(:release_path, releases_path.join(timestamp))
end end
def stage_config_path
Pathname.new fetch(:stage_config_path, 'config/deploy')
end
def deploy_config_path
Pathname.new fetch(:deploy_config_path, 'config/deploy.rb')
end
def repo_url def repo_url
require 'cgi' require 'cgi'
require 'uri' require 'uri'

View file

@ -3,7 +3,14 @@ module Capistrano
module Stages module Stages
def stages def stages
Dir['config/deploy/*.rb'].map { |f| File.basename(f, '.rb') } Dir[stage_definitions].map { |f| File.basename(f, '.rb') }
end
def infer_stages_from_stage_files
end
def stage_definitions
stage_config_path.join('*.rb')
end end
def stage_set? def stage_set?

View file

@ -6,9 +6,10 @@ module Capistrano
end end
def after(task, post_task, *args, &block) def after(task, post_task, *args, &block)
post_task = Rake::Task.define_task(post_task, *args, &block) if block_given? Rake::Task.define_task(post_task, *args, &block) if block_given?
post_task = Rake::Task[post_task]
Rake::Task[task].enhance do Rake::Task[task].enhance do
invoke(post_task) post_task.invoke
end end
end end
@ -49,5 +50,15 @@ module Capistrano
%w{install} %w{install}
end end
def exit_deploy_because_of_exception(ex)
warn t(:deploy_failed, ex: ex.inspect)
invoke 'deploy:failed'
exit(false)
end
def deploying?
fetch(:deploying, false)
end
end end
end end

View file

@ -7,7 +7,6 @@ en = {
start: 'Start', start: 'Start',
update: 'Update', update: 'Update',
finalize: 'Finalise', finalize: 'Finalise',
restart: 'Restart',
finishing: 'Finishing', finishing: 'Finishing',
finished: 'Finished', finished: 'Finished',
stage_not_set: 'Stage not set, please call something such as `cap production deploy`, where production is a stage you have defined.', stage_not_set: 'Stage not set, please call something such as `cap production deploy`, where production is a stage you have defined.',
@ -19,6 +18,7 @@ en = {
mirror_exists: "The repository mirror is at %{at}", mirror_exists: "The repository mirror is at %{at}",
revision_log_message: 'Branch %{branch} deployed as release %{release} by %{user}', revision_log_message: 'Branch %{branch} deployed as release %{release} by %{user}',
rollback_log_message: '%{user} rolled back to release %{release}', rollback_log_message: '%{user} rolled back to release %{release}',
deploy_failed: 'The deploy has failed with an error: %{ex}',
console: { console: {
welcome: 'capistrano console - enter command to execute on %{stage}', welcome: 'capistrano console - enter command to execute on %{stage}',
bye: 'bye' bye: 'bye'

View file

@ -8,11 +8,12 @@ end
stages.each do |stage| stages.each do |stage|
Rake::Task.define_task(stage) do Rake::Task.define_task(stage) do
invoke 'load:defaults'
load 'config/deploy.rb'
load "config/deploy/#{stage}.rb"
load "capistrano/#{fetch(:scm)}.rb"
set(:stage, stage.to_sym) set(:stage, stage.to_sym)
invoke 'load:defaults'
load deploy_config_path
load stage_config_path.join("#{stage}.rb")
load "capistrano/#{fetch(:scm)}.rb"
I18n.locale = fetch(:locale, :en) I18n.locale = fetch(:locale, :en)
configure_backend configure_backend
end end

View file

@ -15,7 +15,6 @@ namespace :deploy do
task :publishing do task :publishing do
invoke 'deploy:symlink:release' invoke 'deploy:symlink:release'
invoke 'deploy:restart'
end end
task :finishing do task :finishing do
@ -42,7 +41,7 @@ namespace :deploy do
namespace :check do namespace :check do
desc 'Check shared and release directories exist' desc 'Check shared and release directories exist'
task :directories do task :directories do
on roles :all do on release_roles :all do
execute :mkdir, '-pv', shared_path, releases_path execute :mkdir, '-pv', shared_path, releases_path
end end
end end
@ -80,7 +79,7 @@ namespace :deploy do
namespace :symlink do namespace :symlink do
desc 'Symlink release to current' desc 'Symlink release to current'
task :release do task :release do
on roles :all do on release_roles :all do
execute :rm, '-rf', current_path execute :rm, '-rf', current_path
execute :ln, '-s', release_path, current_path execute :ln, '-s', release_path, current_path
end end
@ -133,7 +132,7 @@ namespace :deploy do
desc 'Clean up old releases' desc 'Clean up old releases'
task :cleanup do task :cleanup do
on roles :all do |host| on release_roles :all do |host|
releases = capture(:ls, '-x', releases_path).split releases = capture(:ls, '-x', releases_path).split
if releases.count >= fetch(:keep_releases) if releases.count >= fetch(:keep_releases)
info t(:keeping_releases, host: host.to_s, keep_releases: fetch(:keep_releases), releases: releases.count) info t(:keeping_releases, host: host.to_s, keep_releases: fetch(:keep_releases), releases: releases.count)
@ -201,4 +200,7 @@ namespace :deploy do
end end
end end
task :restart
task :failed
end end

View file

@ -57,6 +57,7 @@ end
desc 'Deploy a new release.' desc 'Deploy a new release.'
task :deploy do task :deploy do
set(:deploying, true)
%w{ starting started %w{ starting started
updating updated updating updated
publishing published publishing published

View file

@ -9,7 +9,7 @@ namespace :git do
desc 'Upload the git wrapper script, this script guarantees that we can script git without getting an interactive prompt' desc 'Upload the git wrapper script, this script guarantees that we can script git without getting an interactive prompt'
task :wrapper do task :wrapper do
on roles :all do on release_roles :all do
execute :mkdir, "-p", "#{fetch(:tmp_dir)}/#{fetch(:application)}/" execute :mkdir, "-p", "#{fetch(:tmp_dir)}/#{fetch(:application)}/"
upload! StringIO.new("#!/bin/sh -e\nexec /usr/bin/ssh -o PasswordAuthentication=no -o StrictHostKeyChecking=no \"$@\"\n"), "#{fetch(:tmp_dir)}/#{fetch(:application)}/git-ssh.sh" upload! StringIO.new("#!/bin/sh -e\nexec /usr/bin/ssh -o PasswordAuthentication=no -o StrictHostKeyChecking=no \"$@\"\n"), "#{fetch(:tmp_dir)}/#{fetch(:application)}/git-ssh.sh"
execute :chmod, "+x", "#{fetch(:tmp_dir)}/#{fetch(:application)}/git-ssh.sh" execute :chmod, "+x", "#{fetch(:tmp_dir)}/#{fetch(:application)}/git-ssh.sh"
@ -19,7 +19,7 @@ namespace :git do
desc 'Check that the repository is reachable' desc 'Check that the repository is reachable'
task check: :'git:wrapper' do task check: :'git:wrapper' do
fetch(:branch) fetch(:branch)
on roles :all do on release_roles :all do
with fetch(:git_environmental_variables) do with fetch(:git_environmental_variables) do
exit 1 unless test :git, :'ls-remote', repo_url exit 1 unless test :git, :'ls-remote', repo_url
end end
@ -28,7 +28,7 @@ namespace :git do
desc 'Clone the repo to the cache' desc 'Clone the repo to the cache'
task clone: :'git:wrapper' do task clone: :'git:wrapper' do
on roles :all do on release_roles :all do
if test " [ -f #{repo_path}/HEAD ] " if test " [ -f #{repo_path}/HEAD ] "
info t(:mirror_exists, at: repo_path) info t(:mirror_exists, at: repo_path)
else else
@ -43,7 +43,7 @@ namespace :git do
desc 'Update the repo mirror to reflect the origin state' desc 'Update the repo mirror to reflect the origin state'
task update: :'git:clone' do task update: :'git:clone' do
on roles :all do on release_roles :all do
within repo_path do within repo_path do
execute :git, :remote, :update execute :git, :remote, :update
end end
@ -52,7 +52,7 @@ namespace :git do
desc 'Copy repo to releases' desc 'Copy repo to releases'
task create_release: :'git:update' do task create_release: :'git:update' do
on roles :all do on release_roles :all do
with fetch(:git_environmental_variables) do with fetch(:git_environmental_variables) do
within repo_path do within repo_path do
execute :mkdir, '-p', release_path execute :mkdir, '-p', release_path

View file

@ -1,14 +1,14 @@
namespace :hg do namespace :hg do
desc 'Check that the repo is reachable' desc 'Check that the repo is reachable'
task :check do task :check do
on roles :all do on release_roles :all do
execute "hg", "id", repo_url execute "hg", "id", repo_url
end end
end end
desc 'Clone the repo to the cache' desc 'Clone the repo to the cache'
task :clone do task :clone do
on roles :all do on release_roles :all do
if test " [ -d #{repo_path}/.hg ] " if test " [ -d #{repo_path}/.hg ] "
info t(:mirror_exists, at: repo_path) info t(:mirror_exists, at: repo_path)
else else
@ -21,7 +21,7 @@ namespace :hg do
desc 'Pull changes from the remote repo' desc 'Pull changes from the remote repo'
task :update => :'hg:clone' do task :update => :'hg:clone' do
on roles :all do on release_roles :all do
within repo_path do within repo_path do
execute "hg", "pull" execute "hg", "pull"
end end
@ -30,7 +30,7 @@ namespace :hg do
desc 'Copy repo to releases' desc 'Copy repo to releases'
task :create_release => :'hg:update' do task :create_release => :'hg:update' do
on roles :all do on release_roles :all do
within repo_path do within repo_path do
execute "hg", "archive", release_path, "--rev", fetch(:branch) execute "hg", "archive", release_path, "--rev", fetch(:branch)
end end

View file

@ -26,6 +26,8 @@ namespace :deploy do
end end
end end
after :publishing, :restart
after :restart, :clear_cache do after :restart, :clear_cache do
on roles(:web), in: :groups, limit: 3, wait: 10 do on roles(:web), in: :groups, limit: 3, wait: 10 do
# Here we can do anything such as: # Here we can do anything such as:
@ -35,6 +37,4 @@ namespace :deploy do
end end
end end
after :finishing, 'deploy:cleanup'
end end

View file

@ -1,10 +1,9 @@
set :stage, :<%= stage %>
# Simple Role Syntax # Simple Role Syntax
# ================== # ==================
# Supports bulk-adding hosts to roles, the primary # Supports bulk-adding hosts to roles, the primary
# server in each group is considered to be the first # server in each group is considered to be the first
# unless any hosts have the primary property set. # unless any hosts have the primary property set.
# Don't declare `role :all`, it's a meta role
role :app, %w{deploy@example.com} role :app, %w{deploy@example.com}
role :web, %w{deploy@example.com} role :web, %w{deploy@example.com}
role :db, %w{deploy@example.com} role :db, %w{deploy@example.com}

View file

@ -11,13 +11,33 @@ describe Capistrano::DSL do
dsl.server 'example2.com', roles: %w{web} dsl.server 'example2.com', roles: %w{web}
dsl.server 'example3.com', roles: %w{app web}, active: true dsl.server 'example3.com', roles: %w{app web}, active: true
dsl.server 'example4.com', roles: %w{app}, primary: true dsl.server 'example4.com', roles: %w{app}, primary: true
dsl.server 'example5.com', roles: %w{db}, no_release: true
end end
describe 'fetching all servers' do describe 'fetching all servers' do
subject { dsl.roles(:all) } subject { dsl.roles(:all) }
it 'returns all servers' do it 'returns all servers' do
expect(subject.map(&:hostname)).to eq %w{example1.com example2.com example3.com example4.com} expect(subject.map(&:hostname)).to eq %w{example1.com example2.com example3.com example4.com example5.com}
end
end
describe 'fetching all release servers' do
context 'with no additional options' do
subject { dsl.release_roles(:all) }
it 'returns all release servers' do
expect(subject.map(&:hostname)).to eq %w{example1.com example2.com example3.com example4.com}
end
end
context 'with filter options' do
subject { dsl.release_roles(:all, filter: :active) }
it 'returns all release servers that match the filter' do
expect(subject.map(&:hostname)).to eq %w{example1.com example3.com}
end
end end
end end
@ -70,6 +90,14 @@ describe Capistrano::DSL do
end end
describe 'when defining role with reserved name' do
it 'fails with ArgumentError' do
expect {
dsl.role :all, %w{example1.com}
}.to raise_error(ArgumentError, "all reserved name for role. Please choose another name")
end
end
describe 'when defining hosts using the `role` syntax' do describe 'when defining hosts using the `role` syntax' do
before do before do
dsl.role :web, %w{example1.com example2.com example3.com} dsl.role :web, %w{example1.com example2.com example3.com}
@ -77,16 +105,37 @@ describe Capistrano::DSL do
dsl.role :app, %w{example3.com example4.com} dsl.role :app, %w{example3.com example4.com}
dsl.role :app, %w{example3.com}, active: true dsl.role :app, %w{example3.com}, active: true
dsl.role :app, %w{example4.com}, primary: true dsl.role :app, %w{example4.com}, primary: true
dsl.role :db, %w{example5.com}, no_release: true
end end
describe 'fetching all servers' do describe 'fetching all servers' do
subject { dsl.roles(:all) } subject { dsl.roles(:all) }
it 'returns all servers' do it 'returns all servers' do
expect(subject.map(&:hostname)).to eq %w{example1.com example2.com example3.com example4.com} expect(subject.map(&:hostname)).to eq %w{example1.com example2.com example3.com example4.com example5.com}
end end
end end
describe 'fetching all release servers' do
context 'with no additional options' do
subject { dsl.release_roles(:all) }
it 'returns all release servers' do
expect(subject.map(&:hostname)).to eq %w{example1.com example2.com example3.com example4.com}
end
end
context 'with filter options' do
subject { dsl.release_roles(:all, filter: :active) }
it 'returns all release servers that match the filter' do
expect(subject.map(&:hostname)).to eq %w{example1.com example3.com}
end
end
end
describe 'fetching servers by role' do describe 'fetching servers by role' do
subject { dsl.roles(:app) } subject { dsl.roles(:app) }
@ -340,5 +389,53 @@ describe Capistrano::DSL do
end end
end end
describe 'setting deploy configuration path' do
subject { dsl.deploy_config_path.to_s }
context 'where no config path is set' do
before do
dsl.delete(:deploy_config_path)
end
it 'returns "config/deploy.rb"' do
expect(subject).to eq 'config/deploy.rb'
end
end
context 'where a custom path is set' do
before do
dsl.set(:deploy_config_path, 'my/custom/path.rb')
end
it 'returns the custom path' do
expect(subject).to eq 'my/custom/path.rb'
end
end
end
describe 'setting stage configuration path' do
subject { dsl.stage_config_path.to_s }
context 'where no config path is set' do
before do
dsl.delete(:stage_config_path)
end
it 'returns "config/deploy"' do
expect(subject).to eq 'config/deploy'
end
end
context 'where a custom path is set' do
before do
dsl.set(:stage_config_path, 'my/custom/path')
end
it 'returns the custom path' do
expect(subject).to eq 'my/custom/path'
end
end
end
end end
end end

View file

@ -159,6 +159,11 @@ module Capistrano
let(:options) { { select: :active }} let(:options) { { select: :active }}
it { should be_true } it { should be_true }
end end
context 'with :exclude' do
let(:options) { { exclude: :active }}
it { should be_false }
end
end end
context 'value does not match server properly' do context 'value does not match server properly' do
@ -171,6 +176,11 @@ module Capistrano
let(:options) { { select: :inactive }} let(:options) { { select: :inactive }}
it { should be_false } it { should be_false }
end end
context 'with :exclude' do
let(:options) { { exclude: :inactive }}
it { should be_true }
end
end end
end end
@ -186,6 +196,12 @@ module Capistrano
let(:options) { { select: ->(s) { s.properties.active } } } let(:options) { { select: ->(s) { s.properties.active } } }
it { should be_true } it { should be_true }
end end
context 'with :exclude' do
let(:options) { { exclude: ->(s) { s.properties.active } } }
it { should be_false }
end
end end
context 'value does not match server properly' do context 'value does not match server properly' do
@ -198,6 +214,12 @@ module Capistrano
let(:options) { { select: ->(s) { s.properties.inactive } } } let(:options) { { select: ->(s) { s.properties.inactive } } }
it { should be_false } it { should be_false }
end end
context 'with :exclude' do
let(:options) { { exclude: ->(s) { s.properties.inactive } } }
it { should be_true }
end
end end
end end

View file

@ -141,6 +141,35 @@ module Capistrano
end end
describe 'excluding by property' do
before do
servers.add_host('1', roles: :app, active: true)
servers.add_host('2', roles: :app, active: true, no_release: true)
end
it 'is empty if the filter would remove all matching hosts' do
hosts = servers.roles_for([:app, exclude: :active])
expect(hosts.map(&:hostname)).to be_empty
end
it 'returns the servers without the attributes specified' do
hosts = servers.roles_for([:app, exclude: :no_release])
expect(hosts.map(&:hostname)).to eq %w{1}
end
it 'can exclude hosts by properties on the host using a regular proc' do
hosts = servers.roles_for([:app, exclude: ->(h) { h.properties.no_release }])
expect(hosts.map(&:hostname)).to eq %w{1}
end
it 'is empty if the regular proc filter would remove all matching hosts' do
hosts = servers.roles_for([:app, exclude: ->(h) { h.properties.active }])
expect(hosts.map(&:hostname)).to be_empty
end
end
describe 'filtering roles' do describe 'filtering roles' do
before do before do

View file

@ -1,10 +0,0 @@
require 'spec_helper'
module Capistrano
module DSL
describe Env do
end
end
end

View file

@ -20,17 +20,6 @@ module Capistrano
end end
end end
describe '#stages' do
before do
Dir.expects(:[]).with('config/deploy/*.rb').
returns(['config/deploy/staging.rb', 'config/deploy/production.rb'])
end
it 'returns a list of defined stages' do
expect(dsl.stages).to eq %w{staging production}
end
end
describe '#stage_set?' do describe '#stage_set?' do
subject { dsl.stage_set? } subject { dsl.stage_set? }

View file

@ -0,0 +1,7 @@
set :fail, proc { fail }
before 'deploy:starting', :fail do
on roles :all do
execute :touch, shared_path.join('fail')
end
fetch(:fail)
end

View file

@ -0,0 +1,5 @@
after 'deploy:failed', :failed do
on roles :all do
execute :touch, shared_path.join('failed')
end
end

View file

@ -8,10 +8,9 @@ module TestApp
def default_config def default_config
%{ %{
set :stage, :#{stage}
set :deploy_to, '#{deploy_to}' set :deploy_to, '#{deploy_to}'
set :repo_url, 'git://github.com/capistrano/capistrano.git' set :repo_url, 'git://github.com/capistrano/capistrano.git'
set :branch, 'v3' set :branch, 'master'
set :ssh_options, { keys: "\#{ENV['HOME']}/.vagrant.d/insecure_private_key" } set :ssh_options, { keys: "\#{ENV['HOME']}/.vagrant.d/insecure_private_key" }
server 'vagrant@localhost:2220', roles: %w{web app} server 'vagrant@localhost:2220', roles: %w{web app}
set :linked_files, #{linked_files} set :linked_files, #{linked_files}
@ -58,6 +57,14 @@ module TestApp
end end
end end
def prepend_to_capfile(config)
current_capfile = File.read(capfile)
File.open(capfile, 'w') do |file|
file.write config
file.write current_capfile
end
end
def create_shared_directory(path) def create_shared_directory(path)
FileUtils.mkdir_p(shared_path.join(path)) FileUtils.mkdir_p(shared_path.join(path))
end end
@ -67,9 +74,14 @@ module TestApp
end end
def cap(task) def cap(task)
run "bundle exec cap #{stage} #{task}"
end
def run(command)
Dir.chdir(test_app_path) do Dir.chdir(test_app_path) do
%x[bundle exec cap #{stage} #{task}] %x[#{command}]
end end
$?.success?
end end
def stage def stage
@ -135,4 +147,22 @@ module TestApp
def copy_task_to_test_app(source) def copy_task_to_test_app(source)
FileUtils.cp(source, task_dir) FileUtils.cp(source, task_dir)
end end
def config_path
test_app_path.join('config')
end
def move_configuration_to_custom_location(location)
prepend_to_capfile(
%{
set :stage_config_path, "app/config/deploy"
set :deploy_config_path, "app/config/deploy.rb"
}
)
location = test_app_path.join(location)
FileUtils.mkdir_p(location)
FileUtils.mv(config_path, location)
end
end end