stoplight 5.0.2 → 5.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
  SHA256:
3
- metadata.gz: 33957e89681161b7eee07f1ea96544341f0be3b988a53609829450f13a5840e9
4
- data.tar.gz: cdad58020fe3e1e85b2705cc6d0b1fc733b994717860c911dfab0c9a375b074d
3
+ metadata.gz: 2fba85e77b2b2c6569592f463080da2bca787dc65f12da00bf566b4bb7e56912
4
+ data.tar.gz: 4aaac27c0747de8a550575ecd8a93cc2391f3a73c008c543ee049db6f7fd01b7
5
5
  SHA512:
6
- metadata.gz: e97d13c334f95e586dd561ad3ba3c2a5e7c3f37ef830efca794e1bde280f8f22ebbf3baa02efc61f0978dde42d9d6551aafdef6d1d35f8d2589d7d18c46b84ca
7
- data.tar.gz: e0841a8040fc194c1b271f0dad0550200ea1bc73982545d7143e77c5e4eb867d6b4f9d94d1f5e292833ce1cd3091a6839bfc66b6a62d78ea73468735c6f09ead
6
+ metadata.gz: acc5305b5da510feacb9584a60a6043eb4c7c7280bbf6f3d6c77db968a445aa45fcfaaaf41027684ff9dc7f4ebf615b1f27e0d53315eda932126b6c47b5ca514
7
+ data.tar.gz: 1ce0b8d4fea66779d6688c52a871ac10568184f796fc3d51a08c9d6fb45e2402b59da077cbcdd049b1dcdc9e2e748ebdde9ebd327b28aa810190b6bf8d17049c
data/README.md CHANGED
@@ -128,18 +128,23 @@ receives `nil`. In both cases, the return value of the fallback becomes the retu
128
128
 
129
129
  Stoplight goes with a built-in Admin Panel that can track all active Lights and manually lock them in the desired state (`Green` or `Red`). Locking lights in certain states might be helpful in scenarios like E2E testing.
130
130
 
131
- To add Admin Panel to your Rails project, add this configuration to your `config/routes.rb` file.
131
+ To add Admin Panel protected by basic authentication to your Rails project, add this configuration to your `config/routes.rb` file.
132
132
 
133
133
  ```ruby
134
134
  Rails.application.routes.draw do
135
135
  # ...
136
136
 
137
+ Stoplight::Admin.use(Rack::Auth::Basic) do |username, password|
138
+ username == ENV["STOPLIGHT_ADMIN_USERNAME"] && password == ENV["STOPLIGHT_ADMIN_PASSWORD"]
139
+ end
137
140
  mount Stoplight::Admin => '/stoplights'
138
141
 
139
142
  # ...
140
143
  end
141
144
  ```
142
145
 
146
+ Then set up `STOPLIGHT_ADMIN_USERNAME` and `STOPLIGHT_ADMIN_PASSWORD` env variables to access your Admin panel.
147
+
143
148
  **IMPORTANT:** Stoplight Admin Panel requires you to have `sinatra` and `sinatra-contrib` gems installed. You can either add them to your Gemfile:
144
149
 
145
150
  ```ruby
@@ -158,13 +163,13 @@ gem install sinatra-contrib
158
163
  It is possible to run the Admin Panel separately from your application using the `stoplight-admin:<release-version>` docker image.
159
164
 
160
165
  ```shell
161
- docker run --net=host stoplight-admin:v5
166
+ docker run --net=host bolshakov/stoplight-admin
162
167
  ```
163
168
 
164
169
  **IMPORTANT:** Standalone Admin Panel should use the same Redis your application uses. To achieve this, set the `REDIS_URL` ENV variable via `-e REDIS_URL=<url-to-your-redis-servier>.` E.g.:
165
170
 
166
171
  ```shell
167
- docker run -e REDIS_URL=redis://localhost:6378 --net=host stoplight-admin:v5
172
+ docker run -e REDIS_URL=redis://localhost:6378 --net=host bolshakov/stoplight-admin
168
173
  ```
169
174
 
170
175
 
@@ -384,6 +389,12 @@ Stoplight.configure do |config|
384
389
  end
385
390
  ```
386
391
 
392
+ You can generate initializer with Redis, Admin Panel route and add needed gems to your Gemfile:
393
+
394
+ ```sh
395
+ rails generate stoplight:install --with-admin-panel
396
+ ```
397
+
387
398
  ## Testing
388
399
 
389
400
  Tips for working with Stoplight in test environments:
@@ -416,6 +427,12 @@ Stoplight supports the latest three minor versions of Ruby, which currently are:
416
427
  the minimum supported Ruby version is not considered a breaking change. We support the current stable Redis
417
428
  version (`7.4.x`) and the latest release of the previous major version (`6.2.x`)
418
429
 
430
+ ## Development
431
+
432
+ After checking out the repo, run `bundle install` to install dependencies. Run tests with `bundle exec rspec` and check
433
+ code style with `bundle exec standardrb`. We follow a git flow branching strategy - see our [Git Flow wiki page] for
434
+ details on branch naming, releases, and contribution workflow.
435
+
419
436
  ## Credits
420
437
 
421
438
  Stoplight was originally created by [camdez][] and [tfausak][]. It is currently maintained by [bolshakov][] and
@@ -444,3 +461,4 @@ Fowler’s [CircuitBreaker][] article.
444
461
  [complete list of contributors]: https://github.com/bolshakov/stoplight/graphs/contributors
445
462
  [CircuitBreaker]: http://martinfowler.com/bliki/CircuitBreaker.html
446
463
  [Redis]: https://redis.io/
464
+ [Git Flow wiki page]: https://github.com/bolshakov/stoplight/wiki/Git-Flow
@@ -0,0 +1,16 @@
1
+ Description:
2
+ Generates stoplight initializer to setup Stoplight Redis configuration
3
+ and optionally sets up Admin panel
4
+
5
+ Examples:
6
+ rails generate stoplight:install
7
+
8
+ This will generate "config/initializers/stoplight.rb" initializer with basic config
9
+ Then you should adjust Redis config there.
10
+
11
+ rails generate stoplight:install --with-admin-panel
12
+
13
+ This generated all needed requirements to set up Stoplight Admin Panel:
14
+ * It generates initializer "config/initializers/stoplight.rb" with Redis configuration
15
+ * It injects your "config/routes.rb" with route with basic authentication to Stoplight Admin panel
16
+ * It injects your Gemfile with needed dependencies ('redis', 'sinatra' and 'sinatra-contrib')
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "rails/generators"
5
+ rescue LoadError
6
+ raise <<~WARN
7
+ Currently generators are only available for Rails applications
8
+ WARN
9
+ end
10
+
11
+ module Stoplight
12
+ module Generators
13
+ class InstallGenerator < ::Rails::Generators::Base # :nodoc:
14
+ source_root File.expand_path("templates", __dir__)
15
+
16
+ class_option :with_admin_panel, type: :boolean, optional: true,
17
+ desc: "Define whether to set up admin panel"
18
+
19
+ ROUTES_PATH = "config/routes.rb"
20
+ STOPLIGHT_CONFIG_TEMPLATE = "stoplight.rb.erb"
21
+ INITIALIZERS_PATH = "config/initializers"
22
+ AFTER_INSTALL_NOTIFICATION = <<~TEXT
23
+ \nThank you for using stoplight!
24
+ Now to finish configuration:
25
+ * Run `bundle` from the project root to install new gems
26
+ * Go to 'config/initializers/stoplight.rb' to set up connection to Redis.\n
27
+ TEXT
28
+
29
+ STOPLIGHT_ADMIN_ROUTE = <<-RUBY
30
+ mount Stoplight::Admin => '/stoplights'
31
+ RUBY
32
+
33
+ STOPLIGHT_AUTH = <<-RUBY
34
+ Stoplight::Admin.use(Rack::Auth::Basic) do |username, password|
35
+ username == ENV["STOPLIGHT_ADMIN_USERNAME"] && password == ENV["STOPLIGHT_ADMIN_PASSWORD"]
36
+ end
37
+ RUBY
38
+
39
+ def generate_redis_gem
40
+ if options[:with_admin_panel]
41
+ conf = "\ngem 'redis'"
42
+ inject_into_file "Gemfile", conf
43
+ end
44
+ end
45
+
46
+ def generate_sinatra_deps
47
+ if options[:with_admin_panel]
48
+ conf = <<~RUBY
49
+ gem 'sinatra', require: false
50
+ gem 'sinatra-contrib', require: false
51
+ RUBY
52
+
53
+ inject_into_file "Gemfile", "\n#{conf}"
54
+ end
55
+ end
56
+
57
+ def generate_initializer
58
+ initializer_template = STOPLIGHT_CONFIG_TEMPLATE
59
+ copy_file initializer_template, "#{INITIALIZERS_PATH}/stoplight.rb"
60
+ end
61
+
62
+ def generate_admin_panel
63
+ if options[:with_admin_panel]
64
+ route_config = "#{STOPLIGHT_AUTH}#{STOPLIGHT_ADMIN_ROUTE}\n"
65
+
66
+ inject_into_file ROUTES_PATH, route_config, after: ".application.routes.draw do\n"
67
+ end
68
+ end
69
+
70
+ def redis_configuration_notification
71
+ print AFTER_INSTALL_NOTIFICATION
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "redis"
4
+
5
+ # Set up your project-specific Redis setup here
6
+ # One of the simplest configurations would be configuring Redis via url
7
+ # Example:
8
+ # redis = Redis.new(url: ENV["REDIS_URL"])
9
+ # REDIS_URL usually looks like this
10
+ # "redis://<username>:<password>@<server ip address>:<port>/<redis db>"
11
+ # Example:
12
+ # "redis://admin:p4ssw0rd@10.0.1.1:6380/15"
13
+ redis = Redis.new
14
+ data_store = Stoplight::DataStore::Redis.new(redis)
15
+
16
+ Stoplight.configure do |config|
17
+ config.data_store = data_store
18
+ end
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  begin
4
- require "sinatra"
5
- require "sinatra/contrib"
6
4
  require "sinatra/base"
5
+ require "sinatra/contrib"
7
6
  require "sinatra/json"
8
7
  rescue LoadError
9
8
  raise <<~WARN
@@ -10,6 +10,8 @@ module Stoplight
10
10
  # 4. **Library-Level Default Settings**: Default settings defined in the +Stoplight::Config::UserDefaultConfig+ module.
11
11
  #
12
12
  # The settings are merged in this order, with higher-precedence settings overriding lower-precedence ones.
13
+ # After merging settings, the configuration transformations are applied such as wrapping data stores and notifiers
14
+ # with fail-safe mechanism, type conversion, etc. Each transformation must be idempotent.
13
15
  #
14
16
  # @api private
15
17
  class ConfigProvider
@@ -38,13 +40,28 @@ module Stoplight
38
40
  # @see +Stoplight()+
39
41
  # @return [Stoplight::Light::Config] The configuration for the specified light.
40
42
  # @raise [Error::ConfigurationError]
41
- def provide(light_name, **settings_overrides)
43
+ def provide(light_name, settings_overrides = {})
42
44
  raise Error::ConfigurationError, <<~ERROR if settings_overrides.has_key?(:name)
43
45
  The +name+ setting cannot be overridden in the configuration.
44
46
  ERROR
45
47
 
46
48
  settings = default_settings.merge(settings_overrides, {name: light_name})
47
- Light::Config.new(**settings)
49
+ Light::Config.new(**transform_settings(settings))
50
+ end
51
+
52
+ # Creates a configuration from a given +Stoplight::Light::Config+ object extending it
53
+ # with additional settings overrides.
54
+ #
55
+ # @param config [Stoplight::Light::Config] The configuration object to extend.
56
+ # @param settings_overrides [Hash] The settings to override.
57
+ # @return [Stoplight::Light::Config] The new extended configuration object.
58
+ def from_prototype(config, settings_overrides)
59
+ config.to_h.then do |settings|
60
+ current_name = settings.delete(:name)
61
+ name = settings_overrides.delete(:name) || current_name
62
+
63
+ provide(name, **settings.merge(settings_overrides))
64
+ end
48
65
  end
49
66
 
50
67
  def inspect
@@ -57,6 +74,38 @@ module Stoplight
57
74
  "data_store=#{default_settings[:data_store].class.name}" \
58
75
  ">"
59
76
  end
77
+
78
+ private
79
+
80
+ def transform_settings(settings)
81
+ settings.merge(
82
+ data_store: build_data_store(settings.fetch(:data_store)),
83
+ notifiers: build_notifiers(settings.fetch(:notifiers)),
84
+ tracked_errors: build_tracked_errors(settings.fetch(:tracked_errors)),
85
+ skipped_errors: build_skipped_errors(settings.fetch(:skipped_errors)),
86
+ cool_off_time: build_cool_off_time(settings.fetch(:cool_off_time))
87
+ )
88
+ end
89
+
90
+ def build_data_store(data_store)
91
+ DataStore::FailSafe.wrap(data_store)
92
+ end
93
+
94
+ def build_notifiers(notifiers)
95
+ notifiers.map { |notifier| Notifier::FailSafe.wrap(notifier) }
96
+ end
97
+
98
+ def build_tracked_errors(tracked_error)
99
+ Array(tracked_error)
100
+ end
101
+
102
+ def build_skipped_errors(skipped_errors)
103
+ Array(skipped_errors)
104
+ end
105
+
106
+ def build_cool_off_time(cool_off_time)
107
+ cool_off_time.to_i
108
+ end
60
109
  end
61
110
  end
62
111
  end
@@ -20,9 +20,9 @@ module Stoplight
20
20
  # @return [Proc, nil] The default error notifier (callable object).
21
21
  attr_writer :error_notifier
22
22
 
23
- # @!attribute [r] notifiers
23
+ # @!attribute [rw] notifiers
24
24
  # @return [Array<Stoplight::Notifier::Base>] The default list of notifiers.
25
- attr_reader :notifiers
25
+ attr_accessor :notifiers
26
26
 
27
27
  # @!attribute [w] threshold
28
28
  # @return [Integer, nil] The default failure threshold to trip the circuit breaker.
@@ -40,24 +40,16 @@ module Stoplight
40
40
  # @return [Array<Class>, nil] The default list of errors to skip.
41
41
  attr_writer :skipped_errors
42
42
 
43
+ # @!attribute [w] data_store
44
+ # @return [Stoplight::DataStore::Base] The default data store instance.
45
+ attr_writer :data_store
46
+
43
47
  def initialize
44
48
  # This allows users appending notifiers to the default list,
45
49
  # while still allowing them to override the default list.
46
50
  @notifiers = Default::NOTIFIERS
47
51
  end
48
52
 
49
- # @param value [Stoplight::DataStore::Base]
50
- # @return [Stoplight::DataStore::Base] The default data store instance.
51
- def data_store=(value)
52
- @data_store = DataStore::FailSafe.wrap(value)
53
- end
54
-
55
- # @param value [Array<Stoplight::Notifier::Base>]
56
- # @return [Array<Stoplight::Notifier::FailSafe>]
57
- def notifiers=(value)
58
- @notifiers = value.map { |notifier| Notifier::FailSafe.wrap(notifier) }
59
- end
60
-
61
53
  # Converts the user-defined configuration to a hash.
62
54
  #
63
55
  # @return [Hash] A hash representation of the configuration, excluding nil values.
@@ -67,7 +59,7 @@ module Stoplight
67
59
  cool_off_time: @cool_off_time,
68
60
  data_store: @data_store,
69
61
  error_notifier: @error_notifier,
70
- notifiers: (@notifiers == Default::NOTIFIERS) ? nil : @notifiers, # This is to avoid conflicts with legacy config
62
+ notifiers: @notifiers,
71
63
  threshold: @threshold,
72
64
  window_size: @window_size,
73
65
  tracked_errors: @tracked_errors,
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "securerandom"
4
+
3
5
  module Stoplight
4
6
  module DataStore
5
7
  # A wrapper around a data store that provides fail-safe mechanisms using a
@@ -14,9 +14,7 @@ module Stoplight
14
14
  words.join(" ")
15
15
  end
16
16
 
17
- NOTIFIERS = [
18
- Notifier::FailSafe.wrap(Notifier::IO.new($stderr))
19
- ].freeze
17
+ NOTIFIERS = [Notifier::IO.new($stderr)].freeze
20
18
 
21
19
  THRESHOLD = 3
22
20
 
@@ -3,85 +3,56 @@
3
3
  module Stoplight
4
4
  class Light
5
5
  # A +Stoplight::Light+ configuration object.
6
+ #
7
+ # # @!attribute [r] name
8
+ # @return [String]
9
+ #
10
+ # @!attribute [r] cool_off_time
11
+ # @return [Numeric]
12
+ #
13
+ # @!attribute [r] data_store
14
+ # @return [Stoplight::DataStore::Base]
15
+ #
16
+ # @!attribute [r] error_notifier
17
+ # @return [StandardError => void]
18
+ #
19
+ # @!attribute [r] notifiers
20
+ # @return [Array<Stoplight::Notifier::Base>]
21
+ #
22
+ # @!attribute [r] threshold
23
+ # @return [Numeric]
24
+ #
25
+ # @!attribute [r] window_size
26
+ # @return [Numeric]
27
+ #
28
+ # @!attribute [r] tracked_errors
29
+ # @return [Array<StandardError>]
30
+ #
31
+ # @!attribute [r] skipped_errors
32
+ # @return [Array<Exception>]
33
+ #
34
+ # @!attribute [r] traffic_control
35
+ # @return [Stoplight::TrafficControl::Base]
36
+ #
37
+ # @!attribute [r] traffic_recovery
38
+ # @return [Stoplight::TrafficRecovery::Base]
6
39
  # @api private
7
- class Config
8
- # @!attribute [r] name
9
- # @return [String]
10
- attr_reader :name
11
-
12
- # @!attribute [r] cool_off_time
13
- # @return [Numeric]
14
- attr_reader :cool_off_time
15
-
16
- # @!attribute [r] data_store
17
- # @return [Stoplight::DataStore::Base]
18
- attr_reader :data_store
19
-
20
- # @!attribute [r] error_notifier
21
- # @return [StandardError => void]
22
- attr_reader :error_notifier
23
-
24
- # @!attribute [r] notifiers
25
- # @return [Array<Stoplight::Notifier::Base>]
26
- attr_reader :notifiers
27
-
28
- # @!attribute [r] threshold
29
- # @return [Numeric]
30
- attr_reader :threshold
31
-
32
- # @!attribute [r] window_size
33
- # @return [Numeric]
34
- attr_reader :window_size
35
-
36
- # @!attribute [r] tracked_errors
37
- # @return [Array<StandardError>]
38
- attr_reader :tracked_errors
39
-
40
- # @!attribute [r] skipped_errors
41
- # @return [Array<Exception>]
42
- attr_reader :skipped_errors
43
-
44
- # @!attribute [r] traffic_control
45
- # @return [Stoplight::TrafficControl::Base]
46
- attr_reader :traffic_control
47
-
48
- # @!attribute [r] traffic_recovery
49
- # @return [Stoplight::TrafficRecovery::Base]
50
- attr_reader :traffic_recovery
51
-
52
- # @param name [String]
53
- # @param cool_off_time [Numeric]
54
- # @param data_store [Stoplight::DataStore::Base]
55
- # @param error_notifier [Proc]
56
- # @param notifiers [Array<Stoplight::Notifier::Base>]
57
- # @param threshold [Numeric]
58
- # @param window_size [Numeric]
59
- # @param tracked_errors [Array<StandardError>]
60
- # @param skipped_errors [Array<Exception>]
61
- # @param traffic_control [Stoplight::TrafficControl::Base]
62
- # @param traffic_recovery [Stoplight::TrafficRecovery::Base]
63
- def initialize(name:, cool_off_time:, data_store:, error_notifier:, notifiers:, threshold:, window_size:,
64
- tracked_errors:, skipped_errors:, traffic_control:, traffic_recovery:)
65
- @name = name
66
- @cool_off_time = cool_off_time.to_i
67
- @data_store = DataStore::FailSafe.wrap(data_store)
68
- @error_notifier = error_notifier
69
- @notifiers = notifiers.map { |notifier| Notifier::FailSafe.wrap(notifier) }
70
- @threshold = threshold
71
- @window_size = window_size
72
- @tracked_errors = Array(tracked_errors)
73
- @skipped_errors = Array(skipped_errors)
74
- @traffic_control = traffic_control
75
- @traffic_recovery = traffic_recovery
76
- end
77
-
78
- # @param other [any]
79
- # @return [Boolean]
80
- def ==(other)
81
- other.is_a?(self.class) && to_h == other.to_h
82
- end
83
-
84
- # @param error [Exception]
40
+ Config = Data.define(
41
+ :name,
42
+ :cool_off_time,
43
+ :data_store,
44
+ :error_notifier,
45
+ :notifiers,
46
+ :threshold,
47
+ :window_size,
48
+ :tracked_errors,
49
+ :skipped_errors,
50
+ :traffic_control,
51
+ :traffic_recovery
52
+ ) do
53
+ # Checks if the given error should be tracked
54
+ #
55
+ # @param error [#==] The error to check, e.g. an Exception, Class or Proc
85
56
  # @return [Boolean]
86
57
  def track_error?(error)
87
58
  skip = skipped_errors.any? { |klass| klass === error }
@@ -89,30 +60,6 @@ module Stoplight
89
60
 
90
61
  !skip && track
91
62
  end
92
-
93
- # Updates the configuration with new settings and returns a new instance.
94
- #
95
- # @return [Stoplight::Light::Config]
96
- def with(**settings)
97
- self.class.new(**to_h.merge(settings))
98
- end
99
-
100
- # @return [Hash]
101
- def to_h
102
- {
103
- cool_off_time:,
104
- data_store:,
105
- error_notifier:,
106
- name:,
107
- notifiers:,
108
- threshold:,
109
- window_size:,
110
- tracked_errors:,
111
- skipped_errors:,
112
- traffic_control:,
113
- traffic_recovery:
114
- }
115
- end
116
63
  end
117
64
  end
118
65
  end
@@ -150,7 +150,9 @@ module Stoplight
150
150
  # payment_light.run(->(error) { nil }) { call_payment_api }
151
151
  # @see +Stoplight()+
152
152
  def with(**settings)
153
- reconfigure(config.with(**settings))
153
+ reconfigure(
154
+ Stoplight.config_provider.from_prototype(config, settings)
155
+ )
154
156
  end
155
157
 
156
158
  private
@@ -30,6 +30,12 @@ module Stoplight
30
30
  def stop_traffic?(config, metadata)
31
31
  raise NotImplementedError
32
32
  end
33
+
34
+ # @param other [any]
35
+ # @return [Boolean]
36
+ def ==(other)
37
+ other.is_a?(self.class)
38
+ end
33
39
  end
34
40
  end
35
41
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Stoplight
4
- VERSION = Gem::Version.new("5.0.2")
4
+ VERSION = Gem::Version.new("5.1.0")
5
5
  end
data/lib/stoplight.rb CHANGED
@@ -9,6 +9,7 @@ loader.do_not_eager_load(
9
9
  "#{__dir__}/stoplight/admin",
10
10
  "#{__dir__}/stoplight/admin.rb"
11
11
  )
12
+ loader.ignore("#{__dir__}/generators")
12
13
  loader.ignore("#{__dir__}/stoplight/rspec.rb", "#{__dir__}/stoplight/rspec")
13
14
  loader.setup
14
15
 
@@ -26,7 +27,7 @@ module Stoplight # rubocop:disable Style/Documentation
26
27
  # It raises an error if called more than once.
27
28
  #
28
29
  # @yield [config] Provides a configuration object to the block.
29
- # @yieldparam config [Stoplight::Config::ProgrammaticConfig] The configuration object.
30
+ # @yieldparam config [Stoplight::Config::UserDefaultConfig] The configuration object.
30
31
  # @raise [Stoplight::Error::ConfigurationError] If the library is already configured.
31
32
  # @return [void]
32
33
  #
@@ -118,6 +119,6 @@ end
118
119
  # light = Stoplight("Payment API", skipped_errors: [ActiveRecord::RecordNotFound])
119
120
  #
120
121
  def Stoplight(name, **settings) # rubocop:disable Naming/MethodName
121
- config = Stoplight.config_provider.provide(name, **settings)
122
+ config = Stoplight.config_provider.provide(name, settings)
122
123
  Stoplight::Light.new(config)
123
124
  end
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stoplight
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.2
4
+ version: 5.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cameron Desautels
8
8
  - Taylor Fausak
9
9
  - Justin Steffy
10
+ autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2025-06-22 00:00:00.000000000 Z
13
+ date: 2025-06-27 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: zeitwerk
@@ -37,6 +38,9 @@ files:
37
38
  - CHANGELOG.md
38
39
  - LICENSE.md
39
40
  - README.md
41
+ - lib/generators/stoplight/install/USAGE
42
+ - lib/generators/stoplight/install/install_generator.rb
43
+ - lib/generators/stoplight/install/templates/stoplight.rb.erb
40
44
  - lib/stoplight.rb
41
45
  - lib/stoplight/admin.rb
42
46
  - lib/stoplight/admin/actions/action.rb
@@ -98,6 +102,7 @@ homepage: https://github.com/bolshakov/stoplight
98
102
  licenses:
99
103
  - MIT
100
104
  metadata: {}
105
+ post_install_message:
101
106
  rdoc_options: []
102
107
  require_paths:
103
108
  - lib
@@ -112,7 +117,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
117
  - !ruby/object:Gem::Version
113
118
  version: '0'
114
119
  requirements: []
115
- rubygems_version: 3.6.5
120
+ rubygems_version: 3.4.19
121
+ signing_key:
116
122
  specification_version: 4
117
123
  summary: Traffic control for code.
118
124
  test_files: []