mirror of
https://github.com/capistrano/capistrano
synced 2023-03-27 23:21:18 -04:00
Add hook for deploy failure
If an error is raised during a deploy, the task `deploy:failed` will be triggered. Custom tasks can hook into this using `after`: after 'deploy:failed', :send_for_help do # end I've also taken the opportunity to provide a marginally more useful error message before triggering the task. By default, this 'deploy:failed' will only be triggered when running `cap <stage> deploy` - to trigger after individual tasks use `set :deploying, true` This closes #708 and replaces https://github.com/capistrano/capistrano/pull/720
This commit is contained in:
parent
3ace303dd9
commit
7432c710b0
11 changed files with 80 additions and 0 deletions
17
features/deploy_failure.feature
Normal file
17
features/deploy_failure.feature
Normal 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
|
|
@ -92,3 +92,18 @@ end
|
||||||
Then(/^the task is successful$/) do
|
Then(/^the task is successful$/) do
|
||||||
expect(@success).to be_true
|
expect(@success).to be_true
|
||||||
end
|
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
|
||||||
|
|
|
@ -26,3 +26,13 @@ end
|
||||||
Given(/^the configuration is in a custom location$/) do
|
Given(/^the configuration is in a custom location$/) do
|
||||||
TestApp.move_configuration_to_custom_location('app')
|
TestApp.move_configuration_to_custom_location('app')
|
||||||
end
|
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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -49,5 +49,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
|
||||||
|
|
|
@ -18,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'
|
||||||
|
|
|
@ -200,4 +200,6 @@ namespace :deploy do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
task :failed
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -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
|
||||||
|
|
7
spec/support/tasks/fail.cap
Normal file
7
spec/support/tasks/fail.cap
Normal 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
|
5
spec/support/tasks/failed.cap
Normal file
5
spec/support/tasks/failed.cap
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
after 'deploy:failed', :failed do
|
||||||
|
on roles :all do
|
||||||
|
execute :touch, shared_path.join('failed')
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue