rack-ecg 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/main.yml +22 -0
- data/.rubocop.yml +21 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +69 -0
- data/Gemfile +1 -0
- data/README.md +118 -31
- data/Rakefile +10 -1
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/examples/basic.ru +3 -3
- data/examples/checks.ru +3 -3
- data/examples/hook.ru +17 -0
- data/examples/mounted_path.ru +3 -3
- data/examples/parameters.ru +12 -0
- data/examples/stand_alone.ru +4 -0
- data/lib/rack-ecg.rb +1 -0
- data/lib/rack/ecg.rb +37 -55
- data/lib/rack/ecg/check.rb +45 -0
- data/lib/rack/ecg/check/active_record_connection.rb +32 -0
- data/lib/rack/ecg/check/error.rb +16 -0
- data/lib/rack/ecg/check/git_revision.rb +26 -0
- data/lib/rack/ecg/check/http.rb +16 -0
- data/lib/rack/ecg/check/migration_version.rb +32 -0
- data/lib/rack/ecg/check/redis_connection.rb +34 -0
- data/lib/rack/ecg/check/sequel_connection.rb +54 -0
- data/lib/rack/ecg/check_factory.rb +28 -0
- data/lib/rack/ecg/check_registry.rb +43 -0
- data/lib/rack/ecg/version.rb +3 -1
- data/rack-ecg.gemspec +31 -14
- metadata +91 -31
- data/.travis.yml +0 -15
- data/spec/rack_middleware_spec.rb +0 -146
- data/spec/spec_helper.rb +0 -23
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "singleton"
|
3
|
+
|
4
|
+
module Rack
|
5
|
+
class ECG
|
6
|
+
class CheckRegistry
|
7
|
+
# Raised when a check didn't exist during lookup
|
8
|
+
CheckNotRegistered = Class.new(StandardError)
|
9
|
+
include Singleton
|
10
|
+
|
11
|
+
# Constructs the singleton instance of the registry
|
12
|
+
def initialize
|
13
|
+
@registry = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
# Register a check class by name
|
17
|
+
#
|
18
|
+
# @param [Symbol] name Desired check name
|
19
|
+
# @param [Class] check_class Class implementing check functionality
|
20
|
+
def register(name, check_class)
|
21
|
+
@registry[name] = check_class
|
22
|
+
end
|
23
|
+
|
24
|
+
# Fetches the registered check class by name
|
25
|
+
#
|
26
|
+
# @param [Symbol] name Registered check name
|
27
|
+
# @raise [CheckNotRegistered] if the named check has not been registered
|
28
|
+
def lookup(name)
|
29
|
+
@registry.fetch(name) { raise CheckNotRegistered, "Check '#{name}' is not registered" }
|
30
|
+
end
|
31
|
+
|
32
|
+
# (see #lookup)
|
33
|
+
def self.lookup(name)
|
34
|
+
instance.lookup(name)
|
35
|
+
end
|
36
|
+
|
37
|
+
# (see #register)
|
38
|
+
def self.register(name, check_class)
|
39
|
+
instance.register(name, check_class)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/rack/ecg/version.rb
CHANGED
data/rack-ecg.gemspec
CHANGED
@@ -1,28 +1,45 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative "lib/rack/ecg/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "rack-ecg"
|
8
8
|
spec.version = Rack::ECG::VERSION
|
9
9
|
spec.authors = ["Envato", "Julian Doherty"]
|
10
10
|
spec.email = ["julian@envato.com"]
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
11
|
+
spec.summary = 'Rack middleware serving a health check page'
|
12
|
+
spec.description = <<-EOF
|
13
|
+
rack-ecg allows you to serve a page that shows you facts about your deployed
|
14
|
+
app to allow you to check that everything is running as it should: git
|
15
|
+
revision, database migrations, and more
|
16
|
+
EOF
|
13
17
|
spec.homepage = "https://github.com/envato/rack-ecg"
|
14
18
|
spec.license = "MIT"
|
15
19
|
|
16
|
-
spec.
|
17
|
-
spec.
|
18
|
-
spec.
|
20
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
21
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
22
|
+
spec.metadata["changelog_uri"] = "https://github.com/envato/rack-ecg/blob/main/CHANGELOG.md"
|
23
|
+
|
24
|
+
# Specify which files should be added to the gem when it is released.
|
25
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
26
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
27
|
+
%x(git ls-files -z).split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
28
|
+
end
|
29
|
+
spec.bindir = "exe"
|
30
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
19
31
|
spec.require_paths = ["lib"]
|
20
32
|
|
21
|
-
spec.
|
33
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
|
34
|
+
|
35
|
+
spec.add_runtime_dependency("rack")
|
22
36
|
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
27
|
-
spec.add_development_dependency
|
37
|
+
spec.add_development_dependency("rake", "~> 13.0")
|
38
|
+
spec.add_development_dependency("bundler", "~> 2.2.1")
|
39
|
+
spec.add_development_dependency("rspec", "~> 3.10.0")
|
40
|
+
spec.add_development_dependency("rack-test", "~> 1.1.0")
|
41
|
+
spec.add_development_dependency("pry", "~> 0.13.0")
|
42
|
+
spec.add_development_dependency("rubocop-shopify", "~> 1.0.0")
|
43
|
+
spec.add_development_dependency("yard", "~> 0.9.24")
|
44
|
+
spec.add_development_dependency("redcarpet", "~> 3.5.0")
|
28
45
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-ecg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Envato
|
8
8
|
- Julian Doherty
|
9
|
-
autorequire:
|
10
|
-
bindir:
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2020-12-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -26,106 +26,169 @@ dependencies:
|
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
|
-
name:
|
29
|
+
name: rake
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '
|
34
|
+
version: '13.0'
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: '
|
41
|
+
version: '13.0'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
|
-
name:
|
43
|
+
name: bundler
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version:
|
48
|
+
version: 2.2.1
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version:
|
55
|
+
version: 2.2.1
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: rspec
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
60
|
- - "~>"
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: 3.
|
62
|
+
version: 3.10.0
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 3.
|
69
|
+
version: 3.10.0
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: rack-test
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
74
|
- - "~>"
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version:
|
76
|
+
version: 1.1.0
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
81
|
- - "~>"
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version:
|
83
|
+
version: 1.1.0
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
85
|
name: pry
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
88
|
- - "~>"
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version: 0.
|
90
|
+
version: 0.13.0
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 0.13.0
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: rubocop-shopify
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 1.0.0
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: 1.0.0
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: yard
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - "~>"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: 0.9.24
|
91
119
|
type: :development
|
92
120
|
prerelease: false
|
93
121
|
version_requirements: !ruby/object:Gem::Requirement
|
94
122
|
requirements:
|
95
123
|
- - "~>"
|
96
124
|
- !ruby/object:Gem::Version
|
97
|
-
version: 0.
|
98
|
-
|
99
|
-
|
100
|
-
|
125
|
+
version: 0.9.24
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: redcarpet
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - "~>"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 3.5.0
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: 3.5.0
|
140
|
+
description: |2
|
141
|
+
rack-ecg allows you to serve a page that shows you facts about your deployed
|
142
|
+
app to allow you to check that everything is running as it should: git
|
143
|
+
revision, database migrations, and more
|
101
144
|
email:
|
102
145
|
- julian@envato.com
|
103
146
|
executables: []
|
104
147
|
extensions: []
|
105
148
|
extra_rdoc_files: []
|
106
149
|
files:
|
150
|
+
- ".github/workflows/main.yml"
|
107
151
|
- ".gitignore"
|
108
152
|
- ".rspec"
|
109
|
-
- ".
|
153
|
+
- ".rubocop.yml"
|
154
|
+
- ".ruby-version"
|
155
|
+
- ".yardopts"
|
156
|
+
- CHANGELOG.md
|
110
157
|
- CODE_OF_CONDUCT.md
|
111
158
|
- Gemfile
|
112
159
|
- LICENSE.txt
|
113
160
|
- README.md
|
114
161
|
- Rakefile
|
162
|
+
- bin/console
|
163
|
+
- bin/setup
|
115
164
|
- examples/basic.ru
|
116
165
|
- examples/checks.ru
|
166
|
+
- examples/hook.ru
|
117
167
|
- examples/mounted_path.ru
|
168
|
+
- examples/parameters.ru
|
169
|
+
- examples/stand_alone.ru
|
118
170
|
- lib/rack-ecg.rb
|
119
171
|
- lib/rack/ecg.rb
|
172
|
+
- lib/rack/ecg/check.rb
|
173
|
+
- lib/rack/ecg/check/active_record_connection.rb
|
174
|
+
- lib/rack/ecg/check/error.rb
|
175
|
+
- lib/rack/ecg/check/git_revision.rb
|
176
|
+
- lib/rack/ecg/check/http.rb
|
177
|
+
- lib/rack/ecg/check/migration_version.rb
|
178
|
+
- lib/rack/ecg/check/redis_connection.rb
|
179
|
+
- lib/rack/ecg/check/sequel_connection.rb
|
180
|
+
- lib/rack/ecg/check_factory.rb
|
181
|
+
- lib/rack/ecg/check_registry.rb
|
120
182
|
- lib/rack/ecg/version.rb
|
121
183
|
- rack-ecg.gemspec
|
122
|
-
- spec/rack_middleware_spec.rb
|
123
|
-
- spec/spec_helper.rb
|
124
184
|
homepage: https://github.com/envato/rack-ecg
|
125
185
|
licenses:
|
126
186
|
- MIT
|
127
|
-
metadata:
|
128
|
-
|
187
|
+
metadata:
|
188
|
+
homepage_uri: https://github.com/envato/rack-ecg
|
189
|
+
source_code_uri: https://github.com/envato/rack-ecg
|
190
|
+
changelog_uri: https://github.com/envato/rack-ecg/blob/main/CHANGELOG.md
|
191
|
+
post_install_message:
|
129
192
|
rdoc_options: []
|
130
193
|
require_paths:
|
131
194
|
- lib
|
@@ -133,18 +196,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
133
196
|
requirements:
|
134
197
|
- - ">="
|
135
198
|
- !ruby/object:Gem::Version
|
136
|
-
version:
|
199
|
+
version: 2.5.0
|
137
200
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
201
|
requirements:
|
139
202
|
- - ">="
|
140
203
|
- !ruby/object:Gem::Version
|
141
204
|
version: '0'
|
142
205
|
requirements: []
|
143
|
-
|
144
|
-
|
145
|
-
signing_key:
|
206
|
+
rubygems_version: 3.2.2
|
207
|
+
signing_key:
|
146
208
|
specification_version: 4
|
147
209
|
summary: Rack middleware serving a health check page
|
148
|
-
test_files:
|
149
|
-
- spec/rack_middleware_spec.rb
|
150
|
-
- spec/spec_helper.rb
|
210
|
+
test_files: []
|
data/.travis.yml
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
rvm:
|
3
|
-
- 1.9.3
|
4
|
-
- 2.0.0
|
5
|
-
- 2.1.5
|
6
|
-
- 2.2.1
|
7
|
-
- ruby-head
|
8
|
-
- jruby
|
9
|
-
notifications:
|
10
|
-
webhooks:
|
11
|
-
urls:
|
12
|
-
- https://webhooks.gitter.im/e/b627d6a74f88be59d0b9
|
13
|
-
on_success: change # options: [always|never|change] default: always
|
14
|
-
on_failure: always # options: [always|never|change] default: always
|
15
|
-
on_start: false # default: false - rbx-2
|
@@ -1,146 +0,0 @@
|
|
1
|
-
require "open3"
|
2
|
-
require "stringio"
|
3
|
-
|
4
|
-
RSpec.describe "when used as middleware" do
|
5
|
-
let(:app) {
|
6
|
-
opts = options
|
7
|
-
Rack::Builder.new do
|
8
|
-
use Rack::ECG, opts
|
9
|
-
run lambda {|env|
|
10
|
-
if env["PATH_INFO"] == "/hello/world"
|
11
|
-
[200, {}, ["Hello, World"]]
|
12
|
-
else
|
13
|
-
[404, {}, ["Goodbye, World"]]
|
14
|
-
end
|
15
|
-
}
|
16
|
-
end
|
17
|
-
}
|
18
|
-
let(:options) {
|
19
|
-
{} # empty default
|
20
|
-
}
|
21
|
-
|
22
|
-
context "main app" do
|
23
|
-
it "responds OK for normal requests" do
|
24
|
-
get "/hello/world"
|
25
|
-
expect(last_response).to be_ok
|
26
|
-
end
|
27
|
-
|
28
|
-
it "doesn't include an X-Rack-ECG-Version custom header" do
|
29
|
-
get "/hello/world"
|
30
|
-
expect(last_response.header["X-Rack-ECG-Version"]).to be_nil
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context "ecg app" do
|
35
|
-
it "responds " do
|
36
|
-
get "/_ecg"
|
37
|
-
expect(last_response).to be_ok
|
38
|
-
end
|
39
|
-
|
40
|
-
it "includes an X-Rack-ECG-Version custom header" do
|
41
|
-
get "/_ecg"
|
42
|
-
expect(last_response.header["X-Rack-ECG-Version"]).to eq(Rack::ECG::VERSION)
|
43
|
-
end
|
44
|
-
|
45
|
-
context "when `at` config option is set" do
|
46
|
-
let(:options) {
|
47
|
-
{at: "/health_check"}
|
48
|
-
}
|
49
|
-
|
50
|
-
it "responds from that path" do
|
51
|
-
get "/health_check"
|
52
|
-
expect(last_response.header["X-Rack-ECG-Version"]).to eq(Rack::ECG::VERSION)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
context "when all checks pass" do
|
57
|
-
it "has a success error code" do
|
58
|
-
get "_ecg"
|
59
|
-
expect(last_response.status).to eq(200)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context "when a checks errors" do
|
64
|
-
let(:options) {
|
65
|
-
{ checks: [:error] }
|
66
|
-
}
|
67
|
-
it "has a success error code" do
|
68
|
-
get "_ecg"
|
69
|
-
expect(last_response.status).to eq(500)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
context "git revision" do
|
74
|
-
let(:options) {
|
75
|
-
{ checks: [:git_revision] }
|
76
|
-
}
|
77
|
-
context "when available" do
|
78
|
-
let(:sha) { "cafe1234" }
|
79
|
-
it "is reported" do
|
80
|
-
expect(Open3).to receive(:popen3).
|
81
|
-
with("git rev-parse HEAD").
|
82
|
-
and_return([
|
83
|
-
nil, # stdin
|
84
|
-
StringIO.new(sha + "\n"), # stdout
|
85
|
-
StringIO.new(), # stderr
|
86
|
-
double(value: double(Process::Status, success?: true)) # wait thread & process status
|
87
|
-
])
|
88
|
-
get "/_ecg"
|
89
|
-
expect(json_body["git_revision"]["status"]).to eq("ok")
|
90
|
-
expect(json_body["git_revision"]["value"]).to eq(sha)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
context "when not available" do
|
95
|
-
let(:error_message) { "git had a sad" }
|
96
|
-
it "is reported" do
|
97
|
-
expect(Open3).to receive(:popen3).
|
98
|
-
with("git rev-parse HEAD").
|
99
|
-
and_return([
|
100
|
-
nil, # stdin
|
101
|
-
StringIO.new(), # stdout
|
102
|
-
StringIO.new(error_message + "\n"), # stderr
|
103
|
-
double(value: double(Process::Status, success?: false)) # wait thread & process status
|
104
|
-
])
|
105
|
-
get "/_ecg"
|
106
|
-
expect(json_body["git_revision"]["status"]).to eq("error")
|
107
|
-
expect(json_body["git_revision"]["value"]).to eq("git had a sad")
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
context "migration version" do
|
113
|
-
let(:options) {
|
114
|
-
{ checks: [:migration_version] }
|
115
|
-
}
|
116
|
-
context "when availabile" do
|
117
|
-
it "is reported" do
|
118
|
-
class ActiveRecord
|
119
|
-
class Base
|
120
|
-
def self.connection
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
version = "123456"
|
125
|
-
connection = double("connection")
|
126
|
-
expect(ActiveRecord::Base).to receive(:connection).and_return(connection)
|
127
|
-
expect(connection).to receive(:execute).
|
128
|
-
with("select max(version) as version from schema_migrations").
|
129
|
-
and_return([{"version" => version}])
|
130
|
-
get "/_ecg"
|
131
|
-
expect(json_body["migration_version"]["status"]).to eq("ok")
|
132
|
-
expect(json_body["migration_version"]["value"]).to eq(version)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
context "when not available" do
|
137
|
-
it "is reported" do
|
138
|
-
Object.send(:remove_const, :ActiveRecord) if defined?(ActiveRecord)
|
139
|
-
get "/_ecg"
|
140
|
-
expect(json_body["migration_version"]["status"]).to eq("error")
|
141
|
-
expect(json_body["migration_version"]["value"]).to eq("ActiveRecord not found")
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|