shivam 0.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/test.yml +57 -0
  3. data/.gitignore +10 -0
  4. data/.rspec +1 -0
  5. data/.yardopts +5 -0
  6. data/CHANGELOG.md +899 -0
  7. data/Gemfile +35 -0
  8. data/Guardfile +14 -0
  9. data/LICENSE +23 -0
  10. data/README.md +679 -0
  11. data/Rakefile +21 -0
  12. data/bin/ci/before_build.sh +20 -0
  13. data/bin/ci/before_build_docker.sh +20 -0
  14. data/bin/ci/install_on_debian.sh +46 -0
  15. data/bin/hutch +8 -0
  16. data/examples/consumer.rb +13 -0
  17. data/examples/producer.rb +10 -0
  18. data/hutch.gemspec +27 -0
  19. data/lib/hutch/acknowledgements/base.rb +16 -0
  20. data/lib/hutch/acknowledgements/nack_on_all_failures.rb +19 -0
  21. data/lib/hutch/adapter.rb +11 -0
  22. data/lib/hutch/adapters/bunny.rb +37 -0
  23. data/lib/hutch/adapters/march_hare.rb +41 -0
  24. data/lib/hutch/broker.rb +384 -0
  25. data/lib/hutch/cli.rb +246 -0
  26. data/lib/hutch/config.rb +305 -0
  27. data/lib/hutch/consumer.rb +125 -0
  28. data/lib/hutch/error_handlers/airbrake.rb +54 -0
  29. data/lib/hutch/error_handlers/base.rb +15 -0
  30. data/lib/hutch/error_handlers/bugsnag.rb +30 -0
  31. data/lib/hutch/error_handlers/honeybadger.rb +43 -0
  32. data/lib/hutch/error_handlers/logger.rb +22 -0
  33. data/lib/hutch/error_handlers/rollbar.rb +28 -0
  34. data/lib/hutch/error_handlers/sentry.rb +26 -0
  35. data/lib/hutch/error_handlers/sentry_raven.rb +31 -0
  36. data/lib/hutch/error_handlers.rb +11 -0
  37. data/lib/hutch/exceptions.rb +14 -0
  38. data/lib/hutch/logging.rb +32 -0
  39. data/lib/hutch/message.rb +31 -0
  40. data/lib/hutch/publisher.rb +75 -0
  41. data/lib/hutch/serializers/identity.rb +19 -0
  42. data/lib/hutch/serializers/json.rb +22 -0
  43. data/lib/hutch/tracers/datadog.rb +18 -0
  44. data/lib/hutch/tracers/newrelic.rb +19 -0
  45. data/lib/hutch/tracers/null_tracer.rb +15 -0
  46. data/lib/hutch/tracers.rb +7 -0
  47. data/lib/hutch/version.rb +3 -0
  48. data/lib/hutch/waiter.rb +104 -0
  49. data/lib/hutch/worker.rb +145 -0
  50. data/lib/hutch.rb +69 -0
  51. data/lib/yard-settings/handler.rb +38 -0
  52. data/lib/yard-settings/yard-settings.rb +2 -0
  53. data/spec/hutch/broker_spec.rb +462 -0
  54. data/spec/hutch/cli_spec.rb +93 -0
  55. data/spec/hutch/config_spec.rb +259 -0
  56. data/spec/hutch/consumer_spec.rb +208 -0
  57. data/spec/hutch/error_handlers/airbrake_spec.rb +49 -0
  58. data/spec/hutch/error_handlers/bugsnag_spec.rb +55 -0
  59. data/spec/hutch/error_handlers/honeybadger_spec.rb +58 -0
  60. data/spec/hutch/error_handlers/logger_spec.rb +28 -0
  61. data/spec/hutch/error_handlers/rollbar_spec.rb +45 -0
  62. data/spec/hutch/error_handlers/sentry_raven_spec.rb +37 -0
  63. data/spec/hutch/error_handlers/sentry_spec.rb +47 -0
  64. data/spec/hutch/logger_spec.rb +34 -0
  65. data/spec/hutch/message_spec.rb +38 -0
  66. data/spec/hutch/serializers/json_spec.rb +17 -0
  67. data/spec/hutch/tracers/datadog_spec.rb +44 -0
  68. data/spec/hutch/waiter_spec.rb +51 -0
  69. data/spec/hutch/worker_spec.rb +184 -0
  70. data/spec/hutch_spec.rb +87 -0
  71. data/spec/spec_helper.rb +42 -0
  72. data/templates/default/class/html/settings.erb +0 -0
  73. data/templates/default/class/setup.rb +4 -0
  74. data/templates/default/fulldoc/html/css/hutch.css +13 -0
  75. data/templates/default/layout/html/setup.rb +7 -0
  76. data/templates/default/method_details/html/settings.erb +5 -0
  77. data/templates/default/method_details/setup.rb +4 -0
  78. data/templates/default/method_details/text/settings.erb +0 -0
  79. data/templates/default/module/html/settings.erb +40 -0
  80. data/templates/default/module/setup.rb +4 -0
  81. metadata +205 -0
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hutch::ErrorHandlers::SentryRaven do
4
+ let(:error_handler) { Hutch::ErrorHandlers::SentryRaven.new }
5
+
6
+ describe '#handle' do
7
+ let(:properties) { OpenStruct.new(message_id: "1") }
8
+ let(:payload) { "{}" }
9
+ let(:error) do
10
+ begin
11
+ raise "Stuff went wrong"
12
+ rescue RuntimeError => err
13
+ err
14
+ end
15
+ end
16
+
17
+ it "logs the error to Sentry" do
18
+ expect(Raven).to receive(:capture_exception).with(error, {extra: { payload: payload }})
19
+ error_handler.handle(properties, payload, double, error)
20
+ end
21
+ end
22
+
23
+ describe '#handle_setup_exception' do
24
+ let(:error) do
25
+ begin
26
+ raise "Stuff went wrong during setup"
27
+ rescue RuntimeError => err
28
+ err
29
+ end
30
+ end
31
+
32
+ it "logs the error to Sentry" do
33
+ expect(Raven).to receive(:capture_exception).with(error)
34
+ error_handler.handle_setup_exception(error)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hutch::ErrorHandlers::Sentry do
4
+ let(:error_handler) { Hutch::ErrorHandlers::Sentry.new }
5
+
6
+ before do
7
+ Sentry.init do
8
+ # initialize Sentry so that the integration acutally works
9
+ # otherwise, all its methods are going to return early
10
+ # so it will be impossible to check if it actually works
11
+ end
12
+ end
13
+
14
+ describe '#handle' do
15
+ let(:properties) { OpenStruct.new(message_id: "1") }
16
+ let(:payload) { "{}" }
17
+ let(:error) do
18
+ begin
19
+ raise "Stuff went wrong"
20
+ rescue RuntimeError => err
21
+ err
22
+ end
23
+ end
24
+
25
+ it "logs the error to Sentry" do
26
+ expect(::Sentry).to receive(:capture_exception).with(error).and_call_original
27
+
28
+ error_handler.handle(properties, payload, double, error)
29
+ end
30
+ end
31
+
32
+ describe '#handle_setup_exception' do
33
+ let(:error) do
34
+ begin
35
+ raise "Stuff went wrong during setup"
36
+ rescue RuntimeError => err
37
+ err
38
+ end
39
+ end
40
+
41
+ it "logs the error to Sentry" do
42
+ expect(::Sentry).to receive(:capture_exception).with(error).and_call_original
43
+
44
+ error_handler.handle_setup_exception(error)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hutch::Logging do
4
+ let(:dummy_object) do
5
+ class DummyObject
6
+ include described_class
7
+ end
8
+ end
9
+
10
+ describe '#logger' do
11
+ around do |example|
12
+ old_logger = described_class.logger
13
+ described_class.setup_logger
14
+ example.run
15
+ described_class.logger = old_logger
16
+ end
17
+
18
+ context 'with the default logger' do
19
+ subject { described_class.logger }
20
+
21
+ it { is_expected.to be_instance_of(Logger) }
22
+ end
23
+
24
+ context 'with a custom logger' do
25
+ let(:dummy_logger) { double("Dummy logger") }
26
+
27
+ it "users the custom logger" do
28
+ described_class.logger = dummy_logger
29
+ expect(described_class.logger).to eq(dummy_logger)
30
+ end
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,38 @@
1
+ require 'hutch/message'
2
+
3
+ describe Hutch::Message do
4
+ let(:delivery_info) { double('Delivery Info') }
5
+ let(:props) { double('Properties', content_type: "application/json") }
6
+ let(:body) {{ foo: 'bar' }.with_indifferent_access}
7
+ let(:json_body) { MultiJson.dump(body) }
8
+ subject(:message) { Hutch::Message.new(delivery_info, props, json_body, Hutch::Config[:serializer]) }
9
+
10
+ describe '#body' do
11
+ subject { super().body }
12
+ it { is_expected.to eq(body) }
13
+ end
14
+
15
+ describe '[]' do
16
+ subject { message[:foo] }
17
+ it { is_expected.to eq('bar') }
18
+ end
19
+
20
+ [:message_id, :timestamp].each do |method|
21
+ describe method.to_s do
22
+ it 'delegates to @properties' do
23
+ expect(props).to receive(method)
24
+ message.send(method)
25
+ end
26
+ end
27
+ end
28
+
29
+ [:routing_key, :exchange].each do |method|
30
+ describe method.to_s do
31
+ it 'delegates to @delivery_info' do
32
+ expect(delivery_info).to receive(method)
33
+ message.send(method)
34
+ end
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hutch::Serializers::JSON do
4
+ let(:subject) { described_class }
5
+
6
+ it "encode/decode" do
7
+ payload = { a: 1, b: 2 }
8
+ encoded = subject.encode(payload)
9
+ decoded = subject.decode(encoded)
10
+
11
+ expect(encoded).to eq "{\"a\":1,\"b\":2}"
12
+ expect(decoded).to eq("a" => 1, "b" => 2)
13
+ expect(decoded[:a]).to eq 1
14
+ expect(decoded[:b]).to eq 2
15
+ end
16
+
17
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Hutch::Tracers::Datadog do
4
+ describe "#handle" do
5
+ subject(:handle) { tracer.handle(message) }
6
+
7
+ let(:tracer) { described_class.new(klass) }
8
+ let(:klass) do
9
+ Class.new do
10
+ attr_reader :message
11
+
12
+ def initialize
13
+ @message = nil
14
+ end
15
+
16
+ def class
17
+ OpenStruct.new(name: 'ClassName')
18
+ end
19
+
20
+ def process(message)
21
+ @message = message
22
+ end
23
+ end.new
24
+ end
25
+ let(:message) { double(:message) }
26
+
27
+ before do
28
+ allow(::Datadog::Tracing).to receive(:trace).and_call_original
29
+ end
30
+
31
+ it 'uses Datadog tracer' do
32
+ handle
33
+
34
+ expect(::Datadog::Tracing).to have_received(:trace).with('ClassName',
35
+ hash_including(service: 'hutch', type: 'rabbitmq'))
36
+ end
37
+
38
+ it 'processes the message' do
39
+ expect {
40
+ handle
41
+ }.to change { klass.message }.from(nil).to(message)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,51 @@
1
+ require 'hutch/waiter'
2
+
3
+ RSpec.describe Hutch::Waiter do
4
+ describe '.wait_until_signaled' do
5
+ let(:pid) { Process.pid }
6
+ def start_kill_thread(signal)
7
+ Thread.new do
8
+ # sleep allows the worker time to set up the signal handling
9
+ # before the kill signal is sent.
10
+ sleep 0.001
11
+ Process.kill signal, pid
12
+ end
13
+ end
14
+
15
+ context 'a QUIT signal is received', if: RSpec::Support::Ruby.mri? do
16
+ it 'logs that hutch is stopping' do
17
+ expect(Hutch::Logging.logger).to receive(:info)
18
+ .with('caught SIGQUIT, stopping hutch...')
19
+
20
+ start_kill_thread('QUIT')
21
+ described_class.wait_until_signaled
22
+ end
23
+ end
24
+
25
+ context 'a TERM signal is received', if: !defined?(JRUBY_VERSION) do
26
+ it 'logs that hutch is stopping' do
27
+ expect(Hutch::Logging.logger).to receive(:info)
28
+ .with('caught SIGTERM, stopping hutch...')
29
+
30
+ start_kill_thread('TERM')
31
+ described_class.wait_until_signaled
32
+ end
33
+ end
34
+
35
+ context 'a INT signal is received', if: !defined?(JRUBY_VERSION) do
36
+ it 'logs that hutch is stopping' do
37
+ expect(Hutch::Logging.logger).to receive(:info)
38
+ .with('caught SIGINT, stopping hutch...')
39
+
40
+ start_kill_thread('INT')
41
+ described_class.wait_until_signaled
42
+ end
43
+ end
44
+ end
45
+
46
+ describe described_class::SHUTDOWN_SIGNALS do
47
+ it 'includes only things in Signal.list.keys' do
48
+ expect(described_class).to eq(described_class & Signal.list.keys)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,184 @@
1
+ require 'spec_helper'
2
+ require 'hutch/worker'
3
+
4
+ describe Hutch::Worker do
5
+ let(:consumer) { double('Consumer', routing_keys: %w( a b c ),
6
+ get_queue_name: 'consumer', get_arguments: {},
7
+ get_options: {}, get_serializer: nil) }
8
+ let(:consumers) { [consumer, double('Consumer')] }
9
+ let(:broker) { Hutch::Broker.new }
10
+ let(:setup_procs) { Array.new(2) { Proc.new {} } }
11
+ subject(:worker) { Hutch::Worker.new(broker, consumers, setup_procs) }
12
+
13
+ describe ".#run" do
14
+ it "calls each setup proc" do
15
+ setup_procs.each { |prc| expect(prc).to receive(:call) }
16
+ allow(worker).to receive(:setup_queues)
17
+ allow(Hutch::Waiter).to receive(:wait_until_signaled)
18
+ allow(broker).to receive(:stop)
19
+
20
+ worker.run
21
+ end
22
+ end
23
+
24
+ describe '#setup_queues' do
25
+ it 'sets up queues for each of the consumers' do
26
+ consumers.each do |consumer|
27
+ expect(worker).to receive(:setup_queue).with(consumer)
28
+ end
29
+ worker.setup_queues
30
+ end
31
+ end
32
+
33
+ describe '#setup_queue' do
34
+ let(:queue) { double('Queue', bind: nil, subscribe: nil) }
35
+ before { allow(broker).to receive_messages(queue: queue, bind_queue: nil) }
36
+
37
+ it 'creates a queue' do
38
+ expect(broker).to receive(:queue).with(consumer.get_queue_name, consumer.get_options).and_return(queue)
39
+ worker.setup_queue(consumer)
40
+ end
41
+
42
+ it 'binds the queue to each of the routing keys' do
43
+ expect(broker).to receive(:bind_queue).with(queue, %w( a b c ))
44
+ worker.setup_queue(consumer)
45
+ end
46
+
47
+ it 'sets up a subscription' do
48
+ expect(queue).to receive(:subscribe).with(consumer_tag: %r(^hutch\-.{36}$), manual_ack: true)
49
+ worker.setup_queue(consumer)
50
+ end
51
+
52
+ context 'with a configured consumer tag prefix' do
53
+ before { Hutch::Config.set(:consumer_tag_prefix, 'appname') }
54
+
55
+ it 'sets up a subscription with the configured tag prefix' do
56
+ expect(queue).to receive(:subscribe).with(consumer_tag: %r(^appname\-.{36}$), manual_ack: true)
57
+ worker.setup_queue(consumer)
58
+ end
59
+ end
60
+
61
+ context 'with a configured consumer tag prefix that is too long' do
62
+ let(:maximum_size) { 255 - SecureRandom.uuid.size - 1 }
63
+ before { Hutch::Config.set(:consumer_tag_prefix, 'a'.*(maximum_size + 1)) }
64
+
65
+ it 'raises an error' do
66
+ expect { worker.setup_queue(consumer) }.to raise_error(/Tag must be 255 bytes long at most/)
67
+ end
68
+ end
69
+ end
70
+
71
+ describe '#handle_message' do
72
+ let(:payload) { '{}' }
73
+ let(:consumer_instance) { double('Consumer instance') }
74
+ let(:delivery_info) { double('Delivery Info', routing_key: '',
75
+ delivery_tag: 'dt') }
76
+ let(:properties) { double('Properties', message_id: nil, content_type: "application/json") }
77
+ before { allow(consumer).to receive_messages(new: consumer_instance) }
78
+ before { allow(broker).to receive(:ack) }
79
+ before { allow(broker).to receive(:nack) }
80
+ before { allow(consumer_instance).to receive(:broker=) }
81
+ before { allow(consumer_instance).to receive(:delivery_info=) }
82
+
83
+ it 'passes the message to the consumer' do
84
+ expect(consumer_instance).to receive(:process).
85
+ with(an_instance_of(Hutch::Message))
86
+ expect(consumer_instance).to receive(:message_rejected?).and_return(false)
87
+ worker.handle_message(consumer, delivery_info, properties, payload)
88
+ end
89
+
90
+ it 'acknowledges the message' do
91
+ allow(consumer_instance).to receive(:process)
92
+ expect(broker).to receive(:ack).with(delivery_info.delivery_tag)
93
+ expect(consumer_instance).to receive(:message_rejected?).and_return(false)
94
+ worker.handle_message(consumer, delivery_info, properties, payload)
95
+ end
96
+
97
+ context 'when the consumer fails and a requeue is configured' do
98
+
99
+ it 'requeues the message' do
100
+ allow(consumer_instance).to receive(:process).and_raise('failed')
101
+ requeuer = double
102
+ allow(requeuer).to receive(:handle) { |delivery_info, properties, broker, e|
103
+ broker.requeue delivery_info.delivery_tag
104
+ true
105
+ }
106
+ allow(worker).to receive(:error_acknowledgements).and_return([requeuer])
107
+ expect(broker).to_not receive(:ack)
108
+ expect(broker).to_not receive(:nack)
109
+ expect(broker).to receive(:requeue)
110
+
111
+ worker.handle_message(consumer, delivery_info, properties, payload)
112
+ end
113
+ end
114
+
115
+
116
+ context 'when the consumer raises an exception' do
117
+ before { allow(consumer_instance).to receive(:process).and_raise('a consumer error') }
118
+
119
+ it 'logs the error' do
120
+ Hutch::Config[:error_handlers].each do |backend|
121
+ expect(backend).to receive(:handle)
122
+ end
123
+ worker.handle_message(consumer, delivery_info, properties, payload)
124
+ end
125
+
126
+ it 'rejects the message' do
127
+ expect(broker).to receive(:nack).with(delivery_info.delivery_tag)
128
+ worker.handle_message(consumer, delivery_info, properties, payload)
129
+ end
130
+ end
131
+
132
+ context "when the payload is not valid json" do
133
+ let(:payload) { "Not Valid JSON" }
134
+
135
+ it 'logs the error' do
136
+ Hutch::Config[:error_handlers].each do |backend|
137
+ expect(backend).to receive(:handle)
138
+ end
139
+ worker.handle_message(consumer, delivery_info, properties, payload)
140
+ end
141
+
142
+ it 'rejects the message' do
143
+ expect(broker).to receive(:nack).with(delivery_info.delivery_tag)
144
+ worker.handle_message(consumer, delivery_info, properties, payload)
145
+ end
146
+ end
147
+ end
148
+
149
+
150
+ describe '#acknowledge_error' do
151
+ let(:delivery_info) { double('Delivery Info', routing_key: '',
152
+ delivery_tag: 'dt') }
153
+ let(:properties) { double('Properties', message_id: 'abc123') }
154
+
155
+ subject { worker.acknowledge_error delivery_info, properties, broker, StandardError.new }
156
+
157
+ it 'stops when it runs a successful acknowledgement' do
158
+ skip_ack = double handle: false
159
+ always_ack = double handle: true
160
+ never_used = double handle: true
161
+
162
+ allow(worker).
163
+ to receive(:error_acknowledgements).
164
+ and_return([skip_ack, always_ack, never_used])
165
+
166
+ expect(never_used).to_not receive(:handle)
167
+
168
+ subject
169
+ end
170
+
171
+ it 'defaults to nacking' do
172
+ skip_ack = double handle: false
173
+
174
+ allow(worker).
175
+ to receive(:error_acknowledgements).
176
+ and_return([skip_ack, skip_ack])
177
+
178
+ expect(broker).to receive(:nack)
179
+
180
+ subject
181
+ end
182
+ end
183
+ end
184
+
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hutch do
4
+ describe '.register_consumer' do
5
+ let(:consumer_a) { double('Consumer') }
6
+ let(:consumer_b) { double('Consumer') }
7
+
8
+ it 'saves the consumers in the global consumer list' do
9
+ Hutch.register_consumer(consumer_a)
10
+ Hutch.register_consumer(consumer_b)
11
+ expect(Hutch.consumers).to include consumer_a
12
+ expect(Hutch.consumers).to include consumer_b
13
+ end
14
+ end
15
+
16
+ describe '.connect' do
17
+ context 'not connected' do
18
+ let(:options) { double 'options' }
19
+ let(:config) { double 'config' }
20
+ let(:broker) { double 'broker' }
21
+ let(:action) { Hutch.connect(options, config) }
22
+
23
+ it 'passes options and config' do
24
+ expect(Hutch::Broker).to receive(:new).with(config).and_return broker
25
+ expect(broker).to receive(:connect).with options
26
+
27
+ action
28
+ end
29
+
30
+ end
31
+
32
+ context 'connected' do
33
+ before { allow(Hutch).to receive(:connected?).and_return true }
34
+
35
+ it 'does not reconnect' do
36
+ expect(Hutch::Broker).not_to receive :new
37
+ Hutch.connect
38
+ end
39
+ end
40
+ end
41
+
42
+ describe '.connected?' do
43
+ subject(:connected?) { Hutch.connected? }
44
+
45
+ before { allow(Hutch).to receive(:broker).and_return(broker) }
46
+
47
+ context 'without a broker' do
48
+ let(:broker) { nil }
49
+
50
+ it { expect(connected?).to be_falsey }
51
+ end
52
+
53
+ context 'without a connection' do
54
+ let(:connection) { nil }
55
+ let(:broker) { double(:broker, connection: connection) }
56
+
57
+ it { expect(connected?).to be_falsey }
58
+ end
59
+
60
+ context 'with a closed connection' do
61
+ let(:connection) { double(:connection, open?: false) }
62
+ let(:broker) { double(:broker, connection: connection) }
63
+
64
+ it { expect(connected?).to be_falsey }
65
+ end
66
+
67
+ context 'with an opened connection' do
68
+ let(:connection) { double(:connection, open?: true) }
69
+ let(:broker) { double(:broker, connection: connection) }
70
+
71
+ it { expect(connected?).to be_truthy }
72
+ end
73
+ end
74
+
75
+ describe '#publish' do
76
+ let(:broker) { double(Hutch::Broker) }
77
+ let(:args) { ['test.key', 'message', { headers: { foo: 'bar' } }] }
78
+
79
+ before { allow(Hutch).to receive(:broker).and_return(broker) }
80
+
81
+ it 'delegates to Hutch::Broker#publish' do
82
+ expect(broker).to receive(:publish).with(*args)
83
+ Hutch.publish(*args)
84
+ end
85
+ end
86
+ end
87
+
@@ -0,0 +1,42 @@
1
+ require 'simplecov'
2
+ if ENV['TRAVIS']
3
+ require 'coveralls'
4
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
5
+ end
6
+
7
+ SimpleCov.start do
8
+ add_filter '/spec/'
9
+ add_filter '/.bundle/'
10
+ end
11
+
12
+ require 'raven'
13
+ require 'hutch'
14
+ require 'logger'
15
+
16
+ # set logger to be a null logger
17
+ Hutch::Logging.logger = Logger.new(File::NULL)
18
+
19
+ RSpec.configure do |config|
20
+ config.raise_errors_for_deprecations!
21
+
22
+ if defined?(JRUBY_VERSION)
23
+ config.filter_run_excluding adapter: :bunny
24
+ else
25
+ config.filter_run_excluding adapter: :march_hare
26
+ end
27
+
28
+ config.mock_with :rspec do |mocks|
29
+ mocks.verify_partial_doubles = true
30
+ end
31
+ end
32
+
33
+ # Constants (classes, etc) defined within a block passed to this method
34
+ # will be removed from the global namespace after the block as run.
35
+ def isolate_constants
36
+ existing_constants = Object.constants
37
+ yield
38
+ ensure
39
+ (Object.constants - existing_constants).each do |constant|
40
+ Object.send(:remove_const, constant)
41
+ end
42
+ end
File without changes
@@ -0,0 +1,4 @@
1
+ def init
2
+ super
3
+ sections.push :settings
4
+ end
@@ -0,0 +1,13 @@
1
+ .settings {
2
+ border-spacing: 2.5rem;
3
+ border-collapse: collapse;
4
+ }
5
+
6
+ .settings thead th {
7
+ text-align: left;
8
+ }
9
+
10
+ .settings thead th,
11
+ .settings tbody td {
12
+ padding: .5em 1em;
13
+ }
@@ -0,0 +1,7 @@
1
+ def init
2
+ super
3
+ end
4
+
5
+ def stylesheets
6
+ super + %w(css/hutch.css)
7
+ end
@@ -0,0 +1,5 @@
1
+ <% if object['custom_field'] %>
2
+ <p>
3
+ <%= object['custom_field'] %>
4
+ </p>
5
+ <% end %>
@@ -0,0 +1,4 @@
1
+ def init
2
+ super
3
+ sections.last.place(:settings).after(:source)
4
+ end
@@ -0,0 +1,40 @@
1
+ <% if object['setting_rows'] %>
2
+ <h2>
3
+ Configuration
4
+ </h2>
5
+
6
+ <div class="tags">
7
+ <table border="1" class="settings">
8
+ <thead>
9
+ <tr>
10
+ <th>
11
+ Setting name
12
+ </th>
13
+ <th>
14
+ Default value
15
+ </th>
16
+ <th>
17
+ Type
18
+ </th>
19
+ <th>
20
+ ENV variable
21
+ </th>
22
+ <th>
23
+ Description
24
+ </th>
25
+ </tr>
26
+ </thead>
27
+ <tbody>
28
+ <% for setting in object['setting_rows'] %>
29
+ <tr>
30
+ <td><tt><%= resolve_links "{Hutch::Config##{setting[:name]} #{setting[:name]}}" %></tt></td>
31
+ <td><%= setting[:default_value] %></td>
32
+ <td><%= setting[:type] %></td>
33
+ <td><tt>HUTCH_<%= setting[:name].upcase %></tt></td>
34
+ <td><%= html_markup_markdown setting[:first_line_of_description] %></td>
35
+ </tr>
36
+ <% end %>
37
+ </tbody>
38
+ </table>
39
+ </div>
40
+ <% end %>
@@ -0,0 +1,4 @@
1
+ def init
2
+ super
3
+ sections.place(:settings).before(:children)
4
+ end