health_check_rb 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/linters.yml +27 -0
  3. data/.github/workflows/tests.yml +50 -0
  4. data/.gitignore +33 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +110 -0
  7. data/CHANGELOG +122 -0
  8. data/Gemfile +23 -0
  9. data/MIT-LICENSE +23 -0
  10. data/README.md +392 -0
  11. data/Rakefile +27 -0
  12. data/config/routes.rb +7 -0
  13. data/health_check_rb.gemspec +26 -0
  14. data/init.rb +3 -0
  15. data/lib/health_check_rb/base_health_check.rb +7 -0
  16. data/lib/health_check_rb/check/elasticsearch.rb +18 -0
  17. data/lib/health_check_rb/check/rabbitmq.rb +19 -0
  18. data/lib/health_check_rb/check/redis.rb +30 -0
  19. data/lib/health_check_rb/check/resque.rb +18 -0
  20. data/lib/health_check_rb/check/s3.rb +62 -0
  21. data/lib/health_check_rb/check/sidekiq.rb +20 -0
  22. data/lib/health_check_rb/health_check_controller.rb +80 -0
  23. data/lib/health_check_rb/health_check_routes.rb +18 -0
  24. data/lib/health_check_rb/middleware_health_check.rb +108 -0
  25. data/lib/health_check_rb/utils.rb +194 -0
  26. data/lib/health_check_rb/version.rb +5 -0
  27. data/lib/health_check_rb.rb +129 -0
  28. data/spec/dummy/Rakefile +8 -0
  29. data/spec/dummy/app/assets/config/manifest.js +1 -0
  30. data/spec/dummy/app/controllers/example_controller.rb +7 -0
  31. data/spec/dummy/config/database.yml +10 -0
  32. data/spec/dummy/config/initializers/health_check.rb +18 -0
  33. data/spec/dummy/config/initializers/middleware.rb +3 -0
  34. data/spec/dummy/config/routes.rb +5 -0
  35. data/spec/dummy/db/migrate/.keep +0 -0
  36. data/spec/dummy/fake_app.rb +18 -0
  37. data/spec/dummy/tmp/.keep +0 -0
  38. data/spec/fixtures/migrate/9_create_countries.rb +9 -0
  39. data/spec/health_check_rb_spec.rb +300 -0
  40. data/spec/spec_helper.rb +36 -0
  41. metadata +101 -0
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ipaddr'
4
+
5
+ module HealthCheckRb
6
+ class HealthCheckController < ActionController::Base
7
+ layout false if respond_to? :layout
8
+ before_action :check_origin_ip
9
+ before_action :authenticate
10
+
11
+ def index
12
+ last_modified = Time.now.utc
13
+ max_age = HealthCheckRb.max_age
14
+ last_modified = Time.at((last_modified.to_f / max_age).floor * max_age).utc if max_age > 1
15
+ is_public = (max_age > 1) && !HealthCheckRb.basic_auth_username
16
+ return unless stale? last_modified: last_modified, public: is_public
17
+
18
+ checks = params[:checks] ? params[:checks].split('_') : ['standard']
19
+ checks -= HealthCheckRb.middleware_checks if HealthCheckRb.installed_as_middleware
20
+ begin
21
+ errors = HealthCheckRb::Utils.process_checks checks
22
+ rescue StandardError => e
23
+ errors = e.message.blank? ? e.class.to_s : e.message.to_s
24
+ end
25
+ response.headers['Cache-Control'] = "must-revalidate, max-age=#{max_age}"
26
+ if errors.blank?
27
+ send_response true, nil, :ok, :ok
28
+ HealthCheckRb.success_callbacks&.each do |callback|
29
+ callback.call checks
30
+ end
31
+ else
32
+ msg = HealthCheckRb.include_error_in_response_body ? "#{HealthCheckRb.failure}: #{errors}" : nil
33
+ send_response false, msg, HealthCheckRb.http_status_for_error_text, HealthCheckRb.http_status_for_error_object
34
+
35
+ # Log a single line as some uptime checkers only record that it failed, not the text returned
36
+ msg = "#{HealthCheckRb.failure}: #{errors}"
37
+ logger.send HealthCheckRb.log_level, msg if logger && HealthCheckRb.log_level
38
+ HealthCheckRb.failure_callbacks&.each do |callback|
39
+ callback.call checks, msg
40
+ end
41
+ end
42
+ end
43
+
44
+ protected
45
+
46
+ def send_response(healthy, msg, text_status, obj_status)
47
+ msg ||= healthy ? HealthCheckRb.success : HealthCheckRb.failure
48
+ obj = { healthy: healthy, message: msg }
49
+ respond_to do |format|
50
+ format.html { render plain: msg, status: text_status, content_type: 'text/plain' }
51
+ format.json { render json: obj, status: obj_status }
52
+ format.xml { render xml: obj, status: obj_status }
53
+ format.any { render plain: msg, status: text_status, content_type: 'text/plain' }
54
+ end
55
+ end
56
+
57
+ def authenticate
58
+ return unless HealthCheckRb.basic_auth_username && HealthCheckRb.basic_auth_password
59
+
60
+ authenticate_or_request_with_http_basic 'Health Check' do |username, password|
61
+ username == HealthCheckRb.basic_auth_username && password == HealthCheckRb.basic_auth_password
62
+ end
63
+ end
64
+
65
+ def check_origin_ip
66
+ request_ipaddr = IPAddr.new(HealthCheckRb.accept_proxied_requests ? request.remote_ip : request.ip)
67
+ unless HealthCheckRb.origin_ip_whitelist.blank? ||
68
+ HealthCheckRb.origin_ip_whitelist.any? { |addr| IPAddr.new(addr).include? request_ipaddr }
69
+ render plain: 'Health check is not allowed for the requesting IP',
70
+ status: HealthCheckRb.http_status_for_ip_whitelist_error,
71
+ content_type: 'text/plain'
72
+ end
73
+ end
74
+
75
+ # turn cookies for CSRF off
76
+ def protect_against_forgery?
77
+ false
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ module Routing
5
+ class Mapper
6
+ def health_check_rb_routes(prefix = nil)
7
+ HealthCheckRb::Engine.routes_explicitly_defined = true
8
+ add_health_check_rb_routes prefix
9
+ end
10
+
11
+ def add_health_check_rb_routes(prefix = nil)
12
+ HealthCheckRb.uri = prefix if prefix
13
+ match "#{HealthCheckRb.uri}(/:checks)(.:format)", controller: 'health_check_rb/health_check', action: :index, via: %i[get post],
14
+ defaults: { format: 'txt' }
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ipaddr'
4
+
5
+ module HealthCheckRb
6
+ class MiddlewareHealthcheck
7
+ def initialize(app)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ (response_type, middleware_checks, full_stack_checks) = parse_env env
13
+ if response_type
14
+ if (error_response = ip_blocked(env) || not_authenticated(env))
15
+ return error_response
16
+ end
17
+
18
+ HealthCheckRb.installed_as_middleware = true
19
+ errors = ''
20
+ begin
21
+ # Process the checks to be run from middleware
22
+ errors = HealthCheckRb::Utils.process_checks middleware_checks,
23
+ called_from_middleware: true
24
+ # Process remaining checks through the full stack if there are any
25
+ return @app.call env unless full_stack_checks.empty?
26
+ rescue StandardError => e
27
+ errors = e.message.blank? ? e.class.to_s : e.message.to_s
28
+ end
29
+ healthy = errors.blank?
30
+ msg = healthy ? HealthCheckRb.success : "health_check failed: #{errors}"
31
+ if response_type == 'xml'
32
+ content_type = 'text/xml'
33
+ msg = { healthy: healthy, message: msg }.to_xml
34
+ error_code = HealthCheckRb.http_status_for_error_object
35
+ elsif response_type == 'json'
36
+ content_type = 'application/json'
37
+ msg = { healthy: healthy, message: msg }.to_json
38
+ error_code = HealthCheckRb.http_status_for_error_object
39
+ else
40
+ content_type = 'text/plain'
41
+ error_code = HealthCheckRb.http_status_for_error_text
42
+ end
43
+ [(healthy ? 200 : error_code), { 'Content-Type' => content_type }, [msg]]
44
+ else
45
+ @app.call env
46
+ end
47
+ end
48
+
49
+ protected
50
+
51
+ def parse_env(env)
52
+ uri = env['PATH_INFO']
53
+ return unless uri =~ %r{^/#{Regexp.escape HealthCheckRb.uri}(/([-_0-9a-zA-Z]*))?(\.(\w*))?$}
54
+
55
+ checks = ::Regexp.last_match(2).to_s == '' ? ['standard'] : ::Regexp.last_match(2).split('_')
56
+ response_type = ::Regexp.last_match(4).to_s
57
+ middleware_checks = checks & HealthCheckRb.middleware_checks
58
+ full_stack_checks = (checks - HealthCheckRb.middleware_checks) - ['and']
59
+ [response_type, middleware_checks, full_stack_checks]
60
+ end
61
+
62
+ def ip_blocked(env)
63
+ return false if HealthCheckRb.origin_ip_whitelist.blank?
64
+
65
+ req = Rack::Request.new env
66
+ request_ipaddr = IPAddr.new req.ip
67
+ return if HealthCheckRb.origin_ip_whitelist.any? { |addr| IPAddr.new(addr).include? request_ipaddr }
68
+
69
+ [HealthCheckRb.http_status_for_ip_whitelist_error,
70
+ { 'Content-Type' => 'text/plain' },
71
+ ['Health check is not allowed for the requesting IP']]
72
+ end
73
+
74
+ def not_authenticated(env)
75
+ return false unless HealthCheckRb.basic_auth_username && HealthCheckRb.basic_auth_password
76
+
77
+ auth = MiddlewareHealthcheck::Request.new env
78
+ if auth.provided? && auth.basic? && Rack::Utils.secure_compare(HealthCheckRb.basic_auth_username,
79
+ auth.username) && Rack::Utils.secure_compare(
80
+ HealthCheckRb.basic_auth_password, auth.password
81
+ )
82
+ env['REMOTE_USER'] = auth.username
83
+ return false
84
+ end
85
+ [401,
86
+ { 'Content-Type' => 'text/plain', 'WWW-Authenticate' => 'Basic realm="Health Check"' },
87
+ []]
88
+ end
89
+
90
+ class Request < Rack::Auth::AbstractRequest
91
+ def basic?
92
+ scheme == 'basic'
93
+ end
94
+
95
+ def credentials
96
+ @credentials ||= params.unpack1('m*').split(':', 2)
97
+ end
98
+
99
+ def username
100
+ credentials.first
101
+ end
102
+
103
+ def password
104
+ credentials.last
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,194 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HealthCheckRb
4
+ class Utils
5
+ # TODO: convert class variables to better solution
6
+ # rubocop: disable Style/ClassVars
7
+ @@default_smtp_settings =
8
+ {
9
+ address: 'localhost',
10
+ port: 25,
11
+ domain: 'localhost.localdomain',
12
+ user_name: nil,
13
+ password: nil,
14
+ authentication: nil,
15
+ enable_starttls_auto: true
16
+ }
17
+ # rubocop: enable Style/ClassVars
18
+
19
+ cattr_writer :db_migrate_path
20
+ cattr_accessor :default_smtp_settings
21
+
22
+ class << self
23
+ # process an array containing a list of checks
24
+ def process_checks(checks, called_from_middleware: false)
25
+ errors = +''
26
+ checks.each do |check|
27
+ case check
28
+ when 'and', 'site'
29
+ # do nothing
30
+ when 'database'
31
+ HealthCheckRb::Utils.database_version
32
+ when 'email'
33
+ errors << HealthCheckRb::Utils.check_email
34
+ when 'emailconf'
35
+ errors << HealthCheckRb::Utils.check_email if HealthCheckRb::Utils.mailer_configured?
36
+ when 'migrations', 'migration'
37
+ if defined?(ActiveRecord::Migration) && ActiveRecord::Migration.respond_to?(:check_all_pending!)
38
+ # Rails 7.2+
39
+ begin
40
+ ActiveRecord::Migration.check_all_pending!
41
+ rescue ActiveRecord::PendingMigrationError => e
42
+ errors << e.message
43
+ end
44
+ else
45
+ database_version = HealthCheckRb::Utils.database_version
46
+ migration_version = HealthCheckRb::Utils.migration_version
47
+ if database_version.to_i != migration_version.to_i
48
+ errors << "Current database version (#{database_version}) does not match latest migration (#{migration_version}). "
49
+ end
50
+ end
51
+ when 'cache'
52
+ errors << HealthCheckRb::Utils.check_cache
53
+ when 'resque-redis-if-present'
54
+ errors << HealthCheckRb::Check::Resque.check if defined?(::Resque)
55
+ when 'sidekiq-redis-if-present'
56
+ errors << HealthCheckRb::Check::Sidekiq.check if defined?(::Sidekiq)
57
+ when 'redis-if-present'
58
+ errors << HealthCheckRb::CheckRedis.check if defined?(::Redis)
59
+ when 's3-if-present'
60
+ errors << HealthCheckRb::Check::S3.check if defined?(::Aws)
61
+ when 'elasticsearch-if-present'
62
+ errors << HealthCheckRb::Check::Elasticsearch.check if defined?(::Elasticsearch)
63
+ when 'resque-redis'
64
+ errors << HealthCheckRb::Check::Resque.check
65
+ when 'sidekiq-redis'
66
+ errors << HealthCheckRb::Check::Sidekiq.check
67
+ when 'redis'
68
+ errors << HealthCheckRb::Check::Redis.check
69
+ when 's3'
70
+ errors << HealthCheckRb::Check::S3.check
71
+ when 'elasticsearch'
72
+ errors << HealthCheckRb::Check::Elasticsearch.check
73
+ when 'rabbitmq'
74
+ errors << HealthCheckRb::Check::RabbitMQ.check
75
+ when 'standard'
76
+ errors << HealthCheckRb::Utils.process_checks(HealthCheckRb.standard_checks, called_from_middleware:)
77
+ when 'middleware'
78
+ errors << 'Health check not called from middleware - probably not installed as middleware.' unless called_from_middleware
79
+ when 'custom'
80
+ HealthCheckRb.custom_checks.each_value do |list|
81
+ list.each do |custom_check|
82
+ errors << custom_check.call(self)
83
+ end
84
+ end
85
+ when 'all', 'full'
86
+ errors << HealthCheckRb::Utils.process_checks(HealthCheckRb.full_checks, called_from_middleware:)
87
+ else
88
+ return 'invalid argument to health_test.' unless HealthCheckRb.custom_checks.include? check
89
+
90
+ HealthCheckRb.custom_checks[check].each do |custom_check|
91
+ errors << custom_check.call(self)
92
+ end
93
+
94
+ end
95
+ errors << '. ' unless errors == '' || errors.end_with?('. ')
96
+ end
97
+ errors.strip
98
+ rescue StandardError => e
99
+ e.message
100
+ end
101
+
102
+ def db_migrate_path
103
+ # Lazy initialisation so Rails.root will be defined
104
+ @db_migrate_path ||= Rails.root.join 'db', 'migrate'.to_s
105
+ end
106
+
107
+ def mailer_configured?
108
+ defined?(ActionMailer::Base) &&
109
+ (ActionMailer::Base.delivery_method != :smtp ||
110
+ HealthCheckRb::Utils.default_smtp_settings != ActionMailer::Base.smtp_settings)
111
+ end
112
+
113
+ def database_version
114
+ ActiveRecord::Migrator.current_version if defined?(ActiveRecord)
115
+ end
116
+
117
+ def migration_version(dir = db_migrate_path)
118
+ latest_migration = nil
119
+ Dir[File.join(dir, '[0-9]*_*.rb')].each do |f|
120
+ l = begin
121
+ f.scan(/0*([0-9]+)_[_.a-zA-Z0-9]*.rb/).first.first
122
+ rescue StandardError
123
+ -1
124
+ end
125
+ latest_migration = l if !latest_migration || l.to_i > latest_migration.to_i
126
+ end
127
+ latest_migration
128
+ end
129
+
130
+ def check_email
131
+ case ActionMailer::Base.delivery_method
132
+ when :smtp
133
+ HealthCheckRb::Utils.check_smtp(ActionMailer::Base.smtp_settings, HealthCheckRb.smtp_timeout)
134
+ when :sendmail
135
+ HealthCheckRb::Utils.check_sendmail(ActionMailer::Base.sendmail_settings)
136
+ else
137
+ ''
138
+ end
139
+ end
140
+
141
+ def check_sendmail(settings)
142
+ File.executable?(settings[:location]) ? '' : 'no sendmail executable found. '
143
+ end
144
+
145
+ def check_smtp(settings, timeout)
146
+ begin
147
+ if @skip_external_checks
148
+ status = '250'
149
+ else
150
+ smtp = Net::SMTP.new settings[:address], settings[:port]
151
+ openssl_verify_mode = settings[:openssl_verify_mode]
152
+
153
+ openssl_verify_mode = OpenSSL::SSL.const_get("VERIFY_#{openssl_verify_mode.upcase}") if openssl_verify_mode.is_a? String
154
+
155
+ ssl_context = Net::SMTP.default_ssl_context
156
+ ssl_context.verify_mode = openssl_verify_mode if openssl_verify_mode
157
+ smtp.enable_starttls ssl_context if settings[:enable_starttls_auto]
158
+ smtp.open_timeout = timeout
159
+ smtp.read_timeout = timeout
160
+ smtp.start settings[:domain], settings[:user_name], settings[:password], settings[:authentication] do
161
+ status = smtp.helo(settings[:domain]).status
162
+ end
163
+ end
164
+ rescue StandardError => e
165
+ status = e.to_s
166
+ end
167
+ /^250/.match?(status) ? '' : "SMTP: #{status || 'unexpected error'}. "
168
+ end
169
+
170
+ def check_cache
171
+ t = Time.now.to_i
172
+ value = "ok #{t}"
173
+ ret = ::Rails.cache.read '__health_check_cache_test__'
174
+ if ret.to_s =~ /^ok (\d+)$/
175
+ diff = (::Regexp.last_match(1).to_i - t).abs
176
+ return('Cache expiry is broken. ') if diff > 30
177
+ elsif ret
178
+ return 'Cache is returning garbage. '
179
+ end
180
+ if ::Rails.cache.write '__health_check_cache_test__', value, expires_in: 2.seconds
181
+ ret = ::Rails.cache.read '__health_check_cache_test__'
182
+ if ret =~ /^ok (\d+)$/
183
+ diff = (::Regexp.last_match(1).to_i - t).abs
184
+ (diff < 2 ? '' : 'Out of date cache or time is skewed. ')
185
+ else
186
+ 'Unable to read from cache. '
187
+ end
188
+ else
189
+ 'Unable to write to cache. '
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HealthCheckRb
4
+ VERSION = '4.0.0'
5
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HealthCheckRb
4
+ class Engine < ::Rails::Engine
5
+ cattr_accessor :routes_explicitly_defined
6
+ end
7
+
8
+ # Log level
9
+ mattr_accessor :log_level
10
+ self.log_level = 'info'
11
+
12
+ # Text output upon success
13
+ mattr_accessor :success
14
+ self.success = 'success'
15
+
16
+ # Text output upon failure
17
+ mattr_accessor :failure
18
+ self.failure = 'health_check failed'
19
+
20
+ # Timeout in seconds used when checking smtp server
21
+ mattr_accessor :smtp_timeout
22
+ self.smtp_timeout = 30.0
23
+
24
+ # http status code used when plain text error message is output
25
+ mattr_accessor :http_status_for_error_text
26
+ self.http_status_for_error_text = 500
27
+
28
+ # http status code used when an error object is output (json or xml)
29
+ mattr_accessor :http_status_for_error_object
30
+ self.http_status_for_error_object = 500
31
+
32
+ # http status code used when the ip is not allowed for the request
33
+ mattr_accessor :http_status_for_ip_whitelist_error
34
+ self.http_status_for_ip_whitelist_error = 403
35
+
36
+ # check remote_ip rather than ip for ip whitelist
37
+ mattr_accessor :accept_proxied_requests
38
+ self.accept_proxied_requests = false
39
+
40
+ # ips allowed to perform requests
41
+ mattr_accessor :origin_ip_whitelist
42
+ self.origin_ip_whitelist = []
43
+
44
+ # max-age of response in seconds
45
+ # cache-control is public when max_age > 1 and basic authentication is used
46
+ mattr_accessor :max_age
47
+ self.max_age = 1
48
+
49
+ # s3 buckets
50
+ mattr_accessor :buckets
51
+ self.buckets = {}
52
+
53
+ # rabbitmq
54
+ mattr_accessor :rabbitmq_config
55
+ self.rabbitmq_config = {}
56
+
57
+ # health check uri path
58
+ mattr_accessor :uri
59
+ self.uri = 'health_check'
60
+
61
+ # Basic Authentication
62
+ mattr_accessor :basic_auth_username, :basic_auth_password
63
+ self.basic_auth_username = nil
64
+ self.basic_auth_password = nil
65
+
66
+ # Array of custom check blocks
67
+ mattr_accessor :custom_checks
68
+ mattr_accessor :full_checks
69
+ mattr_accessor :standard_checks
70
+ self.custom_checks = {}
71
+ self.full_checks = %w[database migrations custom email cache redis-if-present sidekiq-redis-if-present
72
+ resque-redis-if-present s3-if-present elasticsearch-if-present]
73
+ self.standard_checks = %w[database migrations custom emailconf]
74
+
75
+ # Middleware based checks
76
+ mattr_accessor :middleware_checks
77
+ self.middleware_checks = ['middleware']
78
+
79
+ mattr_accessor :installed_as_middleware
80
+
81
+ # Allow non-standard redis url and password
82
+ mattr_accessor :redis_url
83
+ self.redis_url = ENV.fetch 'REDIS_URL', nil
84
+
85
+ mattr_accessor :redis_password
86
+ self.redis_password = ENV.fetch 'REDIS_PASSWORD', nil
87
+
88
+ # Include the error in the response body.
89
+ # You should only do this where your /health_check endpoint is NOT open to the public internet
90
+ mattr_accessor :include_error_in_response_body
91
+ self.include_error_in_response_body = false
92
+
93
+ # used for on_failure and on_success
94
+ mattr_accessor :success_callbacks
95
+ mattr_accessor :failure_callbacks
96
+
97
+ def self.add_custom_check(name = 'custom', &block)
98
+ custom_checks[name] ||= []
99
+ custom_checks[name] << block
100
+ end
101
+
102
+ def self.on_success(&block)
103
+ success_callbacks ||= []
104
+ success_callbacks << block
105
+ end
106
+
107
+ def self.on_failure(&block)
108
+ failure_callbacks ||= []
109
+ failure_callbacks << block
110
+ end
111
+
112
+ def self.setup
113
+ yield self
114
+ end
115
+ end
116
+
117
+ require 'health_check_rb/version'
118
+ require 'health_check_rb/base_health_check'
119
+ require 'health_check_rb/utils'
120
+ require 'health_check_rb/health_check_controller'
121
+ require 'health_check_rb/health_check_routes'
122
+ require 'health_check_rb/middleware_health_check'
123
+
124
+ require 'health_check_rb/check/resque'
125
+ require 'health_check_rb/check/s3'
126
+ require 'health_check_rb/check/redis'
127
+ require 'health_check_rb/check/elasticsearch'
128
+ require 'health_check_rb/check/sidekiq'
129
+ require 'health_check_rb/check/rabbitmq'
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
4
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
5
+
6
+ require File.expand_path('./fake_app', __dir__)
7
+
8
+ Rails.application.load_tasks
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ExampleController < ActionController::Base
4
+ def index
5
+ render plain: 'OK'
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ default: &default
2
+ adapter: sqlite3
3
+
4
+ development:
5
+ <<: *default
6
+ database: db/development.sqlite3
7
+
8
+ test:
9
+ <<: *default
10
+ database: db/test.sqlite3
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ CUSTOM_CHECK_FILE_PATH = 'spec/dummy/tmp/custom_file'
4
+
5
+ HealthCheckRb.setup do |config|
6
+ config.success = 'custom_success_message'
7
+ config.http_status_for_error_text = 550
8
+ config.http_status_for_error_object = 555
9
+ config.uri = 'custom_route_prefix'
10
+
11
+ config.add_custom_check do
12
+ File.exist?(CUSTOM_CHECK_FILE_PATH) ? '' : 'custom_file is missing!'
13
+ end
14
+
15
+ config.add_custom_check 'pass' do
16
+ ''
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ FakeApp.config.middleware.insert_after Rails::Rack::Logger, HealthCheckRb::MiddlewareHealthcheck if ENV['MIDDLEWARE'] == 'true'
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.routes.draw do
4
+ get 'example' => 'example#index'
5
+ end
File without changes
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ Bundler.setup
4
+ require 'rails'
5
+ require 'rails/all'
6
+ require 'health_check_rb'
7
+ Bundler.require
8
+
9
+ FakeApp = Class.new Rails::Application
10
+ ENV['RAILS_ENV'] ||= 'test'
11
+ FakeApp.config.eager_load = false
12
+ FakeApp.config.session_store :cookie_store, key: '_myapp_session'
13
+ FakeApp.config.root = File.dirname __FILE__
14
+ FakeApp.config.action_mailer.delivery_method = :smtp
15
+ FakeApp.config.action_mailer.smtp_settings = { address: 'localhost', port: 3555, openssl_verify_mode: OpenSSL::SSL::VERIFY_NONE,
16
+ enable_starttls_auto: true }
17
+ FakeApp.config.secret_key_base = SecureRandom.hex 64
18
+ FakeApp.initialize!
File without changes
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateCountries < ActiveRecord::Migration::Current
4
+ def change
5
+ create_table :countries do |t|
6
+ t.column :name, :string
7
+ end
8
+ end
9
+ end