unleash 3.2.0 → 3.2.4

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: 8800b993fafadb56ff81782ccad56be4fa863d81133cde10486e5c38577ed21e
4
- data.tar.gz: 194b63447aee5b7d6e12594d770ec7ffc693db4fcd3914907594b1074a7f46a5
3
+ metadata.gz: 2cf913a6af33742c1001e328f96a5382eb0666b99280d008d6960e105681ded2
4
+ data.tar.gz: e6cbc6db182f1212e4580e8781b7ac6444b12f26116dc922a4568d728299399a
5
5
  SHA512:
6
- metadata.gz: fa279122da638dba368039dc22ce101236f511ed8471a937daa8f934d180da7e3a3f709ce8869e6157c56d898c403137dd03edc450fffec2c2f1c1d2e0034da2
7
- data.tar.gz: f35cd2146020c38866360ff044596a6f1858847711ee8ee4b2d98b4d5d6b61e47f547895cf273cc4d49b9f9120eb60f68888197790d4a4deed5fadcd927d503a
6
+ metadata.gz: b6499b2f136c8dcf6b7f115b29ad762a336a3e8eac669f4f87577f542242cc9a2cdcb41b36101d9483111217274afc6e07a01d3217393fc7fcd76854866fd74d
7
+ data.tar.gz: e3d5d385c49552035aa9700db64ccb44320e3265cb415d03f9a1d135ab09d126bb10bb0834b72e3b9d7fec4a5340f612d63024e7259ca85d0024684eedd6230f
data/.gitignore CHANGED
@@ -7,6 +7,7 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ /vendor
10
11
 
11
12
  # rspec failure tracking
12
13
  .rspec_status
data/.rubocop.yml CHANGED
@@ -1,12 +1,15 @@
1
1
  # inherit_from: .rubocop_todo.yml
2
2
 
3
+ AllCops:
4
+ TargetRubyVersion: 2.5
5
+
3
6
  Naming/PredicateName:
4
- NameWhitelist:
7
+ AllowedMethods:
5
8
  - is_enabled?
6
9
 
7
10
  Metrics/ClassLength:
8
11
  Max: 120
9
- Metrics/LineLength:
12
+ Layout/LineLength:
10
13
  Max: 140
11
14
  Metrics/MethodLength:
12
15
  Max: 20
@@ -19,9 +22,9 @@ Metrics/BlockLength:
19
22
  Metrics/AbcSize:
20
23
  Max: 25
21
24
  Metrics/CyclomaticComplexity:
22
- Max: 8
25
+ Max: 9
23
26
  Metrics/PerceivedComplexity:
24
- Max: 8
27
+ Max: 9
25
28
 
26
29
  Style/Documentation:
27
30
  Enabled: false
@@ -42,9 +45,12 @@ Style/FrozenStringLiteralComment:
42
45
  Style/GuardClause:
43
46
  MinBodyLength: 8
44
47
 
45
- Style/BracesAroundHashParameters:
46
- Exclude:
47
- - 'spec/**/*.rb'
48
+ Style/HashEachMethods:
49
+ Enabled: true
50
+ Style/HashTransformKeys:
51
+ Enabled: true
52
+ Style/HashTransformValues:
53
+ Enabled: true
48
54
 
49
55
  Style/IfInsideElse:
50
56
  Exclude:
data/.travis.yml CHANGED
@@ -2,14 +2,13 @@ sudo: false
2
2
  language: ruby
3
3
  rvm:
4
4
  - jruby
5
+ - 3.0
5
6
  - 2.7
6
7
  - 2.6
7
8
  - 2.5
8
- - 2.4
9
9
  before_install:
10
- - gem install bundler -v 2.0.2
11
- - git clone --depth 5 --branch v3.2.0 https://github.com/Unleash/client-specification.git
12
- client-specification
10
+ - gem install bundler -v 2.1.4
11
+ - git clone --depth 5 --branch v3.3.0 https://github.com/Unleash/client-specification.git client-specification
13
12
 
14
13
  notifications:
15
14
  slack:
data/README.md CHANGED
@@ -10,10 +10,10 @@ Leverage the [Unleash Server](https://github.com/Unleash/unleash) for powerful f
10
10
 
11
11
  ## Supported Ruby Interpreters
12
12
 
13
+ * MRI 3.0
13
14
  * MRI 2.7
14
15
  * MRI 2.6
15
16
  * MRI 2.5
16
- * MRI 2.4
17
17
  * jruby
18
18
 
19
19
  ## Installation
@@ -21,7 +21,7 @@ Leverage the [Unleash Server](https://github.com/Unleash/unleash) for powerful f
21
21
  Add this line to your application's Gemfile:
22
22
 
23
23
  ```ruby
24
- gem 'unleash', '~> 3.2.0'
24
+ gem 'unleash', '~> 3.2.4'
25
25
  ```
26
26
 
27
27
  And then execute:
@@ -66,7 +66,7 @@ Argument | Description | Required? | Type | Default Value|
66
66
  `disable_metrics` | Disables sending metrics to Unleash server. | N | Boolean | `false` |
67
67
  `custom_http_headers` | Custom headers to send to Unleash. | N | Hash | {} |
68
68
  `timeout` | How long to wait for the connection to be established or wait in reading state (open_timeout/read_timeout) | N | Integer | 30 |
69
- `retry_limit` | How many consecutive failures in connecting to the Unleash server are allowed before giving up. | N | Integer | 1 |
69
+ `retry_limit` | How many consecutive failures in connecting to the Unleash server are allowed before giving up. Use `Float::INFINITY` if you would like it to never give up. | N | Numeric | 5 |
70
70
  `backup_file` | Filename to store the last known state from the Unleash server. Best to not change this from the default. | N | String | `Dir.tmpdir + "/unleash-#{app_name}-repo.json` |
71
71
  `logger` | Specify a custom `Logger` class to handle logs for the Unleash client. | N | Class | `Logger.new(STDOUT)` |
72
72
  `log_level` | Change the log level for the `Logger` class. Constant from `Logger::Severity`. | N | Constant | `Logger::ERROR` |
data/examples/simple.rb CHANGED
@@ -17,13 +17,13 @@ puts ">> START simple.rb"
17
17
  # or:
18
18
 
19
19
  @unleash = Unleash::Client.new(
20
- url: 'http://unleash.herokuapp.com/api',
20
+ url: 'https://app.unleash-hosted.com/demo/api',
21
21
  app_name: 'simple-test',
22
22
  instance_id: 'local-test-cli',
23
23
  refresh_interval: 2,
24
24
  metrics_interval: 2,
25
25
  retry_limit: 2,
26
- log_level: Logger::DEBUG
26
+ custom_http_headers: {'Authorization': '943ca9171e2c884c545c5d82417a655fb77cec970cc3b78a8ff87f4406b495d0'},
27
27
  )
28
28
 
29
29
  # feature_name = "AwesomeFeature"
@@ -1,16 +1,29 @@
1
1
  module Unleash
2
2
  class ActivationStrategy
3
- attr_accessor :name, :params
3
+ attr_accessor :name, :params, :constraints
4
4
 
5
- def initialize(name, params)
5
+ def initialize(name, params, constraints = [])
6
6
  self.name = name
7
7
 
8
8
  if params.is_a?(Hash)
9
9
  self.params = params
10
+ elsif params.nil?
11
+ self.params = {}
10
12
  else
11
- Unleash.logger.warn "Invalid params provided for ActivationStrategy #{params}"
13
+ Unleash.logger.warn "Invalid params provided for ActivationStrategy (params:#{params})"
12
14
  self.params = {}
13
15
  end
16
+
17
+ if constraints.is_a?(Array) && constraints.each{ |c| c.is_a?(Constraint) }
18
+ self.constraints = constraints
19
+ else
20
+ Unleash.logger.warn "Invalid constraints provided for ActivationStrategy (contraints: #{constraints})"
21
+ self.constraints = []
22
+ end
23
+ end
24
+
25
+ def matches_context?(context)
26
+ self.constraints.any?{ |c| c.matches_context? context }
14
27
  end
15
28
  end
16
29
  end
@@ -60,7 +60,7 @@ module Unleash
60
60
  Unleash.logger.debug "Unleash::Client.get_variant for feature: #{feature} with context #{context}"
61
61
 
62
62
  if Unleash.configuration.disable_client
63
- Unleash.logger.debug "unleash_client is disabled! Always returning #{default_variant} for feature #{feature}!"
63
+ Unleash.logger.debug "unleash_client is disabled! Always returning #{fallback_variant} for feature #{feature}!"
64
64
  return fallback_variant || Unleash::FeatureToggle.disabled_variant
65
65
  end
66
66
 
@@ -116,7 +116,11 @@ module Unleash
116
116
 
117
117
  def start_toggle_fetcher
118
118
  Unleash.toggle_fetcher = Unleash::ToggleFetcher.new
119
- self.fetcher_scheduled_executor = Unleash::ScheduledExecutor.new('ToggleFetcher', Unleash.configuration.refresh_interval)
119
+ self.fetcher_scheduled_executor = Unleash::ScheduledExecutor.new(
120
+ 'ToggleFetcher',
121
+ Unleash.configuration.refresh_interval,
122
+ Unleash.configuration.retry_limit
123
+ )
120
124
  self.fetcher_scheduled_executor.run do
121
125
  Unleash.toggle_fetcher.fetch
122
126
  end
@@ -125,7 +129,11 @@ module Unleash
125
129
  def start_metrics
126
130
  Unleash.toggle_metrics = Unleash::Metrics.new
127
131
  Unleash.reporter = Unleash::MetricsReporter.new
128
- self.metrics_scheduled_executor = Unleash::ScheduledExecutor.new('MetricsReporter', Unleash.configuration.metrics_interval)
132
+ self.metrics_scheduled_executor = Unleash::ScheduledExecutor.new(
133
+ 'MetricsReporter',
134
+ Unleash.configuration.metrics_interval,
135
+ Unleash.configuration.retry_limit
136
+ )
129
137
  self.metrics_scheduled_executor.run do
130
138
  Unleash.reporter.send
131
139
  end
@@ -0,0 +1,26 @@
1
+ module Unleash
2
+ class Constraint
3
+ attr_accessor :context_name, :operator, :values
4
+
5
+ VALID_OPERATORS = ['IN', 'NOT_IN'].freeze
6
+
7
+ def initialize(context_name, operator, values = [])
8
+ raise ArgumentError, "context_name is not a String" unless context_name.is_a?(String)
9
+ raise ArgumentError, "operator does not hold a valid value:" + VALID_OPERATORS unless VALID_OPERATORS.include? operator
10
+ raise ArgumentError, "values does not hold an Array" unless values.is_a?(Array)
11
+
12
+ self.context_name = context_name
13
+ self.operator = operator
14
+ self.values = values
15
+ end
16
+
17
+ def matches_context?(context)
18
+ Unleash.logger.debug "Unleash::Constraint matches_context? values: #{self.values} context.get_by_name(#{self.context_name})" \
19
+ " #{context.get_by_name(self.context_name)} "
20
+
21
+ is_included = self.values.include? context.get_by_name(self.context_name)
22
+
23
+ operator == 'IN' ? is_included : !is_included
24
+ end
25
+ end
26
+ end
@@ -1,6 +1,8 @@
1
1
  module Unleash
2
2
  class Context
3
- attr_accessor :app_name, :environment, :user_id, :session_id, :remote_address, :properties
3
+ ATTRS = [:app_name, :environment, :user_id, :session_id, :remote_address].freeze
4
+
5
+ attr_accessor(*[ATTRS, :properties].flatten)
4
6
 
5
7
  def initialize(params = {})
6
8
  raise ArgumentError, "Unleash::Context must be initialized with a hash." unless params.is_a?(Hash)
@@ -12,18 +14,29 @@ module Unleash
12
14
  self.remote_address = value_for('remoteAddress', params)
13
15
 
14
16
  properties = value_for('properties', params)
15
- self.properties = properties.is_a?(Hash) ? properties : {}
17
+ self.properties = properties.is_a?(Hash) ? properties.transform_keys(&:to_sym) : {}
16
18
  end
17
19
 
18
20
  def to_s
19
- "<Context: user_id=#{self.user_id},session_id=#{self.session_id},remote_address=#{self.remote_address},properties=#{self.properties}>"
21
+ "<Context: user_id=#{@user_id},session_id=#{@session_id},remote_address=#{@remote_address},properties=#{@properties}" \
22
+ ",app_name=#{@app_name},environment=#{@environment}>"
23
+ end
24
+
25
+ def get_by_name(name)
26
+ normalized_name = underscore(name).to_sym
27
+
28
+ if ATTRS.include? normalized_name
29
+ self.send(normalized_name)
30
+ else
31
+ self.properties.fetch(normalized_name)
32
+ end
20
33
  end
21
34
 
22
35
  private
23
36
 
24
37
  # Method to fetch values from hash for two types of keys: string in camelCase and symbol in snake_case
25
- def value_for(key, params, default_value = '')
26
- params.values_at(key, underscore(key).to_sym).compact.first || default_value
38
+ def value_for(key, params, default_value = nil)
39
+ params.values_at(key, key.to_sym, underscore(key), underscore(key).to_sym).compact.first || default_value
27
40
  end
28
41
 
29
42
  # converts CamelCase to snake_case
@@ -1,4 +1,5 @@
1
1
  require 'unleash/activation_strategy'
2
+ require 'unleash/constraint'
2
3
  require 'unleash/variant_definition'
3
4
  require 'unleash/variant'
4
5
  require 'unleash/strategy/util'
@@ -13,20 +14,9 @@ module Unleash
13
14
 
14
15
  self.name = params.fetch('name', nil)
15
16
  self.enabled = params.fetch('enabled', false)
16
- self.strategies = params.fetch('strategies', [])
17
- .select{ |s| s.has_key?('name') && Unleash::STRATEGIES.has_key?(s['name'].to_sym) }
18
- .map{ |s| ActivationStrategy.new(s['name'], s['parameters'] || {}) } || []
19
17
 
20
- self.variant_definitions = (params.fetch('variants', []) || [])
21
- .select{ |v| v.is_a?(Hash) && v.has_key?('name') }
22
- .map do |v|
23
- VariantDefinition.new(
24
- v.fetch('name', ''),
25
- v.fetch('weight', 0),
26
- v.fetch('payload', nil),
27
- v.fetch('overrides', [])
28
- )
29
- end || []
18
+ self.strategies = initialize_strategies(params)
19
+ self.variant_definitions = initialize_variant_definitions(params)
30
20
  end
31
21
 
32
22
  def to_s
@@ -64,23 +54,29 @@ module Unleash
64
54
  result =
65
55
  if self.enabled
66
56
  self.strategies.empty? ||
67
- self.strategies.any?{ |s| strategy_enabled?(s, context) }
57
+ self.strategies.any? do |s|
58
+ strategy_enabled?(s, context) && strategy_constraint_matches?(s, context)
59
+ end
68
60
  else
69
61
  default_result
70
62
  end
71
63
 
72
- Unleash.logger.debug "FeatureToggle (enabled:#{self.enabled} default_result:#{default_result} " \
73
- "and Strategies combined returned #{result})"
64
+ Unleash.logger.debug "Unleash::FeatureToggle (enabled:#{self.enabled} default_result:#{default_result} " \
65
+ "and Strategies combined with contraints returned #{result})"
74
66
 
75
67
  result
76
68
  end
77
69
 
78
70
  def strategy_enabled?(strategy, context)
79
71
  r = Unleash::STRATEGIES.fetch(strategy.name.to_sym, :unknown).is_enabled?(strategy.params, context)
80
- Unleash.logger.debug "Strategy #{strategy.name} returned #{r} with context: #{context}" # "for params #{strategy.params} "
72
+ Unleash.logger.debug "Unleash::FeatureToggle.strategy_enabled? Strategy #{strategy.name} returned #{r} with context: #{context}"
81
73
  r
82
74
  end
83
75
 
76
+ def strategy_constraint_matches?(strategy, context)
77
+ strategy.constraints.empty? || strategy.constraints.all?{ |c| c.matches_context?(context) }
78
+ end
79
+
84
80
  def disabled_variant
85
81
  Unleash::Variant.new(name: 'disabled', enabled: false)
86
82
  end
@@ -127,5 +123,36 @@ module Unleash
127
123
  end
128
124
  context
129
125
  end
126
+
127
+ def initialize_strategies(params)
128
+ params.fetch('strategies', [])
129
+ .select{ |s| s.has_key?('name') && Unleash::STRATEGIES.has_key?(s['name'].to_sym) }
130
+ .map do |s|
131
+ ActivationStrategy.new(
132
+ s['name'],
133
+ s['parameters'],
134
+ (s['constraints'] || []).map do |c|
135
+ Constraint.new(
136
+ c.fetch('contextName'),
137
+ c.fetch('operator'),
138
+ c.fetch('values')
139
+ )
140
+ end
141
+ )
142
+ end || []
143
+ end
144
+
145
+ def initialize_variant_definitions(params)
146
+ (params.fetch('variants', []) || [])
147
+ .select{ |v| v.is_a?(Hash) && v.has_key?('name') }
148
+ .map do |v|
149
+ VariantDefinition.new(
150
+ v.fetch('name', ''),
151
+ v.fetch('weight', 0),
152
+ v.fetch('payload', nil),
153
+ v.fetch('overrides', [])
154
+ )
155
+ end || []
156
+ end
130
157
  end
131
158
  end
@@ -0,0 +1,55 @@
1
+ require 'unleash/strategy/util'
2
+
3
+ module Unleash
4
+ module Strategy
5
+ class FlexibleRollout < Base
6
+ def name
7
+ 'flexibleRollout'
8
+ end
9
+
10
+ # need: params['percentage']
11
+ def is_enabled?(params = {}, context = nil)
12
+ return false unless params.is_a?(Hash)
13
+ return false unless context.class.name == 'Unleash::Context'
14
+
15
+ stickiness = params.fetch('stickiness', 'default')
16
+ stickiness_id = resolve_stickiness(stickiness, context)
17
+
18
+ begin
19
+ percentage = Integer(params.fetch('rollout', 0))
20
+ percentage = 0 if percentage > 100 || percentage.negative?
21
+ rescue ArgumentError
22
+ return false
23
+ end
24
+
25
+ group_id = params.fetch('groupId', '')
26
+ normalized_number = Util.get_normalized_number(stickiness_id, group_id)
27
+
28
+ return false if stickiness_id.nil?
29
+
30
+ (percentage.positive? && normalized_number <= percentage)
31
+ end
32
+
33
+ private
34
+
35
+ def random
36
+ Random.rand(0..100)
37
+ end
38
+
39
+ def resolve_stickiness(stickiness, context)
40
+ case stickiness
41
+ when 'userId'
42
+ context.user_id
43
+ when 'sessionId'
44
+ context.session_id
45
+ when 'random'
46
+ random
47
+ when 'default'
48
+ context.user_id || context.session_id || random
49
+ else
50
+ nil
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -11,7 +11,7 @@ module Unleash
11
11
  def is_enabled?(params = {}, context = nil)
12
12
  return false unless params.is_a?(Hash) && params.has_key?('percentage')
13
13
  return false unless context.class.name == 'Unleash::Context'
14
- return false if context.session_id.empty?
14
+ return false if context.session_id.nil? || context.session_id.empty?
15
15
 
16
16
  percentage = Integer(params['percentage'] || 0)
17
17
  (percentage.positive? && Util.get_normalized_number(context.session_id, params['groupId'] || "") <= percentage)
@@ -8,10 +8,10 @@ module Unleash
8
8
  end
9
9
 
10
10
  # need: params['percentage'], params['groupId'], context.user_id,
11
- def is_enabled?(params = {}, context = nil)
11
+ def is_enabled?(params = {}, context = nil, _constraints = [])
12
12
  return false unless params.is_a?(Hash) && params.has_key?('percentage')
13
13
  return false unless context.class.name == 'Unleash::Context'
14
- return false if context.user_id.empty?
14
+ return false if context.user_id.nil? || context.user_id.empty?
15
15
 
16
16
  percentage = Integer(params['percentage'] || 0)
17
17
  (percentage.positive? && Util.get_normalized_number(context.user_id, params['groupId'] || "") <= percentage)
@@ -48,7 +48,7 @@ module Unleash
48
48
  self.etag = response['ETag']
49
49
  response_hash = JSON.parse(response.body)
50
50
 
51
- if response_hash['version'] == 1
51
+ if response_hash['version'] >= 1
52
52
  features = response_hash['features']
53
53
  else
54
54
  raise NotImplemented, "Version of features provided by unleash server" \
@@ -71,6 +71,7 @@ module Unleash
71
71
  self.toggle_lock.synchronize do
72
72
  file = File.open(backup_file_tmp, "w")
73
73
  file.write(self.toggle_cache.to_json)
74
+ file.close
74
75
  File.rename(backup_file_tmp, backup_file)
75
76
  end
76
77
  rescue StandardError => e
@@ -1,3 +1,3 @@
1
1
  module Unleash
2
- VERSION = "3.2.0".freeze
2
+ VERSION = "3.2.4".freeze
3
3
  end
data/lib/unleash.rb CHANGED
@@ -5,7 +5,7 @@ require 'unleash/context'
5
5
  require 'unleash/client'
6
6
  require 'logger'
7
7
 
8
- Gem.find_files('unleash/strategy/**/*.rb').each{ |path| require path }
8
+ Gem.find_files('unleash/strategy/**/*.rb').each{ |path| require path unless path.end_with? '_spec.rb' }
9
9
 
10
10
  module Unleash
11
11
  TIME_RESOLUTION = 3
@@ -21,16 +21,16 @@ Gem::Specification.new do |spec|
21
21
  spec.bindir = 'bin'
22
22
  spec.executables = spec.files.grep(%r{^bin/unleash}) { |f| File.basename(f) }
23
23
  spec.require_paths = ["lib"]
24
- spec.required_ruby_version = "~> 2.4"
24
+ spec.required_ruby_version = ">= 2.5"
25
25
 
26
26
  spec.add_dependency "murmurhash3", "~> 0.1.6"
27
27
 
28
- spec.add_development_dependency "bundler", "~> 2.0"
29
- spec.add_development_dependency "rake", "~> 10.0"
30
- spec.add_development_dependency "rspec", "~> 3.0"
31
- spec.add_development_dependency "rspec-json_expectations", "~> 2.1"
32
- spec.add_development_dependency "webmock", "~> 3.0"
28
+ spec.add_development_dependency "bundler", "~> 2.1"
29
+ spec.add_development_dependency "rake", "~> 12.3"
30
+ spec.add_development_dependency "rspec", "~> 3.9"
31
+ spec.add_development_dependency "rspec-json_expectations", "~> 2.2"
32
+ spec.add_development_dependency "webmock", "~> 3.8"
33
33
 
34
34
  spec.add_development_dependency "coveralls", "~> 0.8"
35
- spec.add_development_dependency "rubocop", "~> 0.72"
35
+ spec.add_development_dependency "rubocop", "~> 0.80"
36
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unleash
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 3.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Renato Arruda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-20 00:00:00.000000000 Z
11
+ date: 2021-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: murmurhash3
@@ -30,70 +30,70 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.0'
33
+ version: '2.1'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.0'
40
+ version: '2.1'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: '12.3'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: '12.3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '3.0'
61
+ version: '3.9'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '3.0'
68
+ version: '3.9'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec-json_expectations
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '2.1'
75
+ version: '2.2'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '2.1'
82
+ version: '2.2'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: webmock
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '3.0'
89
+ version: '3.8'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '3.0'
96
+ version: '3.8'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: coveralls
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -114,14 +114,14 @@ dependencies:
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0.72'
117
+ version: '0.80'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0.72'
124
+ version: '0.80'
125
125
  description: |-
126
126
  This is the ruby client for Unleash, a powerful feature toggle system
127
127
  that gives you a great overview over all feature toggles across all your applications and services.
@@ -148,6 +148,7 @@ files:
148
148
  - lib/unleash/activation_strategy.rb
149
149
  - lib/unleash/client.rb
150
150
  - lib/unleash/configuration.rb
151
+ - lib/unleash/constraint.rb
151
152
  - lib/unleash/context.rb
152
153
  - lib/unleash/feature_toggle.rb
153
154
  - lib/unleash/metrics.rb
@@ -156,6 +157,7 @@ files:
156
157
  - lib/unleash/strategy/application_hostname.rb
157
158
  - lib/unleash/strategy/base.rb
158
159
  - lib/unleash/strategy/default.rb
160
+ - lib/unleash/strategy/flexible_rollout.rb
159
161
  - lib/unleash/strategy/gradual_rollout_random.rb
160
162
  - lib/unleash/strategy/gradual_rollout_sessionid.rb
161
163
  - lib/unleash/strategy/gradual_rollout_userid.rb
@@ -179,16 +181,16 @@ require_paths:
179
181
  - lib
180
182
  required_ruby_version: !ruby/object:Gem::Requirement
181
183
  requirements:
182
- - - "~>"
184
+ - - ">="
183
185
  - !ruby/object:Gem::Version
184
- version: '2.4'
186
+ version: '2.5'
185
187
  required_rubygems_version: !ruby/object:Gem::Requirement
186
188
  requirements:
187
189
  - - ">="
188
190
  - !ruby/object:Gem::Version
189
191
  version: '0'
190
192
  requirements: []
191
- rubygems_version: 3.1.2
193
+ rubygems_version: 3.2.3
192
194
  signing_key:
193
195
  specification_version: 4
194
196
  summary: Unleash feature toggle client.