stoplight 1.0.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 99e35ef6375d1da3d14f453873c410bcad7ad4c6
4
- data.tar.gz: 16d8b5d40dd9f17de105a3df570f5d41cdd997c6
3
+ metadata.gz: c9ae554bc9377af5da84befa1e47b71f28d3610b
4
+ data.tar.gz: a65e07dbe879f7895751607894992ad5e8a437f1
5
5
  SHA512:
6
- metadata.gz: 24bc5b7cc600179cdd4ef63976d544379574078c33810faf507aaee6e8a37e78c8a28f88d5897ff053f9b8ffc819dd6a5b07ddecb2e97402ffa7deb436b325ac
7
- data.tar.gz: d3b3339c2ff9c14233ea35035ac96e127894d5455748d9085f7384077bb04d45c7ac31c5f4bd7ed94d21ed876e66f52fda8363bfb5c7464e54b7f5cb18e94082
6
+ metadata.gz: e7e320df17b172d01c35e397d21046f44d30608a3491eb05036b2cfeb75c79afc83c15e01c1fc676518de5e3313fa4597bfd5ca84f0322fbf30ff387bf5eead2
7
+ data.tar.gz: 0db404935da87b9e0b731d9a191288234db19f0b37b240bfe4d32418482a9fe4a6a03f2a039263d379447b5db991e1b172629216997bcf69278f2fb0ed743eda
data/CHANGELOG.md CHANGED
@@ -1,6 +1,10 @@
1
- # Changelog
1
+ # Change log
2
2
 
3
- This project uses [Semantic Versioning][1].
3
+ Stoplight uses [Semantic Versioning][1].
4
+
5
+ ## v1.1.0 (2015-07-04)
6
+
7
+ - #71: Added Slack notifier. Thanks, @s1mplex!
4
8
 
5
9
  ## v1.0.0 (2015-02-19)
6
10
 
data/LICENSE.md CHANGED
@@ -1,20 +1,21 @@
1
+ The MIT License (MIT)
2
+
1
3
  Copyright (c) 2015 Cameron Desautels, Taylor Fausak & Justin Steffy
2
4
 
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject
9
- to the following conditions:
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
10
11
 
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
13
14
 
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18
- ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19
- CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,37 +1,20 @@
1
- <p align="center">
2
- <img alt="Stoplight" src="https://a.pomf.se/wdlzpt.svg">
3
- </p>
4
-
5
- <h1 align="center">
6
- <a href="https://github.com/orgsync/stoplight">
7
- Stoplight
8
- </a>
9
- </h1>
10
-
11
- <p align="center">
12
- Stoplight is traffic control for code. It's an implementation of
13
- the circuit breaker pattern in Ruby.
14
- </p>
15
-
16
- <p align="center">
17
- <a href="https://rubygems.org/gems/stoplight">
18
- <img alt="" src="https://img.shields.io/gem/v/stoplight.svg">
19
- </a>
20
- <a href="https://travis-ci.org/orgsync/stoplight">
21
- <img alt="" src="https://img.shields.io/travis/orgsync/stoplight/master.svg">
22
- </a>
23
- <a href="https://coveralls.io/r/orgsync/stoplight">
24
- <img alt="" src="https://img.shields.io/coveralls/orgsync/stoplight/master.svg">
25
- </a>
26
- <a href="https://codeclimate.com/github/orgsync/stoplight">
27
- <img alt="" src="https://img.shields.io/codeclimate/github/orgsync/stoplight.svg">
28
- </a>
29
- <a href="https://gemnasium.com/orgsync/stoplight">
30
- <img alt="" src="https://img.shields.io/gemnasium/orgsync/stoplight.svg">
31
- </a>
32
- </p>
33
-
34
- <hr>
1
+ # [Stoplight][]
2
+
3
+ [![Version][]](https://rubygems.org/gems/stoplight)
4
+ [![Build][]](https://travis-ci.org/orgsync/stoplight)
5
+ [![Coverage][]](https://coveralls.io/r/orgsync/stoplight)
6
+ [![Grade][]](http://www.libgrader.com/libraries/ruby/stoplight)
7
+ [![Climate][]](https://codeclimate.com/github/orgsync/stoplight)
8
+ [![Dependencies][]](https://gemnasium.com/orgsync/stoplight)
9
+
10
+ Stoplight is traffic control for code. It's an implementation of the circuit
11
+ breaker pattern in Ruby.
12
+
13
+ ---
14
+
15
+ Does your code use unreliable systems, like a flaky database or a
16
+ spotty web service? Wrap those up with stoplights to prevent them
17
+ from affecting the rest of your application down.
35
18
 
36
19
  Check out [stoplight-admin][] for controlling your stoplights.
37
20
 
@@ -45,9 +28,12 @@ Check out [stoplight-admin][] for controlling your stoplights.
45
28
  - [Setup](#setup)
46
29
  - [Data store](#data-store)
47
30
  - [Notifiers](#notifiers)
31
+ - [HipChat](#hipchat)
32
+ - [Slack](#slack)
48
33
  - [Rails](#rails-1)
49
34
  - [Advanced usage](#advanced-usage)
50
35
  - [Locking](#locking)
36
+ - [Testing](#testing)
51
37
  - [Credits](#credits)
52
38
 
53
39
  ## Installation
@@ -55,15 +41,20 @@ Check out [stoplight-admin][] for controlling your stoplights.
55
41
  Add it to your Gemfile:
56
42
 
57
43
  ``` rb
58
- gem 'stoplight', '~> 1.0'
44
+ gem 'stoplight', '~> 1.1'
59
45
  ```
60
46
 
61
47
  Or install it manually:
62
48
 
63
49
  ``` sh
64
- $ gem install stoplight --version '~> 1.0'
50
+ $ gem install stoplight --version '~> 1.1'
65
51
  ```
66
52
 
53
+ Stoplight uses [Semantic Versioning][]. Check out [the change log][] for a
54
+ detailed list of changes.
55
+
56
+ Stoplight works with all supported versions of Ruby (2.0 through 2.2).
57
+
67
58
  ## Basic usage
68
59
 
69
60
  To get started, create a stoplight:
@@ -74,7 +65,8 @@ light = Stoplight('example-1') { 22.0 / 7 }
74
65
  ```
75
66
 
76
67
  Then you can run it and it will return the result of calling the
77
- block. This is the green state.
68
+ block. This is the green state. (The green state corresponds to the
69
+ closed state for circuit breakers.)
78
70
 
79
71
  ``` rb
80
72
  light.run
@@ -94,7 +86,8 @@ light = Stoplight('example-2') { 1 / 0 }
94
86
 
95
87
  Now when you run it, the error will be recorded and passed through.
96
88
  After running it a few times, the stoplight will stop trying and
97
- fail fast. This is the red state.
89
+ fail fast. This is the red state. (The red state corresponds to the
90
+ open state for circuit breakers.)
98
91
 
99
92
  ``` rb
100
93
  light.run
@@ -111,7 +104,16 @@ light.color
111
104
  ```
112
105
 
113
106
  When the stoplight changes from green to red, it will notify every
114
- configured notifier.
107
+ configured notifier. See [the notifiers section][] to learn more
108
+ about notifiers.
109
+
110
+ The stoplight will move into the yellow state after being in the
111
+ red state for a while. (The yellow state corresponds to the half
112
+ open state for circuit breakers.) To configure how long it takes
113
+ to switch into the yellow state, check out [the timeout section][]
114
+ When stoplights are yellow, they'll try to run their code. If it
115
+ fails, they'll switch back to red. If it succeeds, they'll switch
116
+ to green.
115
117
 
116
118
  ### Custom errors
117
119
 
@@ -179,7 +181,7 @@ light.run
179
181
  ### Custom timeout
180
182
 
181
183
  Stoplights will automatically attempt to recover after a certain
182
- amount of time. A light in the red state for longer than the timeout
184
+ amount of time. A light in the red state for longer than the timeout
183
185
  will transition to the yellow state. This timeout is customizable.
184
186
 
185
187
  ``` rb
@@ -211,7 +213,9 @@ Here's an example configuration:
211
213
  ``` rb
212
214
  class ApplicationController < ActionController::Base
213
215
  around_action :stoplight
216
+
214
217
  private
218
+
215
219
  def stoplight(&block)
216
220
  Stoplight("#{params[:controller]}##{params[:action]}", &block)
217
221
  .with_allowed_errors([ActiveRecord::RecordNotFound])
@@ -262,10 +266,12 @@ Stoplight::Light.default_notifiers
262
266
  # => [#<Stoplight::Notifier::IO:...>]
263
267
  ```
264
268
 
265
- If you want to send notifications elsewhere, you'll have to set
266
- them up. Currently the only other supported notifier is HipChat.
267
- Make sure you have [the HipChat gem][] installed before configuring
268
- Stoplight.
269
+ If you want to send notifications elsewhere, you'll have to set them up.
270
+ Currently the only supported notifiers are HipChat and Slack.
271
+
272
+ #### HipChat
273
+
274
+ Make sure you have [the HipChat gem][] installed before configuring Stoplight.
269
275
 
270
276
  ``` rb
271
277
  require 'hipchat'
@@ -278,6 +284,21 @@ Stoplight::Light.default_notifiers += [notifier]
278
284
  # => [#<Stoplight::Notifier::IO:...>, #<Stoplight::Notifier::HipChat:...>]
279
285
  ```
280
286
 
287
+ #### Slack
288
+
289
+ Make sure you have [the Slack gem][] installed before configuring Stoplight.
290
+
291
+ ``` rb
292
+ require 'slack-notifier'
293
+ # => true
294
+ slack = Slack::Notifier.new('http://www.example.com/webhook-url')
295
+ # => #<Slack::Notifier:...>
296
+ notifier = Stoplight::Notifier::Slack.new(slack)
297
+ # => #<Stoplight::Notifier::Slack:...>
298
+ Stoplight::Light.default_notifiers += [notifier]
299
+ # => [#<Stoplight::Notifier::IO:...>, #<Stoplight::Notifier::Slack:...>]
300
+ ```
301
+
281
302
  ### Rails
282
303
 
283
304
  Stoplight is designed to work seamlessly with Rails. If you want
@@ -316,16 +337,61 @@ If you have configured a custom data store and that data store
316
337
  fails, Stoplight will switch over to using a blank in-memory data
317
338
  store. That means you will lose the locked state of any stoplights.
318
339
 
340
+ ## Testing
341
+
342
+ Stoplights typically work as expected without modification in test suites.
343
+ However there are a few things you can do to make them behave better. If your
344
+ stoplights are spewing messages into your test output, you can silence them
345
+ with a couple configuration changes.
346
+
347
+ ``` rb
348
+ Stoplight::Light.default_error_notifier = -> _ {}
349
+ Stoplight::Light.default_notifiers = []
350
+ ```
351
+
352
+ If your tests mysteriously fail because stoplights are the wrong color, you can
353
+ try resetting the data store before each test case. For example, this would
354
+ give each test case a fresh data store with RSpec.
355
+
356
+ ``` rb
357
+ before(:each) do
358
+ Stoplight::Light.default_data_Store = Stoplight::DataStore::Memory.new
359
+ end
360
+ ```
361
+
362
+ Sometimes you may want to test stoplights directly. You can avoid resetting the
363
+ data store by giving each stoplight a unique name.
364
+
365
+ ``` rb
366
+ stoplight = Stoplight("test-#{rand}") { ... }
367
+ ```
368
+
319
369
  ## Credits
320
370
 
321
- Stoplight is brought to you by [@camdez][] and [@tfausak][] from
322
- [@OrgSync][]. We were inspired by Martin Fowler's [CircuitBreaker][]
323
- article.
371
+ Stoplight is brought to you by [@camdez][] and [@tfausak][] from [@OrgSync][].
372
+ A [complete list of contributors][] is available on GitHub. We were inspired by
373
+ Martin Fowler's [CircuitBreaker][] article.
374
+
375
+ Stoplight is licensed under [the MIT License][].
324
376
 
377
+ [stoplight]: https://github.com/orgsync/stoplight
378
+ [version]: https://img.shields.io/gem/v/stoplight.svg?label=version
379
+ [build]: https://img.shields.io/travis/orgsync/stoplight/master.svg?label=build
380
+ [grade]: https://img.shields.io/badge/grade-A-brightgreen.svg
381
+ [coverage]: https://img.shields.io/coveralls/orgsync/stoplight/master.svg?label=coverage
382
+ [climate]: https://img.shields.io/codeclimate/github/orgsync/stoplight.svg?label=climate
383
+ [dependencies]: https://img.shields.io/gemnasium/orgsync/stoplight.svg?label=dependencies
325
384
  [stoplight-admin]: https://github.com/orgsync/stoplight-admin
385
+ [semantic versioning]: http://semver.org/spec/v2.0.0.html
386
+ [the change log]: CHANGELOG.md
387
+ [the notifiers section]: #notifiers
388
+ [the timeout section]: #custom-timeout
326
389
  [the redis gem]: https://rubygems.org/gems/redis
327
390
  [the hipchat gem]: https://rubygems.org/gems/hipchat
391
+ [the slack gem]: https://rubygems.org/gems/slack-notifier
328
392
  [@camdez]: https://github.com/camdez
329
393
  [@tfausak]: https://github.com/tfausak
330
394
  [@orgsync]: https://github.com/OrgSync
395
+ [complete list of contributors]: https://github.com/orgsync/stoplight/graphs/contributors
331
396
  [circuitbreaker]: http://martinfowler.com/bliki/CircuitBreaker.html
397
+ [the mit license]: LICENSE.md
data/lib/stoplight.rb CHANGED
@@ -19,6 +19,7 @@ require 'stoplight/notifier'
19
19
  require 'stoplight/notifier/base'
20
20
  require 'stoplight/notifier/hip_chat'
21
21
  require 'stoplight/notifier/io'
22
+ require 'stoplight/notifier/slack'
22
23
 
23
24
  require 'stoplight/default'
24
25
 
@@ -40,7 +40,7 @@ module Stoplight
40
40
  end
41
41
 
42
42
  def record_failure(light, failure)
43
- size, _ = @redis.multi do
43
+ size, = @redis.multi do
44
44
  @redis.lpush(failures_key(light), failure.to_json)
45
45
  @redis.ltrim(failures_key(light), 0, light.threshold - 1)
46
46
  end
@@ -49,7 +49,7 @@ module Stoplight
49
49
  end
50
50
 
51
51
  def clear_failures(light)
52
- failures, _ = @redis.multi do
52
+ failures, = @redis.multi do
53
53
  query_failures(light)
54
54
  @redis.del(failures_key(light))
55
55
  end
@@ -67,7 +67,7 @@ module Stoplight
67
67
  end
68
68
 
69
69
  def clear_state(light)
70
- state, _ = @redis.multi do
70
+ state, = @redis.multi do
71
71
  query_state(light)
72
72
  @redis.hdel(states_key, light.name)
73
73
  end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+
3
+ module Stoplight
4
+ module Notifier
5
+ # @see Base
6
+ class Slack < Base
7
+ # @return [Proc]
8
+ attr_reader :formatter
9
+
10
+ # @return [::Slack::Notifier]
11
+ attr_reader :slack
12
+
13
+ # @param slack [::Slack::Notifier]
14
+ # @param formatter [Proc, nil]
15
+ def initialize(slack, formatter = nil)
16
+ @slack = slack
17
+ @formatter = formatter || Default::FORMATTER
18
+ end
19
+
20
+ def notify(light, from_color, to_color, error)
21
+ message = formatter.call(light, from_color, to_color, error)
22
+ slack.ping(message)
23
+ message
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
2
 
3
3
  module Stoplight
4
- VERSION = Gem::Version.new('1.0.0')
4
+ VERSION = Gem::Version.new('1.1.0')
5
5
  end
data/spec/spec_helper.rb CHANGED
@@ -7,3 +7,10 @@ require 'stoplight'
7
7
  require 'timecop'
8
8
 
9
9
  Timecop.safe_mode = true
10
+
11
+ RSpec.configure do |rspec|
12
+ rspec.color = true
13
+ rspec.disable_monkey_patching!
14
+ rspec.order = :random
15
+ rspec.warnings = true
16
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight::Color do
5
+ RSpec.describe Stoplight::Color do
6
6
  it 'is a module' do
7
7
  expect(described_class).to be_a(Module)
8
8
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight::DataStore::Base do
5
+ RSpec.describe Stoplight::DataStore::Base do
6
6
  let(:data_store) { described_class.new }
7
7
 
8
8
  it 'is a class' do
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight::DataStore::Memory do
5
+ RSpec.describe Stoplight::DataStore::Memory do
6
6
  let(:data_store) { described_class.new }
7
7
  let(:light) { Stoplight::Light.new(name) {} }
8
8
  let(:name) { ('a'..'z').to_a.shuffle.join }
@@ -3,7 +3,7 @@
3
3
  require 'spec_helper'
4
4
  require 'fakeredis'
5
5
 
6
- describe Stoplight::DataStore::Redis do
6
+ RSpec.describe Stoplight::DataStore::Redis do
7
7
  let(:data_store) { described_class.new(redis) }
8
8
  let(:redis) { Redis.new }
9
9
  let(:light) { Stoplight::Light.new(name) {} }
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight::DataStore do
5
+ RSpec.describe Stoplight::DataStore do
6
6
  it 'is a module' do
7
7
  expect(described_class).to be_a(Module)
8
8
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight::Default do
5
+ RSpec.describe Stoplight::Default do
6
6
  it 'is a module' do
7
7
  expect(described_class).to be_a(Module)
8
8
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight::Error do
5
+ RSpec.describe Stoplight::Error do
6
6
  it 'is a module' do
7
7
  expect(described_class).to be_a(Module)
8
8
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight::Failure do
5
+ RSpec.describe Stoplight::Failure do
6
6
  let(:error) { ZeroDivisionError.new('divided by 0') }
7
7
  let(:error_class) { error.class.name }
8
8
  let(:error_message) { error.message }
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight::Light::Runnable do
5
+ RSpec.describe Stoplight::Light::Runnable do
6
6
  subject { Stoplight::Light.new(name, &code) }
7
7
 
8
8
  let(:code) { -> { code_result } }
@@ -20,7 +20,7 @@ describe Stoplight::Light::Runnable do
20
20
  let(:time) { Time.new }
21
21
 
22
22
  def random_string
23
- ('a'..'z').to_a.shuffle.first(8).join
23
+ ('a'..'z').to_a.sample(8).join
24
24
  end
25
25
 
26
26
  describe '#color' do
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight::Light do
5
+ RSpec.describe Stoplight::Light do
6
6
  let(:light) { described_class.new(name, &code) }
7
7
  let(:name) { ('a'..'z').to_a.shuffle.join }
8
8
  let(:code) { -> {} }
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight::Notifier::Base do
5
+ RSpec.describe Stoplight::Notifier::Base do
6
6
  let(:notifier) { described_class.new }
7
7
 
8
8
  it 'is a class' do
@@ -3,7 +3,7 @@
3
3
  require 'spec_helper'
4
4
  require 'hipchat'
5
5
 
6
- describe Stoplight::Notifier::HipChat do
6
+ RSpec.describe Stoplight::Notifier::HipChat do
7
7
  it 'is a class' do
8
8
  expect(described_class).to be_a(Module)
9
9
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight::Notifier::IO do
5
+ RSpec.describe Stoplight::Notifier::IO do
6
6
  it 'is a class' do
7
7
  expect(described_class).to be_a(Module)
8
8
  end
@@ -0,0 +1,55 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'slack-notifier'
5
+
6
+ RSpec.describe Stoplight::Notifier::Slack do
7
+ it 'is a subclass of Base' do
8
+ expect(described_class).to be < Stoplight::Notifier::Base
9
+ end
10
+
11
+ describe '#formatter' do
12
+ it 'is initially the default' do
13
+ expect(described_class.new(nil).formatter)
14
+ .to eql(Stoplight::Default::FORMATTER)
15
+ end
16
+
17
+ it 'reads the formatter' do
18
+ formatter = proc {}
19
+ expect(described_class.new(nil, formatter).formatter).to eql(formatter)
20
+ end
21
+ end
22
+
23
+ describe '#slack_notifier' do
24
+ it 'reads Slack::Notifier client' do
25
+ slack = Slack::Notifier.new('WEBHOOK_URL')
26
+ expect(described_class.new(slack).slack).to eql(slack)
27
+ end
28
+ end
29
+
30
+ describe '#notify' do
31
+ let(:light) { Stoplight::Light.new(name, &code) }
32
+ let(:name) { ('a'..'z').to_a.shuffle.join }
33
+ let(:code) { -> {} }
34
+ let(:from_color) { Stoplight::Color::GREEN }
35
+ let(:to_color) { Stoplight::Color::RED }
36
+ let(:notifier) { described_class.new(slack) }
37
+ let(:slack) { double(Slack::Notifier) }
38
+
39
+ before do
40
+ expect(slack).to receive(:ping).with(kind_of(String))
41
+ end
42
+
43
+ it 'returns the message' do
44
+ error = nil
45
+ expect(notifier.notify(light, from_color, to_color, error))
46
+ .to eql(notifier.formatter.call(light, from_color, to_color, error))
47
+ end
48
+
49
+ it 'returns the message with an error' do
50
+ error = ZeroDivisionError.new('divided by 0')
51
+ expect(notifier.notify(light, from_color, to_color, error))
52
+ .to eql(notifier.formatter.call(light, from_color, to_color, error))
53
+ end
54
+ end
55
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight::Notifier do
5
+ RSpec.describe Stoplight::Notifier do
6
6
  it 'is a module' do
7
7
  expect(described_class).to be_a(Module)
8
8
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight::State do
5
+ RSpec.describe Stoplight::State do
6
6
  it 'is a module' do
7
7
  expect(described_class).to be_a(Module)
8
8
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight::VERSION do
5
+ RSpec.describe Stoplight::VERSION do
6
6
  it 'is a gem version' do
7
7
  expect(described_class).to be_a(Gem::Version)
8
8
  end
@@ -2,13 +2,13 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Stoplight do
5
+ RSpec.describe Stoplight do
6
6
  it 'is a module' do
7
7
  expect(described_class).to be_a(Module)
8
8
  end
9
9
  end
10
10
 
11
- describe 'Stoplight' do
11
+ RSpec.describe 'Stoplight' do
12
12
  subject(:light) { Stoplight(name, &code) }
13
13
  let(:name) { ('a'..'z').to_a.shuffle.join }
14
14
  let(:code) { -> {} }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stoplight
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cameron Desautels
@@ -10,146 +10,202 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-02-19 00:00:00.000000000 Z
13
+ date: 2015-07-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: benchmark-ips
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - ~>
19
+ - - "~>"
20
20
  - !ruby/object:Gem::Version
21
- version: '2.1'
21
+ version: '2.2'
22
22
  type: :development
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
- - - ~>
26
+ - - "~>"
27
27
  - !ruby/object:Gem::Version
28
- version: '2.1'
28
+ version: '2.2'
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: coveralls
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
- - - ~>
33
+ - - "~>"
34
34
  - !ruby/object:Gem::Version
35
- version: '0.7'
35
+ version: '0.8'
36
36
  type: :development
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
- - - ~>
40
+ - - "~>"
41
41
  - !ruby/object:Gem::Version
42
- version: '0.7'
42
+ version: '0.8'
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: fakeredis
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - ~>
47
+ - - "~>"
48
48
  - !ruby/object:Gem::Version
49
49
  version: '0.5'
50
50
  type: :development
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
- - - ~>
54
+ - - "~>"
55
55
  - !ruby/object:Gem::Version
56
56
  version: '0.5'
57
+ - !ruby/object:Gem::Dependency
58
+ name: guard
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: '2.12'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '2.12'
71
+ - !ruby/object:Gem::Dependency
72
+ name: guard-rspec
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '4.6'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - "~>"
83
+ - !ruby/object:Gem::Version
84
+ version: '4.6'
85
+ - !ruby/object:Gem::Dependency
86
+ name: guard-rubocop
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: '1.2'
92
+ type: :development
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - "~>"
97
+ - !ruby/object:Gem::Version
98
+ version: '1.2'
57
99
  - !ruby/object:Gem::Dependency
58
100
  name: hipchat
59
101
  requirement: !ruby/object:Gem::Requirement
60
102
  requirements:
61
- - - ~>
103
+ - - "~>"
62
104
  - !ruby/object:Gem::Version
63
- version: '1.4'
105
+ version: '1.5'
64
106
  type: :development
65
107
  prerelease: false
66
108
  version_requirements: !ruby/object:Gem::Requirement
67
109
  requirements:
68
- - - ~>
110
+ - - "~>"
69
111
  - !ruby/object:Gem::Version
70
- version: '1.4'
112
+ version: '1.5'
71
113
  - !ruby/object:Gem::Dependency
72
114
  name: rake
73
115
  requirement: !ruby/object:Gem::Requirement
74
116
  requirements:
75
- - - ~>
117
+ - - "~>"
76
118
  - !ruby/object:Gem::Version
77
119
  version: '10.4'
78
120
  type: :development
79
121
  prerelease: false
80
122
  version_requirements: !ruby/object:Gem::Requirement
81
123
  requirements:
82
- - - ~>
124
+ - - "~>"
83
125
  - !ruby/object:Gem::Version
84
126
  version: '10.4'
85
127
  - !ruby/object:Gem::Dependency
86
128
  name: redis
87
129
  requirement: !ruby/object:Gem::Requirement
88
130
  requirements:
89
- - - ~>
131
+ - - "~>"
90
132
  - !ruby/object:Gem::Version
91
133
  version: '3.2'
92
134
  type: :development
93
135
  prerelease: false
94
136
  version_requirements: !ruby/object:Gem::Requirement
95
137
  requirements:
96
- - - ~>
138
+ - - "~>"
97
139
  - !ruby/object:Gem::Version
98
140
  version: '3.2'
99
141
  - !ruby/object:Gem::Dependency
100
142
  name: rspec
101
143
  requirement: !ruby/object:Gem::Requirement
102
144
  requirements:
103
- - - ~>
145
+ - - "~>"
104
146
  - !ruby/object:Gem::Version
105
- version: '3.2'
147
+ version: '3.3'
106
148
  type: :development
107
149
  prerelease: false
108
150
  version_requirements: !ruby/object:Gem::Requirement
109
151
  requirements:
110
- - - ~>
152
+ - - "~>"
111
153
  - !ruby/object:Gem::Version
112
- version: '3.2'
154
+ version: '3.3'
113
155
  - !ruby/object:Gem::Dependency
114
156
  name: rubocop
115
157
  requirement: !ruby/object:Gem::Requirement
116
158
  requirements:
117
- - - ~>
159
+ - - "~>"
160
+ - !ruby/object:Gem::Version
161
+ version: '0.32'
162
+ type: :development
163
+ prerelease: false
164
+ version_requirements: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - "~>"
167
+ - !ruby/object:Gem::Version
168
+ version: '0.32'
169
+ - !ruby/object:Gem::Dependency
170
+ name: slack-notifier
171
+ requirement: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - "~>"
118
174
  - !ruby/object:Gem::Version
119
- version: '0.29'
175
+ version: 1.2.1
120
176
  type: :development
121
177
  prerelease: false
122
178
  version_requirements: !ruby/object:Gem::Requirement
123
179
  requirements:
124
- - - ~>
180
+ - - "~>"
125
181
  - !ruby/object:Gem::Version
126
- version: '0.29'
182
+ version: 1.2.1
127
183
  - !ruby/object:Gem::Dependency
128
184
  name: timecop
129
185
  requirement: !ruby/object:Gem::Requirement
130
186
  requirements:
131
- - - ~>
187
+ - - "~>"
132
188
  - !ruby/object:Gem::Version
133
189
  version: '0.7'
134
190
  type: :development
135
191
  prerelease: false
136
192
  version_requirements: !ruby/object:Gem::Requirement
137
193
  requirements:
138
- - - ~>
194
+ - - "~>"
139
195
  - !ruby/object:Gem::Version
140
196
  version: '0.7'
141
197
  - !ruby/object:Gem::Dependency
142
198
  name: yard
143
199
  requirement: !ruby/object:Gem::Requirement
144
200
  requirements:
145
- - - ~>
201
+ - - "~>"
146
202
  - !ruby/object:Gem::Version
147
203
  version: '0.8'
148
204
  type: :development
149
205
  prerelease: false
150
206
  version_requirements: !ruby/object:Gem::Requirement
151
207
  requirements:
152
- - - ~>
208
+ - - "~>"
153
209
  - !ruby/object:Gem::Version
154
210
  version: '0.8'
155
211
  description: An implementation of the circuit breaker pattern.
@@ -162,7 +218,6 @@ extensions: []
162
218
  extra_rdoc_files: []
163
219
  files:
164
220
  - CHANGELOG.md
165
- - CONTRIBUTING.md
166
221
  - LICENSE.md
167
222
  - README.md
168
223
  - lib/stoplight.rb
@@ -180,6 +235,7 @@ files:
180
235
  - lib/stoplight/notifier/base.rb
181
236
  - lib/stoplight/notifier/hip_chat.rb
182
237
  - lib/stoplight/notifier/io.rb
238
+ - lib/stoplight/notifier/slack.rb
183
239
  - lib/stoplight/state.rb
184
240
  - lib/stoplight/version.rb
185
241
  - spec/spec_helper.rb
@@ -196,6 +252,7 @@ files:
196
252
  - spec/stoplight/notifier/base_spec.rb
197
253
  - spec/stoplight/notifier/hip_chat_spec.rb
198
254
  - spec/stoplight/notifier/io_spec.rb
255
+ - spec/stoplight/notifier/slack_spec.rb
199
256
  - spec/stoplight/notifier_spec.rb
200
257
  - spec/stoplight/state_spec.rb
201
258
  - spec/stoplight/version_spec.rb
@@ -210,12 +267,12 @@ require_paths:
210
267
  - lib
211
268
  required_ruby_version: !ruby/object:Gem::Requirement
212
269
  requirements:
213
- - - '>='
270
+ - - ">="
214
271
  - !ruby/object:Gem::Version
215
272
  version: 1.9.3
216
273
  required_rubygems_version: !ruby/object:Gem::Requirement
217
274
  requirements:
218
- - - '>='
275
+ - - ">="
219
276
  - !ruby/object:Gem::Version
220
277
  version: '0'
221
278
  requirements: []
@@ -239,6 +296,7 @@ test_files:
239
296
  - spec/stoplight/notifier/base_spec.rb
240
297
  - spec/stoplight/notifier/hip_chat_spec.rb
241
298
  - spec/stoplight/notifier/io_spec.rb
299
+ - spec/stoplight/notifier/slack_spec.rb
242
300
  - spec/stoplight/notifier_spec.rb
243
301
  - spec/stoplight/state_spec.rb
244
302
  - spec/stoplight/version_spec.rb
data/CONTRIBUTING.md DELETED
@@ -1,7 +0,0 @@
1
- # Contributing
2
-
3
- 1. **Fork** the repository.
4
- 2. Create a **branch** for your feature (`git checkout -b feature`).
5
- 3. **Commit** your changes (`git commit -a -m 'Feature'`).
6
- 4. **Push** to your branch (`git push origin feature`).
7
- 5. Create a **pull request**.