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
|
||||
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
|
||||
|
|
|
@ -26,3 +26,13 @@ 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
|
||||
|
|
|
@ -15,6 +15,10 @@ module RemoteCommandHelpers
|
|||
def exists?(type, path)
|
||||
%{[ -#{type} "#{path}" ] && echo "#{path} exists." || echo "Error: #{path} does not exist."}
|
||||
end
|
||||
|
||||
def safely_remove_file(path)
|
||||
run_vagrant_command("rm #{test_file}") rescue Vagrant::Errors::VagrantError
|
||||
end
|
||||
end
|
||||
|
||||
World(RemoteCommandHelpers)
|
||||
|
|
|
@ -30,6 +30,14 @@ module Capistrano
|
|||
end
|
||||
end
|
||||
|
||||
def exit_because_of_exception(ex)
|
||||
if deploying?
|
||||
exit_deploy_because_of_exception(ex)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# allows the `cap install` task to load without a capfile
|
||||
|
|
|
@ -49,5 +49,15 @@ module Capistrano
|
|||
%w{install}
|
||||
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
|
||||
|
|
|
@ -18,6 +18,7 @@ en = {
|
|||
mirror_exists: "The repository mirror is at %{at}",
|
||||
revision_log_message: 'Branch %{branch} deployed as release %{release} by %{user}',
|
||||
rollback_log_message: '%{user} rolled back to release %{release}',
|
||||
deploy_failed: 'The deploy has failed with an error: %{ex}',
|
||||
console: {
|
||||
welcome: 'capistrano console - enter command to execute on %{stage}',
|
||||
bye: 'bye'
|
||||
|
|
|
@ -200,4 +200,6 @@ namespace :deploy do
|
|||
end
|
||||
end
|
||||
|
||||
task :failed
|
||||
|
||||
end
|
||||
|
|
|
@ -57,6 +57,7 @@ end
|
|||
|
||||
desc 'Deploy a new release.'
|
||||
task :deploy do
|
||||
set(:deploying, true)
|
||||
%w{ starting started
|
||||
updating updated
|
||||
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