diff --git a/README.md b/README.md index 941a8885..d574287f 100644 --- a/README.md +++ b/README.md @@ -646,18 +646,21 @@ That'll post a line like follows to a preconfigured chatbot in Basecamp: [My App] [dhh] Rolled back to version d264c4e92470ad1bd18590f04466787262f605de ``` -### Using custom healthcheck path or port +### Custom healthcheck -MRSK defaults to checking the health of your application again `/up` on port 3000. You can tailor both with the `healthcheck` setting: +MRSK defaults to checking the health of your application again `/up` on port 3000 up to 7 times. You can tailor the behaviour with the `healthcheck` setting: ```yaml healthcheck: path: /healthz port: 4000 + max_attempts: 7 ``` This will ensure your application is configured with a traefik label for the healthcheck against `/healthz` and that the pre-deploy healthcheck that MRSK performs is done against the same path on port 4000. +The healthcheck also allows for an optional `max_attempts` setting, which will attempt the healthcheck up to the specified number of times before failing the deploy. This is useful for applications that take a while to start up. The default is 7. + ## Commands ### Running commands on servers diff --git a/lib/mrsk/cli/healthcheck.rb b/lib/mrsk/cli/healthcheck.rb index 3fda7754..5e9f42dc 100644 --- a/lib/mrsk/cli/healthcheck.rb +++ b/lib/mrsk/cli/healthcheck.rb @@ -1,5 +1,4 @@ class Mrsk::Cli::Healthcheck < Mrsk::Cli::Base - MAX_ATTEMPTS = 7 class HealthcheckError < StandardError; end @@ -13,6 +12,7 @@ class Mrsk::Cli::Healthcheck < Mrsk::Cli::Base target = "Health check against #{MRSK.config.healthcheck["path"]}" attempt = 1 + max_attempts = MRSK.config.healthcheck["max_attempts"] begin status = capture_with_info(*MRSK.healthcheck.curl) @@ -23,8 +23,8 @@ class Mrsk::Cli::Healthcheck < Mrsk::Cli::Base raise HealthcheckError, "#{target} failed with status #{status}" end rescue SSHKit::Command::Failed - if attempt <= MAX_ATTEMPTS - info "#{target} failed to respond, retrying in #{attempt}s..." + if attempt <= max_attempts + info "#{target} failed to respond, retrying in #{attempt}s (attempt #{attempt}/#{max_attempts})..." sleep attempt attempt += 1 diff --git a/lib/mrsk/configuration.rb b/lib/mrsk/configuration.rb index c8ac5a03..a2c2ecf1 100644 --- a/lib/mrsk/configuration.rb +++ b/lib/mrsk/configuration.rb @@ -158,7 +158,7 @@ class Mrsk::Configuration end def healthcheck - { "path" => "/up", "port" => 3000 }.merge(raw_config.healthcheck || {}) + { "path" => "/up", "port" => 3000, "max_attempts" => 7 }.merge(raw_config.healthcheck || {}) end def readiness_delay diff --git a/test/cli/healthcheck_test.rb b/test/cli/healthcheck_test.rb index 7a9df6eb..a3441a7e 100644 --- a/test/cli/healthcheck_test.rb +++ b/test/cli/healthcheck_test.rb @@ -23,8 +23,8 @@ class CliHealthcheckTest < CliTestCase .returns("200") run_command("perform").tap do |output| - assert_match "Health check against /up failed to respond, retrying in 1s...", output - assert_match "Health check against /up failed to respond, retrying in 2s...", output + assert_match "Health check against /up failed to respond, retrying in 1s (attempt 1/7)...", output + assert_match "Health check against /up failed to respond, retrying in 2s (attempt 2/7)...", output assert_match "Health check against /up succeeded with 200 OK!", output end end diff --git a/test/configuration_test.rb b/test/configuration_test.rb index ec65686d..2697673b 100644 --- a/test/configuration_test.rb +++ b/test/configuration_test.rb @@ -249,6 +249,6 @@ class ConfigurationTest < ActiveSupport::TestCase end test "to_h" do - assert_equal({ :roles=>["web"], :hosts=>["1.1.1.1", "1.1.1.2"], :primary_host=>"1.1.1.1", :version=>"missing", :repository=>"dhh/app", :absolute_image=>"dhh/app:missing", :service_with_version=>"app-missing", :env_args=>["-e", "REDIS_URL=\"redis://x/y\""], :ssh_options=>{:user=>"root", :auth_methods=>["publickey"]}, :volume_args=>["--volume", "/local/path:/container/path"], :logging=>["--log-opt", "max-size=\"10m\""], :healthcheck=>{"path"=>"/up", "port"=>3000 }}, @config.to_h) + assert_equal({ :roles=>["web"], :hosts=>["1.1.1.1", "1.1.1.2"], :primary_host=>"1.1.1.1", :version=>"missing", :repository=>"dhh/app", :absolute_image=>"dhh/app:missing", :service_with_version=>"app-missing", :env_args=>["-e", "REDIS_URL=\"redis://x/y\""], :ssh_options=>{:user=>"root", :auth_methods=>["publickey"]}, :volume_args=>["--volume", "/local/path:/container/path"], :logging=>["--log-opt", "max-size=\"10m\""], :healthcheck=>{"path"=>"/up", "port"=>3000, "max_attempts" => 7 }}, @config.to_h) end end