unleash 4.5.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b823e18f3a0768928856433b11674d37ea62cc7f2b8b15786920488aba5c063c
4
- data.tar.gz: 6c8ec27517214b441c711d2f0069c211492ce3185bf4f1741c7b07077a28b088
3
+ metadata.gz: 46123d78efc7bf615f2ccf84d20087a6680b7999fed0e4b4e22014b044b7d455
4
+ data.tar.gz: 9992d9a6da906ab49b7ab5cfb9b8521c3f8bdd849ac76099153157debe3a989b
5
5
  SHA512:
6
- metadata.gz: a324e1902ae4e3885a206531e25d6138db8e39fb50b946471d0dcce3aec1ce595c2743b79ad3519af7cb80e83a284428d16bb2f3385313f889938f2ded80feef
7
- data.tar.gz: b89d72bb1b7a0fdd6ba65fe92ab1909ec5b02742d6e2d2447d047ed0d3325efe29e0e0f033ad4ff0ad12e80041a2a8697b64e366dd185077953be59073c8e801
6
+ metadata.gz: 49a49172df9366a14e26ae3d5486347fd9bf0cab8b154139bceb642a5f586ac2e01b617c4756c8e64a48a96d7f93605e686d98092ba86cd1db5bcb4e24142641
7
+ data.tar.gz: eb53f5f237afe96847ac14cc9af19a4d517c63e874cc829c957bf729e80cdf05f5d251393d918e36ccedc1e15ad0e8933923b5561674126c518a6322ea0956ad
@@ -50,7 +50,7 @@ jobs:
50
50
  - name: Install dependencies
51
51
  run: bundle install
52
52
  - name: Download test cases
53
- run: git clone --depth 5 --branch v4.3.1 https://github.com/Unleash/client-specification.git client-specification
53
+ run: git clone --depth 5 --branch v5.0.2 https://github.com/Unleash/client-specification.git client-specification
54
54
  - name: Run tests
55
55
  run: bundle exec rake
56
56
  env:
data/.rubocop.yml CHANGED
@@ -13,6 +13,8 @@ Metrics/ClassLength:
13
13
  Max: 135
14
14
  CountAsOne:
15
15
  - 'method_call'
16
+ Exclude:
17
+ - 'lib/unleash/feature_toggle.rb'
16
18
  Layout/LineLength:
17
19
  Max: 140
18
20
  Metrics/MethodLength:
data/CHANGELOG.md CHANGED
@@ -13,6 +13,17 @@ Note: These changes are not considered notable:
13
13
 
14
14
  ## [Unreleased]
15
15
 
16
+ ## [5.0.0] - 2023-10-30
17
+ ### Added
18
+ - change seed for variantutils to ensure fair distribution (#160)
19
+ - client specification is [here](https://github.com/Unleash/client-specification/tree/v5.0.2/specifications)
20
+ - A new seed is introduced to ensure a fair distribution for variants, addressing the issue of skewed variant distribution due to using the same hash string for both gradual rollout and variant allocation.
21
+
22
+ ## [4.6.0] - 2023-10-16
23
+ ### Added
24
+ - dependant toggles (#155)
25
+ - client specification is [here](https://github.com/Unleash/client-specification/pull/63)
26
+
16
27
  ## [4.5.0] - 2023-07-05
17
28
  ### Added
18
29
  - variants in strategies (#148)
data/README.md CHANGED
@@ -25,7 +25,7 @@ Leverage the [Unleash Server](https://github.com/Unleash/unleash) for powerful f
25
25
  Add this line to your application's Gemfile:
26
26
 
27
27
  ```ruby
28
- gem 'unleash', '~> 4.5.0'
28
+ gem 'unleash', '~> 5.0.0'
29
29
  ```
30
30
 
31
31
  And then execute:
@@ -528,7 +528,7 @@ You can also run `bin/console` for an interactive prompt that will allow you to
528
528
  This SDK is also built against the Unleash Client Specification tests.
529
529
  To run the Ruby SDK against this test suite, you'll need to have a copy on your machine, you can clone the repository directly using:
530
530
 
531
- `git clone --depth 5 --branch v4.3.1 https://github.com/Unleash/client-specification.git client-specification`
531
+ `git clone --depth 5 --branch v5.0.2 https://github.com/Unleash/client-specification.git client-specification`
532
532
 
533
533
  After doing this, `rake spec` will also run the client specification tests.
534
534
 
@@ -539,7 +539,7 @@ To install this gem onto your local machine, run `bundle exec rake install`.
539
539
  Choose a new version number following [Semantic Versioning](https://semver.org/spec/v2.0.0.html) semantics and then:
540
540
 
541
541
  - update the version number in [./lib/unleash/version.rb](./lib/unleash/version.rb),
542
- - if a major or minor version bump, update the [Installation section](#Installation) in [README.md](README.md)
542
+ - if a major or minor version bump, update the [Installation section](#installation) in [README.md](README.md)
543
543
  - update [CHANGELOG.md](CHANGELOG.md) following the format on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
544
544
  - commit with message `chore: bump version to x.y.z`
545
545
  - then run `bundle exec rake release`
@@ -555,3 +555,5 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/unleas
555
555
  Be sure to run both `bundle exec rspec` and `bundle exec rubocop` in your branch before creating a pull request.
556
556
 
557
557
  Please include tests with any pull requests, to avoid regressions.
558
+
559
+ Check out our guide for more information on how to build and scale [feature flag systems](https://docs.getunleash.io/topics/feature-flags/feature-flag-best-practices)
@@ -41,7 +41,6 @@ module Unleash
41
41
  end
42
42
 
43
43
  toggle_as_hash = Unleash&.toggles&.select{ |toggle| toggle['name'] == feature }&.first
44
-
45
44
  if toggle_as_hash.nil?
46
45
  Unleash.logger.debug "Unleash::Client.is_enabled? feature: #{feature} not found"
47
46
  return default_value
@@ -53,7 +53,7 @@ module Unleash
53
53
  {
54
54
  'UNLEASH-INSTANCEID' => self.instance_id,
55
55
  'UNLEASH-APPNAME' => self.app_name,
56
- 'Unleash-Client-Spec' => '4.2.2'
56
+ 'Unleash-Client-Spec' => '5.0.2'
57
57
  }.merge!(generate_custom_http_headers)
58
58
  end
59
59
 
@@ -107,7 +107,7 @@ module Unleash
107
107
  context_value = context.get_by_name(self.context_name)
108
108
 
109
109
  v.map!(&:upcase) if self.case_insensitive
110
- context_value.upcase! if self.case_insensitive
110
+ context_value = context_value.upcase if self.case_insensitive
111
111
 
112
112
  OPERATORS[self.operator].call(context_value, v)
113
113
  end
@@ -7,7 +7,7 @@ require 'securerandom'
7
7
 
8
8
  module Unleash
9
9
  class FeatureToggle
10
- attr_accessor :name, :enabled, :strategies, :variant_definitions
10
+ attr_accessor :name, :enabled, :dependencies, :strategies, :variant_definitions
11
11
 
12
12
  FeatureEvaluationResult = Struct.new(:enabled?, :strategy)
13
13
 
@@ -16,6 +16,7 @@ module Unleash
16
16
 
17
17
  self.name = params.fetch('name', nil)
18
18
  self.enabled = params.fetch('enabled', false)
19
+ self.dependencies = params.fetch('dependencies', [])
19
20
 
20
21
  self.strategies = initialize_strategies(params, segment_map)
21
22
  self.variant_definitions = initialize_variant_definitions(params)
@@ -41,11 +42,11 @@ module Unleash
41
42
 
42
43
  evaluation_result = evaluate(context)
43
44
 
44
- group_id = evaluation_result[:strategy]&.params.to_h['groupId'] || self.name
45
+ group_id = evaluation_result.strategy&.params.to_h['groupId'] || self.name
45
46
 
46
47
  variant = resolve_variant(context, evaluation_result, group_id)
47
48
 
48
- choice = evaluation_result[:enabled?] ? :yes : :no
49
+ choice = evaluation_result.enabled? ? :yes : :no
49
50
  Unleash.toggle_metrics.increment_variant(self.name, choice, variant.name) unless Unleash.configuration.disable_metrics
50
51
  variant
51
52
  end
@@ -57,9 +58,9 @@ module Unleash
57
58
  private
58
59
 
59
60
  def resolve_variant(context, evaluation_result, group_id)
60
- variant_definitions = evaluation_result[:strategy]&.variant_definitions
61
+ variant_definitions = evaluation_result.strategy&.variant_definitions
61
62
  variant_definitions = self.variant_definitions if variant_definitions.nil? || variant_definitions.empty?
62
- return Unleash::FeatureToggle.disabled_variant unless evaluation_result[:enabled?]
63
+ return Unleash::FeatureToggle.disabled_variant unless evaluation_result.enabled?
63
64
  return Unleash::FeatureToggle.disabled_variant if sum_variant_defs_weights(variant_definitions) <= 0
64
65
 
65
66
  variant_from_override_match(context, variant_definitions) ||
@@ -72,12 +73,42 @@ module Unleash
72
73
 
73
74
  # only check if it is enabled, do not do metrics
74
75
  def am_enabled?(context)
75
- evaluate(context)[:enabled?]
76
+ evaluate(context).enabled?
77
+ end
78
+
79
+ def parent_dependencies_satisfied?(context)
80
+ dependencies.empty? || dependencies.all?{ |parent| evaluate_parent(parent, context) }
81
+ end
82
+
83
+ def evaluate_parent(parent, context)
84
+ parent_toggle = get_parent(parent["feature"])
85
+ return false if parent_toggle.nil? || !parent_toggle.dependencies.empty?
86
+
87
+ evaluation_result = parent_toggle.is_enabled?(context)
88
+ return !evaluation_result if parent["enabled"] == false
89
+
90
+ return false unless evaluation_result
91
+
92
+ return evaluation_result if parent["variants"].nil? || parent["variants"].empty?
93
+
94
+ parent["variants"].include?(parent_toggle.get_variant(context).name)
95
+ end
96
+
97
+ def get_parent(feature)
98
+ toggle_as_hash = Unleash&.toggles&.find{ |toggle| toggle['name'] == feature }
99
+ if toggle_as_hash.nil?
100
+ Unleash.logger.debug "Unleash::Client.is_enabled? feature: #{feature} not found"
101
+ return nil
102
+ end
103
+
104
+ Unleash::FeatureToggle.new(toggle_as_hash, Unleash&.segment_cache)
76
105
  end
77
106
 
78
107
  def evaluate(context)
79
108
  evaluation_result =
80
- if !self.enabled
109
+ if !parent_dependencies_satisfied?(context)
110
+ FeatureEvaluationResult.new(false, nil)
111
+ elsif !self.enabled
81
112
  FeatureEvaluationResult.new(false, nil)
82
113
  elsif self.strategies.empty?
83
114
  FeatureEvaluationResult.new(true, nil)
@@ -86,9 +117,8 @@ module Unleash
86
117
  FeatureEvaluationResult.new(!strategy.nil?, strategy)
87
118
  end
88
119
 
89
- Unleash.logger.debug "Unleash::FeatureToggle (enabled:#{self.enabled} " \
90
- "and Strategies combined with contraints returned #{evaluation_result})"
91
-
120
+ Unleash.logger.debug "Unleash::FeatureToggle (enabled:#{self.enabled}) " \
121
+ "and Strategies combined with constraints returned #{evaluation_result})"
92
122
  evaluation_result
93
123
  end
94
124
 
@@ -133,6 +163,7 @@ module Unleash
133
163
  variant_weight = Unleash::Strategy::Util.get_normalized_number(
134
164
  variant_salt(context, stickiness),
135
165
  group_id,
166
+ Unleash::Strategy::Util::VARIANT_NORMALIZER_SEED,
136
167
  sum_variant_defs_weights(variant_definitions)
137
168
  )
138
169
  prev_weights = 0
@@ -24,7 +24,7 @@ module Unleash
24
24
  end
25
25
 
26
26
  group_id = params.fetch('groupId', '')
27
- normalized_number = Util.get_normalized_number(stickiness_id, group_id)
27
+ normalized_number = Util.get_normalized_number(stickiness_id, group_id, 0)
28
28
 
29
29
  return false if stickiness_id.nil?
30
30
 
@@ -14,7 +14,7 @@ module Unleash
14
14
  return false if context.session_id.nil? || context.session_id.empty?
15
15
 
16
16
  percentage = Integer(params['percentage'] || 0)
17
- (percentage.positive? && Util.get_normalized_number(context.session_id, params['groupId'] || "") <= percentage)
17
+ (percentage.positive? && Util.get_normalized_number(context.session_id, params['groupId'] || "", 0) <= percentage)
18
18
  end
19
19
  end
20
20
  end
@@ -14,7 +14,7 @@ module Unleash
14
14
  return false if context.user_id.nil? || context.user_id.empty?
15
15
 
16
16
  percentage = Integer(params['percentage'] || 0)
17
- (percentage.positive? && Util.get_normalized_number(context.user_id, params['groupId'] || "") <= percentage)
17
+ (percentage.positive? && Util.get_normalized_number(context.user_id, params['groupId'] || "", 0) <= percentage)
18
18
  end
19
19
  end
20
20
  end
@@ -6,10 +6,11 @@ module Unleash
6
6
  module_function
7
7
 
8
8
  NORMALIZER = 100
9
+ VARIANT_NORMALIZER_SEED = 86_028_157
9
10
 
10
11
  # convert the two strings () into a number between 1 and base (100 by default)
11
- def get_normalized_number(identifier, group_id, base = NORMALIZER)
12
- MurmurHash3::V32.str_hash("#{group_id}:#{identifier}") % base + 1
12
+ def get_normalized_number(identifier, group_id, seed, base = NORMALIZER)
13
+ MurmurHash3::V32.str_hash("#{group_id}:#{identifier}", seed) % base + 1
13
14
  end
14
15
  end
15
16
  end
@@ -1,3 +1,3 @@
1
1
  module Unleash
2
- VERSION = "4.5.0".freeze
2
+ VERSION = "5.0.0".freeze
3
3
  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: 4.5.0
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Renato Arruda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-24 00:00:00.000000000 Z
11
+ date: 2023-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: murmurhash3