stoplight 1.1.1 → 1.2.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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +119 -59
- data/lib/stoplight.rb +4 -0
- data/lib/stoplight/notifier/bugsnag.rb +37 -0
- data/lib/stoplight/notifier/honeybadger.rb +43 -0
- data/lib/stoplight/notifier/logger.rb +19 -0
- data/lib/stoplight/version.rb +1 -1
- data/spec/stoplight/notifier/bugsnag_spec.rb +89 -0
- data/spec/stoplight/notifier/honeybadger_spec.rb +74 -0
- data/spec/stoplight/notifier/logger_spec.rb +70 -0
- metadata +49 -12
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d93190b30a8d042b53c5b2cf115a02dc4d2ca890
         | 
| 4 | 
            +
              data.tar.gz: 0c4f3b4da7602df759e976eed9d73dfdb87fa7e5
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: efbc488c2ebea3bca686f190d14a06bf48b563b2d1c4d07fc30692901d5d72aa353dd93b2d422d0dac0affe01d3cd16d2ea293b767c70ead80a571810b787190
         | 
| 7 | 
            +
              data.tar.gz: 93bd99e0422058fb537555e872baf50513672f9c0035eb6f717dae6157ae049c94ac8d810045a825b3d364dc0014a307f7705adbabcc36b6fb28b252b27ddf17
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -2,6 +2,12 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            Stoplight uses [Semantic Versioning][1].
         | 
| 4 4 |  | 
| 5 | 
            +
            ## v1.2.0 (2015-09-11)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            - #78: Added a Bugsnag notifier. Thanks, @bolshakov!
         | 
| 8 | 
            +
            - Added a Honeybadger notifier.
         | 
| 9 | 
            +
            - #77: Added a logger notifier. Thanks again, @bolshakov!
         | 
| 10 | 
            +
             | 
| 5 11 | 
             
            ## v1.1.1 (2015-07-16)
         | 
| 6 12 |  | 
| 7 13 | 
             
            - Introduced a generic notifier to reduce duplication between the IO and Slack
         | 
    
        data/README.md
    CHANGED
    
    | @@ -12,9 +12,9 @@ breaker pattern in Ruby. | |
| 12 12 |  | 
| 13 13 | 
             
            ---
         | 
| 14 14 |  | 
| 15 | 
            -
            Does your code use unreliable systems, like a flaky database or a
         | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 15 | 
            +
            Does your code use unreliable systems, like a flaky database or a spotty web
         | 
| 16 | 
            +
            service? Wrap calls to those up in stoplights to prevent them from affecting
         | 
| 17 | 
            +
            the rest of your application.
         | 
| 18 18 |  | 
| 19 19 | 
             
            Check out [stoplight-admin][] for controlling your stoplights.
         | 
| 20 20 |  | 
| @@ -27,8 +27,12 @@ Check out [stoplight-admin][] for controlling your stoplights. | |
| 27 27 | 
             
              - [Rails](#rails)
         | 
| 28 28 | 
             
            - [Setup](#setup)
         | 
| 29 29 | 
             
              - [Data store](#data-store)
         | 
| 30 | 
            +
                - [Redis](#redis)
         | 
| 30 31 | 
             
              - [Notifiers](#notifiers)
         | 
| 32 | 
            +
                - [Bugsnag](#bugsnag)
         | 
| 31 33 | 
             
                - [HipChat](#hipchat)
         | 
| 34 | 
            +
                - [Honeybadger](#honeybadger)
         | 
| 35 | 
            +
                - [Logger](#logger)
         | 
| 32 36 | 
             
                - [Slack](#slack)
         | 
| 33 37 | 
             
              - [Rails](#rails-1)
         | 
| 34 38 | 
             
            - [Advanced usage](#advanced-usage)
         | 
| @@ -64,9 +68,9 @@ light = Stoplight('example-1') { 22.0 / 7 } | |
| 64 68 | 
             
            # => #<Stoplight::Light:...>
         | 
| 65 69 | 
             
            ```
         | 
| 66 70 |  | 
| 67 | 
            -
            Then you can run it and it will return the result of calling the
         | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 71 | 
            +
            Then you can run it and it will return the result of calling the block. This is
         | 
| 72 | 
            +
            the green state. (The green state corresponds to the closed state for circuit
         | 
| 73 | 
            +
              breakers.)
         | 
| 70 74 |  | 
| 71 75 | 
             
            ``` rb
         | 
| 72 76 | 
             
            light.run
         | 
| @@ -75,19 +79,19 @@ light.color | |
| 75 79 | 
             
            # => "green"
         | 
| 76 80 | 
             
            ```
         | 
| 77 81 |  | 
| 78 | 
            -
            If everything goes well, you shouldn't even be able to tell that
         | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 82 | 
            +
            If everything goes well, you shouldn't even be able to tell that you're using a
         | 
| 83 | 
            +
            stoplight. That's not very interesting though, so let's create a failing
         | 
| 84 | 
            +
            stoplight:
         | 
| 81 85 |  | 
| 82 86 | 
             
            ``` rb
         | 
| 83 87 | 
             
            light = Stoplight('example-2') { 1 / 0 }
         | 
| 84 88 | 
             
            # => #<Stoplight::Light:...>
         | 
| 85 89 | 
             
            ```
         | 
| 86 90 |  | 
| 87 | 
            -
            Now when you run it, the error will be recorded and passed through.
         | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            +
            Now when you run it, the error will be recorded and passed through. After
         | 
| 92 | 
            +
            running it a few times, the stoplight will stop trying and fail fast. This is
         | 
| 93 | 
            +
            the red state. (The red state corresponds to the open state for circuit
         | 
| 94 | 
            +
              breakers.)
         | 
| 91 95 |  | 
| 92 96 | 
             
            ``` rb
         | 
| 93 97 | 
             
            light.run
         | 
| @@ -103,23 +107,21 @@ light.color | |
| 103 107 | 
             
            # => "red"
         | 
| 104 108 | 
             
            ```
         | 
| 105 109 |  | 
| 106 | 
            -
            When the stoplight changes from green to red, it will notify every
         | 
| 107 | 
            -
             | 
| 108 | 
            -
            about notifiers.
         | 
| 110 | 
            +
            When the stoplight changes from green to red, it will notify every configured
         | 
| 111 | 
            +
            notifier. See [the notifiers section][] to learn more about notifiers.
         | 
| 109 112 |  | 
| 110 | 
            -
            The stoplight will move into the yellow state after being in the
         | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 116 | 
            -
            to green.
         | 
| 113 | 
            +
            The stoplight will move into the yellow state after being in the red state for
         | 
| 114 | 
            +
            a while. (The yellow state corresponds to the half open state for circuit
         | 
| 115 | 
            +
              breakers.) To configure how long it takes to switch into the yellow state,
         | 
| 116 | 
            +
              check out [the timeout section][] When stoplights are yellow, they will try
         | 
| 117 | 
            +
              to run their code. If it fails, they'll switch back to red. If it succeeds,
         | 
| 118 | 
            +
              they'll switch to green.
         | 
| 117 119 |  | 
| 118 120 | 
             
            ### Custom errors
         | 
| 119 121 |  | 
| 120 | 
            -
            Some errors shouldn't cause your stoplight to move into the red
         | 
| 121 | 
            -
             | 
| 122 | 
            -
             | 
| 122 | 
            +
            Some errors shouldn't cause your stoplight to move into the red state. Usually
         | 
| 123 | 
            +
            these are handled elsewhere in your stack and don't represent real failures. A
         | 
| 124 | 
            +
            good example is `ActiveRecord::RecordNotFound`.
         | 
| 123 125 |  | 
| 124 126 | 
             
            ``` rb
         | 
| 125 127 | 
             
            light = Stoplight('example-3') { User.find(123) }
         | 
| @@ -140,10 +142,10 @@ The following errors are always allowed: `NoMemoryError`, `ScriptError`, | |
| 140 142 |  | 
| 141 143 | 
             
            ### Custom fallback
         | 
| 142 144 |  | 
| 143 | 
            -
            By default, stoplights will re-raise errors when they're green.
         | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 145 | 
            +
            By default, stoplights will re-raise errors when they're green. When they're
         | 
| 146 | 
            +
            red, they'll raise a `Stoplight::Error::RedLight` error. You can provide a
         | 
| 147 | 
            +
            fallback that will be called in both of these cases. It will be passed the
         | 
| 148 | 
            +
            error if the light was green.
         | 
| 147 149 |  | 
| 148 150 | 
             
            ``` rb
         | 
| 149 151 | 
             
            light = Stoplight('example-4') { 1 / 0 }
         | 
| @@ -166,9 +168,8 @@ light.run | |
| 166 168 |  | 
| 167 169 | 
             
            ### Custom threshold
         | 
| 168 170 |  | 
| 169 | 
            -
            Some bits of code might be allowed to fail more or less frequently
         | 
| 170 | 
            -
             | 
| 171 | 
            -
            in seconds.
         | 
| 171 | 
            +
            Some bits of code might be allowed to fail more or less frequently than others.
         | 
| 172 | 
            +
            You can configure this by setting a custom threshold.
         | 
| 172 173 |  | 
| 173 174 | 
             
            ``` rb
         | 
| 174 175 | 
             
            light = Stoplight('example-5') { fail }
         | 
| @@ -185,9 +186,9 @@ The default threshold is `3`. | |
| 185 186 |  | 
| 186 187 | 
             
            ### Custom timeout
         | 
| 187 188 |  | 
| 188 | 
            -
            Stoplights will automatically attempt to recover after a certain
         | 
| 189 | 
            -
             | 
| 190 | 
            -
             | 
| 189 | 
            +
            Stoplights will automatically attempt to recover after a certain amount of
         | 
| 190 | 
            +
            time. A light in the red state for longer than the timeout will transition to
         | 
| 191 | 
            +
            the yellow state. This timeout is customizable.
         | 
| 191 192 |  | 
| 192 193 | 
             
            ``` rb
         | 
| 193 194 | 
             
            light = Stoplight('example-6') { fail }
         | 
| @@ -208,13 +209,15 @@ light.run | |
| 208 209 | 
             
            # RuntimeError:
         | 
| 209 210 | 
             
            ```
         | 
| 210 211 |  | 
| 211 | 
            -
            The default timeout is `60` seconds.  | 
| 212 | 
            -
            automatic recovery | 
| 212 | 
            +
            The default timeout is `60` seconds. To disable automatic recovery, set the
         | 
| 213 | 
            +
            timeout to `Float::INFINITY`. To make automatic recovery instantaneous, set the
         | 
| 214 | 
            +
            timeout to `0` seconds. Note that this is not recommended, as it effectively
         | 
| 215 | 
            +
            replaces the red state with yellow.
         | 
| 213 216 |  | 
| 214 217 | 
             
            ### Rails
         | 
| 215 218 |  | 
| 216 | 
            -
            Stoplight was designed to wrap Rails actions with minimal effort.
         | 
| 217 | 
            -
             | 
| 219 | 
            +
            Stoplight was designed to wrap Rails actions with minimal effort. Here's an
         | 
| 220 | 
            +
            example configuration:
         | 
| 218 221 |  | 
| 219 222 | 
             
            ``` rb
         | 
| 220 223 | 
             
            class ApplicationController < ActionController::Base
         | 
| @@ -247,9 +250,12 @@ Stoplight::Light.default_data_store | |
| 247 250 | 
             
            # => #<Stoplight::DataStore::Memory:...>
         | 
| 248 251 | 
             
            ```
         | 
| 249 252 |  | 
| 250 | 
            -
            If you want to use a persistent data store, you'll have to set it
         | 
| 251 | 
            -
             | 
| 252 | 
            -
             | 
| 253 | 
            +
            If you want to use a persistent data store, you'll have to set it up. Currently
         | 
| 254 | 
            +
            the only supported persistent data store is Redis.
         | 
| 255 | 
            +
             | 
| 256 | 
            +
            #### Redis
         | 
| 257 | 
            +
             | 
| 258 | 
            +
            Make sure you have [the Redis gem][] (`~> 3.2`) installed before configuring
         | 
| 253 259 | 
             
            Stoplight.
         | 
| 254 260 |  | 
| 255 261 | 
             
            ``` rb
         | 
| @@ -273,11 +279,25 @@ Stoplight::Light.default_notifiers | |
| 273 279 | 
             
            ```
         | 
| 274 280 |  | 
| 275 281 | 
             
            If you want to send notifications elsewhere, you'll have to set them up.
         | 
| 276 | 
            -
             | 
| 282 | 
            +
             | 
| 283 | 
            +
            #### Bugsnag
         | 
| 284 | 
            +
             | 
| 285 | 
            +
            Make sure you have [the Bugsnag gem][] (`~> 2.8`) installed before configuring
         | 
| 286 | 
            +
            Stoplight.
         | 
| 287 | 
            +
             | 
| 288 | 
            +
            ``` rb
         | 
| 289 | 
            +
            require 'bugsnag'
         | 
| 290 | 
            +
            # => true
         | 
| 291 | 
            +
            notifier = Stoplight::Notifier::Bugsnag.new(Bugsnag)
         | 
| 292 | 
            +
            # => #<Stoplight::Notifier::Bugsnag:...>
         | 
| 293 | 
            +
            Stoplight::Light.default_notifiers += [notifier]
         | 
| 294 | 
            +
            # => [#<Stoplight::Notifier::IO:...>, #<Stoplight::Notifier::Bugsnag:...>]
         | 
| 295 | 
            +
            ```
         | 
| 277 296 |  | 
| 278 297 | 
             
            #### HipChat
         | 
| 279 298 |  | 
| 280 | 
            -
            Make sure you have [the HipChat gem][] installed before configuring | 
| 299 | 
            +
            Make sure you have [the HipChat gem][] (`~> 1.5`) installed before configuring
         | 
| 300 | 
            +
            Stoplight.
         | 
| 281 301 |  | 
| 282 302 | 
             
            ``` rb
         | 
| 283 303 | 
             
            require 'hipchat'
         | 
| @@ -290,9 +310,40 @@ Stoplight::Light.default_notifiers += [notifier] | |
| 290 310 | 
             
            # => [#<Stoplight::Notifier::IO:...>, #<Stoplight::Notifier::HipChat:...>]
         | 
| 291 311 | 
             
            ```
         | 
| 292 312 |  | 
| 313 | 
            +
            #### Honeybadger
         | 
| 314 | 
            +
             | 
| 315 | 
            +
            Make sure you have [the Honeybadger gem][] (`~> 2.1`) installed before
         | 
| 316 | 
            +
            configuring Stoplight.
         | 
| 317 | 
            +
             | 
| 318 | 
            +
            ``` rb
         | 
| 319 | 
            +
            require 'honeybadger'
         | 
| 320 | 
            +
            # => true
         | 
| 321 | 
            +
            notifier = Stoplight::Notifier::Honeybadger.new('api key')
         | 
| 322 | 
            +
            # => #<Stoplight::Notifier::Honeybadger:...>
         | 
| 323 | 
            +
            Stoplight::Light.default_notifiers += [notifier]
         | 
| 324 | 
            +
            # => [#<Stoplight::Notifier::IO:...>, #<Stoplight::Notifier::Honeybadger:...>]
         | 
| 325 | 
            +
            ```
         | 
| 326 | 
            +
             | 
| 327 | 
            +
            #### Logger
         | 
| 328 | 
            +
             | 
| 329 | 
            +
            Stoplight can be configured to use [the Logger class][] from the standard
         | 
| 330 | 
            +
            library.
         | 
| 331 | 
            +
             | 
| 332 | 
            +
            ``` rb
         | 
| 333 | 
            +
            require 'logger'
         | 
| 334 | 
            +
            # => true
         | 
| 335 | 
            +
            logger = Logger.new(STDERR)
         | 
| 336 | 
            +
            # => #<Logger:...>
         | 
| 337 | 
            +
            notifier = Stoplight::Notifier::Logger.new(logger)
         | 
| 338 | 
            +
            # => #<Stoplight::Notifier::Logger:...>
         | 
| 339 | 
            +
            Stoplight::Light.default_notifiers += [notifier]
         | 
| 340 | 
            +
            # => [#<Stoplight::Notifier::IO:...>, #<Stoplight::Notifier::Logger:...>]
         | 
| 341 | 
            +
            ```
         | 
| 342 | 
            +
             | 
| 293 343 | 
             
            #### Slack
         | 
| 294 344 |  | 
| 295 | 
            -
            Make sure you have [the Slack gem][] installed before configuring | 
| 345 | 
            +
            Make sure you have [the Slack gem][] (`~> 1.3`) installed before configuring
         | 
| 346 | 
            +
            Stoplight.
         | 
| 296 347 |  | 
| 297 348 | 
             
            ``` rb
         | 
| 298 349 | 
             
            require 'slack-notifier'
         | 
| @@ -307,25 +358,25 @@ Stoplight::Light.default_notifiers += [notifier] | |
| 307 358 |  | 
| 308 359 | 
             
            ### Rails
         | 
| 309 360 |  | 
| 310 | 
            -
            Stoplight is designed to work seamlessly with Rails. If you want
         | 
| 311 | 
            -
             | 
| 312 | 
            -
             | 
| 313 | 
            -
             | 
| 361 | 
            +
            Stoplight is designed to work seamlessly with Rails. If you want to use the
         | 
| 362 | 
            +
            in-memory data store, you don't need to do anything special. If you want to use
         | 
| 363 | 
            +
            a persistent data store, you'll need to configure it. Create an initializer for
         | 
| 364 | 
            +
            Stoplight:
         | 
| 314 365 |  | 
| 315 366 | 
             
            ``` rb
         | 
| 316 367 | 
             
            # config/initializers/stoplight.rb
         | 
| 317 368 | 
             
            require 'stoplight'
         | 
| 318 369 | 
             
            Stoplight::Light.default_data_store = Stoplight::DataStore::Redis.new(...)
         | 
| 319 | 
            -
            Stoplight::Light.default_notifiers += [Stoplight::Notifier:: | 
| 370 | 
            +
            Stoplight::Light.default_notifiers += [Stoplight::Notifier::Logger.new(Rails.logger)]
         | 
| 320 371 | 
             
            ```
         | 
| 321 372 |  | 
| 322 373 | 
             
            ## Advanced usage
         | 
| 323 374 |  | 
| 324 375 | 
             
            ### Locking
         | 
| 325 376 |  | 
| 326 | 
            -
            Although stoplights can operate on their own, occasionally you may
         | 
| 327 | 
            -
             | 
| 328 | 
            -
             | 
| 377 | 
            +
            Although stoplights can operate on their own, occasionally you may want to
         | 
| 378 | 
            +
            override the default behavior. You can lock a light in either the green or red
         | 
| 379 | 
            +
            state using `set_state`.
         | 
| 329 380 |  | 
| 330 381 | 
             
            ``` rb
         | 
| 331 382 | 
             
            light = Stoplight('example-7') { true }
         | 
| @@ -338,12 +389,18 @@ light.run | |
| 338 389 | 
             
            # Stoplight::Error::RedLight: example-7
         | 
| 339 390 | 
             
            ```
         | 
| 340 391 |  | 
| 341 | 
            -
            **Code in locked red lights may still run under certain conditions!**
         | 
| 342 | 
            -
             | 
| 343 | 
            -
             | 
| 344 | 
            -
             | 
| 392 | 
            +
            **Code in locked red lights may still run under certain conditions!** If you
         | 
| 393 | 
            +
            have configured a custom data store and that data store fails, Stoplight will
         | 
| 394 | 
            +
            switch over to using a blank in-memory data store. That means you will lose the
         | 
| 395 | 
            +
            locked state of any stoplights.
         | 
| 396 | 
            +
             | 
| 397 | 
            +
            You can go back to using the default behavior by unlocking the stoplight.
         | 
| 398 | 
            +
             | 
| 399 | 
            +
            ``` rb
         | 
| 400 | 
            +
            light.data_store.set_state(light, Stoplight::State::UNLOCKED)
         | 
| 401 | 
            +
            ```
         | 
| 345 402 |  | 
| 346 | 
            -
             | 
| 403 | 
            +
            ### Testing
         | 
| 347 404 |  | 
| 348 405 | 
             
            Stoplights typically work as expected without modification in test suites.
         | 
| 349 406 | 
             
            However there are a few things you can do to make them behave better. If your
         | 
| @@ -393,7 +450,10 @@ Stoplight is licensed under [the MIT License][]. | |
| 393 450 | 
             
            [the notifiers section]: #notifiers
         | 
| 394 451 | 
             
            [the timeout section]: #custom-timeout
         | 
| 395 452 | 
             
            [the redis gem]: https://rubygems.org/gems/redis
         | 
| 453 | 
            +
            [the bugsnag gem]: https://rubygems.org/gems/bugsnag
         | 
| 396 454 | 
             
            [the hipchat gem]: https://rubygems.org/gems/hipchat
         | 
| 455 | 
            +
            [the honeybadger gem]: https://rubygems.org/gems/honeybadger
         | 
| 456 | 
            +
            [the logger class]: http://ruby-doc.org/stdlib-2.2.3/libdoc/logger/rdoc/Logger.html
         | 
| 397 457 | 
             
            [the slack gem]: https://rubygems.org/gems/slack-notifier
         | 
| 398 458 | 
             
            [@camdez]: https://github.com/camdez
         | 
| 399 459 | 
             
            [@tfausak]: https://github.com/tfausak
         | 
    
        data/lib/stoplight.rb
    CHANGED
    
    | @@ -18,8 +18,12 @@ require 'stoplight/data_store/redis' | |
| 18 18 | 
             
            require 'stoplight/notifier'
         | 
| 19 19 | 
             
            require 'stoplight/notifier/base'
         | 
| 20 20 | 
             
            require 'stoplight/notifier/generic'
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            require 'stoplight/notifier/bugsnag'
         | 
| 21 23 | 
             
            require 'stoplight/notifier/hip_chat'
         | 
| 24 | 
            +
            require 'stoplight/notifier/honeybadger'
         | 
| 22 25 | 
             
            require 'stoplight/notifier/io'
         | 
| 26 | 
            +
            require 'stoplight/notifier/logger'
         | 
| 23 27 | 
             
            require 'stoplight/notifier/slack'
         | 
| 24 28 |  | 
| 25 29 | 
             
            require 'stoplight/default'
         | 
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Stoplight
         | 
| 4 | 
            +
              module Notifier
         | 
| 5 | 
            +
                # @see Base
         | 
| 6 | 
            +
                class Bugsnag < Base
         | 
| 7 | 
            +
                  DEFAULT_OPTIONS = {
         | 
| 8 | 
            +
                    severity: 'info'
         | 
| 9 | 
            +
                  }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  StoplightStatusChange = Class.new(Error::Base)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  # @return [Proc]
         | 
| 14 | 
            +
                  attr_reader :formatter
         | 
| 15 | 
            +
                  # @return [::Bugsnag]
         | 
| 16 | 
            +
                  attr_reader :bugsnag
         | 
| 17 | 
            +
                  # @return [Hash{Symbol => Object}]
         | 
| 18 | 
            +
                  attr_reader :options
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  # @param bugsnag [::Bugsnag]
         | 
| 21 | 
            +
                  # @param formatter [Proc, nil]
         | 
| 22 | 
            +
                  # @param options [Hash{Symbol => Object}]
         | 
| 23 | 
            +
                  # @option options [String] :severity
         | 
| 24 | 
            +
                  def initialize(bugsnag, formatter = nil, options = {})
         | 
| 25 | 
            +
                    @bugsnag = bugsnag
         | 
| 26 | 
            +
                    @formatter = formatter || Default::FORMATTER
         | 
| 27 | 
            +
                    @options = DEFAULT_OPTIONS.merge(options)
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  def notify(light, from_color, to_color, error)
         | 
| 31 | 
            +
                    message = formatter.call(light, from_color, to_color, error)
         | 
| 32 | 
            +
                    bugsnag.notify(StoplightStatusChange.new(message), options)
         | 
| 33 | 
            +
                    message
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
            end
         | 
| @@ -0,0 +1,43 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Stoplight
         | 
| 4 | 
            +
              module Notifier
         | 
| 5 | 
            +
                # @see Base
         | 
| 6 | 
            +
                class Honeybadger < Base
         | 
| 7 | 
            +
                  DEFAULT_OPTIONS = {
         | 
| 8 | 
            +
                    parameters: {},
         | 
| 9 | 
            +
                    session: {},
         | 
| 10 | 
            +
                    context: {}
         | 
| 11 | 
            +
                  }.freeze
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  # @return [String]
         | 
| 14 | 
            +
                  attr_reader :api_key
         | 
| 15 | 
            +
                  # @return [Proc]
         | 
| 16 | 
            +
                  attr_reader :formatter
         | 
| 17 | 
            +
                  # @return [Hash{Symbol => Object}]
         | 
| 18 | 
            +
                  attr_reader :options
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  # @param api_key [String]
         | 
| 21 | 
            +
                  # @param formatter [Proc, nil]
         | 
| 22 | 
            +
                  # @param options [Hash{Symbol => Object}]
         | 
| 23 | 
            +
                  # @option options [Hash] :parameters
         | 
| 24 | 
            +
                  # @option options [Hash] :session
         | 
| 25 | 
            +
                  # @option options [Hash] :context
         | 
| 26 | 
            +
                  def initialize(api_key, formatter = nil, options = {})
         | 
| 27 | 
            +
                    @api_key = api_key
         | 
| 28 | 
            +
                    @formatter = formatter || Default::FORMATTER
         | 
| 29 | 
            +
                    @options = DEFAULT_OPTIONS.merge(options)
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def notify(light, from_color, to_color, error)
         | 
| 33 | 
            +
                    message = formatter.call(light, from_color, to_color, error)
         | 
| 34 | 
            +
                    h = options.merge(
         | 
| 35 | 
            +
                      api_key: api_key,
         | 
| 36 | 
            +
                      error_message: message,
         | 
| 37 | 
            +
                      backtrace: (error.backtrace if error))
         | 
| 38 | 
            +
                    ::Honeybadger.notify(h)
         | 
| 39 | 
            +
                    message
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
            end
         | 
    
        data/lib/stoplight/version.rb
    CHANGED
    
    
| @@ -0,0 +1,89 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'spec_helper'
         | 
| 4 | 
            +
            require 'bugsnag'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            RSpec.describe Stoplight::Notifier::Bugsnag do
         | 
| 7 | 
            +
              StoplightStatusChange = Stoplight::Notifier::Bugsnag::StoplightStatusChange
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              it 'is a class' do
         | 
| 10 | 
            +
                expect(described_class).to be_a(Class)
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              it 'is a subclass of Base' do
         | 
| 14 | 
            +
                expect(described_class).to be < Stoplight::Notifier::Base
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              describe '#formatter' do
         | 
| 18 | 
            +
                it 'is initially the default' do
         | 
| 19 | 
            +
                  expect(described_class.new(nil, nil).formatter)
         | 
| 20 | 
            +
                    .to eql(Stoplight::Default::FORMATTER)
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                it 'reads the formatter' do
         | 
| 24 | 
            +
                  formatter = proc {}
         | 
| 25 | 
            +
                  expect(described_class.new(nil, formatter).formatter)
         | 
| 26 | 
            +
                    .to eql(formatter)
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              describe '#options' do
         | 
| 31 | 
            +
                it 'is initially the default' do
         | 
| 32 | 
            +
                  expect(described_class.new(nil, nil).options)
         | 
| 33 | 
            +
                    .to eql(Stoplight::Notifier::Bugsnag::DEFAULT_OPTIONS)
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                it 'reads the options' do
         | 
| 37 | 
            +
                  options = { key: :value }
         | 
| 38 | 
            +
                  expect(described_class.new(nil, nil, options).options)
         | 
| 39 | 
            +
                    .to eql(Stoplight::Notifier::Bugsnag::DEFAULT_OPTIONS.merge(options))
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              describe '#bugsnag' do
         | 
| 44 | 
            +
                it 'reads the Bugsnag client' do
         | 
| 45 | 
            +
                  client = ::Bugsnag
         | 
| 46 | 
            +
                  expect(described_class.new(client, nil).bugsnag)
         | 
| 47 | 
            +
                    .to eql(client)
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              describe '#notify' do
         | 
| 52 | 
            +
                let(:light) { Stoplight::Light.new(name, &code) }
         | 
| 53 | 
            +
                let(:name) { ('a'..'z').to_a.shuffle.join }
         | 
| 54 | 
            +
                let(:code) { -> {} }
         | 
| 55 | 
            +
                let(:from_color) { Stoplight::Color::GREEN }
         | 
| 56 | 
            +
                let(:to_color) { Stoplight::Color::RED }
         | 
| 57 | 
            +
                let(:notifier) { described_class.new(bugsnag) }
         | 
| 58 | 
            +
                let(:bugsnag) { double(Bugsnag) }
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                subject(:result) do
         | 
| 61 | 
            +
                  notifier.notify(light, from_color, to_color, error)
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                before do
         | 
| 65 | 
            +
                  status_change = StoplightStatusChange.new(message)
         | 
| 66 | 
            +
                  expect(bugsnag).to receive(:notify).with(status_change, severity: 'info')
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                context 'when no error given' do
         | 
| 70 | 
            +
                  let(:error) { nil }
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                  it 'logs message' do
         | 
| 73 | 
            +
                    expect(result).to eq(message)
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                context 'when message with an error given' do
         | 
| 78 | 
            +
                  let(:error) { ZeroDivisionError.new('divided by 0') }
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  it 'logs message' do
         | 
| 81 | 
            +
                    expect(result).to eq(message)
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                def message
         | 
| 86 | 
            +
                  notifier.formatter.call(light, from_color, to_color, error)
         | 
| 87 | 
            +
                end
         | 
| 88 | 
            +
              end
         | 
| 89 | 
            +
            end
         | 
| @@ -0,0 +1,74 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            require 'honeybadger'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            RSpec.describe Stoplight::Notifier::Honeybadger do
         | 
| 5 | 
            +
              it 'is a class' do
         | 
| 6 | 
            +
                expect(described_class).to be_a(Class)
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              it 'is a subclass of Base' do
         | 
| 10 | 
            +
                expect(described_class).to be < Stoplight::Notifier::Base
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              describe '#formatter' do
         | 
| 14 | 
            +
                it 'is initially the default' do
         | 
| 15 | 
            +
                  expect(described_class.new(nil).formatter).to eql(
         | 
| 16 | 
            +
                    Stoplight::Default::FORMATTER)
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                it 'reads the formatter' do
         | 
| 20 | 
            +
                  formatter = proc {}
         | 
| 21 | 
            +
                  expect(described_class.new(nil, formatter).formatter).to eql(formatter)
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              describe '#options' do
         | 
| 26 | 
            +
                it 'is initially the default' do
         | 
| 27 | 
            +
                  expect(described_class.new(nil).options).to eql(
         | 
| 28 | 
            +
                    Stoplight::Notifier::Honeybadger::DEFAULT_OPTIONS)
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                it 'reads the options' do
         | 
| 32 | 
            +
                  options = { key: :value }
         | 
| 33 | 
            +
                  expect(described_class.new(nil, nil, options).options).to eql(
         | 
| 34 | 
            +
                    Stoplight::Notifier::Honeybadger::DEFAULT_OPTIONS.merge(options))
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              describe '#notify' do
         | 
| 39 | 
            +
                let(:light) { Stoplight::Light.new(name, &code) }
         | 
| 40 | 
            +
                let(:name) { ('a'..'z').to_a.shuffle.join }
         | 
| 41 | 
            +
                let(:code) { -> {} }
         | 
| 42 | 
            +
                let(:from_color) { Stoplight::Color::GREEN }
         | 
| 43 | 
            +
                let(:to_color) { Stoplight::Color::RED }
         | 
| 44 | 
            +
                let(:notifier) { described_class.new(api_key) }
         | 
| 45 | 
            +
                let(:api_key) { ('a'..'z').to_a.shuffle.join }
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                before do
         | 
| 48 | 
            +
                  allow(Honeybadger).to receive(:notify)
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                it 'returns the message' do
         | 
| 52 | 
            +
                  error = nil
         | 
| 53 | 
            +
                  message = notifier.formatter.call(light, from_color, to_color, error)
         | 
| 54 | 
            +
                  expect(notifier.notify(light, from_color, to_color, error)).to eql(
         | 
| 55 | 
            +
                    message)
         | 
| 56 | 
            +
                  expect(Honeybadger).to have_received(:notify).with(
         | 
| 57 | 
            +
                    hash_including(
         | 
| 58 | 
            +
                      api_key: api_key,
         | 
| 59 | 
            +
                      error_message: message))
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                it 'returns the message with an error' do
         | 
| 63 | 
            +
                  error = ZeroDivisionError.new('divided by 0')
         | 
| 64 | 
            +
                  message = notifier.formatter.call(light, from_color, to_color, error)
         | 
| 65 | 
            +
                  expect(notifier.notify(light, from_color, to_color, error)).to eql(
         | 
| 66 | 
            +
                    message)
         | 
| 67 | 
            +
                  expect(Honeybadger).to have_received(:notify).with(
         | 
| 68 | 
            +
                    hash_including(
         | 
| 69 | 
            +
                      api_key: api_key,
         | 
| 70 | 
            +
                      error_message: message,
         | 
| 71 | 
            +
                      backtrace: error.backtrace))
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
            end
         | 
| @@ -0,0 +1,70 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'spec_helper'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            RSpec.describe Stoplight::Notifier::Logger do
         | 
| 6 | 
            +
              it 'is a class' do
         | 
| 7 | 
            +
                expect(described_class).to be_a(Class)
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              it 'is a subclass of Base' do
         | 
| 11 | 
            +
                expect(described_class).to be < Stoplight::Notifier::Base
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              describe '#formatter' do
         | 
| 15 | 
            +
                it 'is initially the default' do
         | 
| 16 | 
            +
                  expect(described_class.new(nil, nil).formatter)
         | 
| 17 | 
            +
                    .to eql(Stoplight::Default::FORMATTER)
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                it 'reads the formatter' do
         | 
| 21 | 
            +
                  formatter = proc {}
         | 
| 22 | 
            +
                  expect(described_class.new(nil, formatter).formatter)
         | 
| 23 | 
            +
                    .to eql(formatter)
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              describe '#logger' do
         | 
| 28 | 
            +
                it 'reads the logger' do
         | 
| 29 | 
            +
                  logger = Logger.new(StringIO.new)
         | 
| 30 | 
            +
                  expect(described_class.new(logger, nil).logger)
         | 
| 31 | 
            +
                    .to eql(logger)
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              describe '#notify' do
         | 
| 36 | 
            +
                let(:light) { Stoplight::Light.new(name, &code) }
         | 
| 37 | 
            +
                let(:name) { ('a'..'z').to_a.shuffle.join }
         | 
| 38 | 
            +
                let(:code) { -> {} }
         | 
| 39 | 
            +
                let(:from_color) { Stoplight::Color::GREEN }
         | 
| 40 | 
            +
                let(:to_color) { Stoplight::Color::RED }
         | 
| 41 | 
            +
                let(:notifier) { described_class.new(Logger.new(io)) }
         | 
| 42 | 
            +
                let(:io) { StringIO.new }
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                before do
         | 
| 45 | 
            +
                  notifier.notify(light, from_color, to_color, error)
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                subject(:result) { io.string }
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                context 'when no error given' do
         | 
| 51 | 
            +
                  let(:error) { nil }
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  it 'logs message' do
         | 
| 54 | 
            +
                    expect(result).to match(/.+#{message}/)
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                context 'when message with an error given' do
         | 
| 59 | 
            +
                  let(:error) { ZeroDivisionError.new('divided by 0') }
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  it 'logs message' do
         | 
| 62 | 
            +
                    expect(result).to match(/.+#{message}/)
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                def message
         | 
| 67 | 
            +
                  notifier.formatter.call(light, from_color, to_color, error)
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
            end
         | 
    
        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. | 
| 4 | 
            +
              version: 1.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Cameron Desautels
         | 
| @@ -10,7 +10,7 @@ authors: | |
| 10 10 | 
             
            autorequire: 
         | 
| 11 11 | 
             
            bindir: bin
         | 
| 12 12 | 
             
            cert_chain: []
         | 
| 13 | 
            -
            date: 2015- | 
| 13 | 
            +
            date: 2015-09-11 00:00:00.000000000 Z
         | 
| 14 14 | 
             
            dependencies:
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 16 16 | 
             
              name: benchmark-ips
         | 
| @@ -18,14 +18,28 @@ dependencies: | |
| 18 18 | 
             
                requirements:
         | 
| 19 19 | 
             
                - - "~>"
         | 
| 20 20 | 
             
                  - !ruby/object:Gem::Version
         | 
| 21 | 
            -
                    version: '2. | 
| 21 | 
            +
                    version: '2.3'
         | 
| 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. | 
| 28 | 
            +
                    version: '2.3'
         | 
| 29 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 30 | 
            +
              name: bugsnag
         | 
| 31 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 32 | 
            +
                requirements:
         | 
| 33 | 
            +
                - - "~>"
         | 
| 34 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 35 | 
            +
                    version: '2.8'
         | 
| 36 | 
            +
              type: :development
         | 
| 37 | 
            +
              prerelease: false
         | 
| 38 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 39 | 
            +
                requirements:
         | 
| 40 | 
            +
                - - "~>"
         | 
| 41 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 42 | 
            +
                    version: '2.8'
         | 
| 29 43 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 30 44 | 
             
              name: coveralls
         | 
| 31 45 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -60,14 +74,14 @@ dependencies: | |
| 60 74 | 
             
                requirements:
         | 
| 61 75 | 
             
                - - "~>"
         | 
| 62 76 | 
             
                  - !ruby/object:Gem::Version
         | 
| 63 | 
            -
                    version: '2. | 
| 77 | 
            +
                    version: '2.13'
         | 
| 64 78 | 
             
              type: :development
         | 
| 65 79 | 
             
              prerelease: false
         | 
| 66 80 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 67 81 | 
             
                requirements:
         | 
| 68 82 | 
             
                - - "~>"
         | 
| 69 83 | 
             
                  - !ruby/object:Gem::Version
         | 
| 70 | 
            -
                    version: '2. | 
| 84 | 
            +
                    version: '2.13'
         | 
| 71 85 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 72 86 | 
             
              name: guard-rspec
         | 
| 73 87 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -110,6 +124,20 @@ dependencies: | |
| 110 124 | 
             
                - - "~>"
         | 
| 111 125 | 
             
                  - !ruby/object:Gem::Version
         | 
| 112 126 | 
             
                    version: '1.5'
         | 
| 127 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 128 | 
            +
              name: honeybadger
         | 
| 129 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 130 | 
            +
                requirements:
         | 
| 131 | 
            +
                - - "~>"
         | 
| 132 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 133 | 
            +
                    version: '2.1'
         | 
| 134 | 
            +
              type: :development
         | 
| 135 | 
            +
              prerelease: false
         | 
| 136 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 137 | 
            +
                requirements:
         | 
| 138 | 
            +
                - - "~>"
         | 
| 139 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 140 | 
            +
                    version: '2.1'
         | 
| 113 141 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 114 142 | 
             
              name: rake
         | 
| 115 143 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -158,42 +186,42 @@ dependencies: | |
| 158 186 | 
             
                requirements:
         | 
| 159 187 | 
             
                - - "~>"
         | 
| 160 188 | 
             
                  - !ruby/object:Gem::Version
         | 
| 161 | 
            -
                    version: '0. | 
| 189 | 
            +
                    version: '0.34'
         | 
| 162 190 | 
             
              type: :development
         | 
| 163 191 | 
             
              prerelease: false
         | 
| 164 192 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 165 193 | 
             
                requirements:
         | 
| 166 194 | 
             
                - - "~>"
         | 
| 167 195 | 
             
                  - !ruby/object:Gem::Version
         | 
| 168 | 
            -
                    version: '0. | 
| 196 | 
            +
                    version: '0.34'
         | 
| 169 197 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 170 198 | 
             
              name: slack-notifier
         | 
| 171 199 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 172 200 | 
             
                requirements:
         | 
| 173 201 | 
             
                - - "~>"
         | 
| 174 202 | 
             
                  - !ruby/object:Gem::Version
         | 
| 175 | 
            -
                    version: 1. | 
| 203 | 
            +
                    version: '1.3'
         | 
| 176 204 | 
             
              type: :development
         | 
| 177 205 | 
             
              prerelease: false
         | 
| 178 206 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 179 207 | 
             
                requirements:
         | 
| 180 208 | 
             
                - - "~>"
         | 
| 181 209 | 
             
                  - !ruby/object:Gem::Version
         | 
| 182 | 
            -
                    version: 1. | 
| 210 | 
            +
                    version: '1.3'
         | 
| 183 211 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 184 212 | 
             
              name: timecop
         | 
| 185 213 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 186 214 | 
             
                requirements:
         | 
| 187 215 | 
             
                - - "~>"
         | 
| 188 216 | 
             
                  - !ruby/object:Gem::Version
         | 
| 189 | 
            -
                    version: '0. | 
| 217 | 
            +
                    version: '0.8'
         | 
| 190 218 | 
             
              type: :development
         | 
| 191 219 | 
             
              prerelease: false
         | 
| 192 220 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 193 221 | 
             
                requirements:
         | 
| 194 222 | 
             
                - - "~>"
         | 
| 195 223 | 
             
                  - !ruby/object:Gem::Version
         | 
| 196 | 
            -
                    version: '0. | 
| 224 | 
            +
                    version: '0.8'
         | 
| 197 225 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 198 226 | 
             
              name: yard
         | 
| 199 227 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -233,9 +261,12 @@ files: | |
| 233 261 | 
             
            - lib/stoplight/light/runnable.rb
         | 
| 234 262 | 
             
            - lib/stoplight/notifier.rb
         | 
| 235 263 | 
             
            - lib/stoplight/notifier/base.rb
         | 
| 264 | 
            +
            - lib/stoplight/notifier/bugsnag.rb
         | 
| 236 265 | 
             
            - lib/stoplight/notifier/generic.rb
         | 
| 237 266 | 
             
            - lib/stoplight/notifier/hip_chat.rb
         | 
| 267 | 
            +
            - lib/stoplight/notifier/honeybadger.rb
         | 
| 238 268 | 
             
            - lib/stoplight/notifier/io.rb
         | 
| 269 | 
            +
            - lib/stoplight/notifier/logger.rb
         | 
| 239 270 | 
             
            - lib/stoplight/notifier/slack.rb
         | 
| 240 271 | 
             
            - lib/stoplight/state.rb
         | 
| 241 272 | 
             
            - lib/stoplight/version.rb
         | 
| @@ -251,9 +282,12 @@ files: | |
| 251 282 | 
             
            - spec/stoplight/light/runnable_spec.rb
         | 
| 252 283 | 
             
            - spec/stoplight/light_spec.rb
         | 
| 253 284 | 
             
            - spec/stoplight/notifier/base_spec.rb
         | 
| 285 | 
            +
            - spec/stoplight/notifier/bugsnag_spec.rb
         | 
| 254 286 | 
             
            - spec/stoplight/notifier/generic_spec.rb
         | 
| 255 287 | 
             
            - spec/stoplight/notifier/hip_chat_spec.rb
         | 
| 288 | 
            +
            - spec/stoplight/notifier/honeybadger_spec.rb
         | 
| 256 289 | 
             
            - spec/stoplight/notifier/io_spec.rb
         | 
| 290 | 
            +
            - spec/stoplight/notifier/logger_spec.rb
         | 
| 257 291 | 
             
            - spec/stoplight/notifier/slack_spec.rb
         | 
| 258 292 | 
             
            - spec/stoplight/notifier_spec.rb
         | 
| 259 293 | 
             
            - spec/stoplight/state_spec.rb
         | 
| @@ -296,9 +330,12 @@ test_files: | |
| 296 330 | 
             
            - spec/stoplight/light/runnable_spec.rb
         | 
| 297 331 | 
             
            - spec/stoplight/light_spec.rb
         | 
| 298 332 | 
             
            - spec/stoplight/notifier/base_spec.rb
         | 
| 333 | 
            +
            - spec/stoplight/notifier/bugsnag_spec.rb
         | 
| 299 334 | 
             
            - spec/stoplight/notifier/generic_spec.rb
         | 
| 300 335 | 
             
            - spec/stoplight/notifier/hip_chat_spec.rb
         | 
| 336 | 
            +
            - spec/stoplight/notifier/honeybadger_spec.rb
         | 
| 301 337 | 
             
            - spec/stoplight/notifier/io_spec.rb
         | 
| 338 | 
            +
            - spec/stoplight/notifier/logger_spec.rb
         | 
| 302 339 | 
             
            - spec/stoplight/notifier/slack_spec.rb
         | 
| 303 340 | 
             
            - spec/stoplight/notifier_spec.rb
         | 
| 304 341 | 
             
            - spec/stoplight/state_spec.rb
         |