determinator 2.2.1 → 2.3.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: 6d7789a1dadc2dd7a112279b38edf04c2c6c1e908dc70f28667f030653207e10
4
- data.tar.gz: 8b25552108ae67607d973e16354f4606ff709c72a6b88d426e6b55e5348383f7
3
+ metadata.gz: 64d1088dbb10e6ed41b2d1b03f381eb97ad45ffeeb44d44cbb4cd86c16f37eab
4
+ data.tar.gz: 051e42e160577f2d18bbe400ef65316a72e7208aa04fb7afdb56593ff675d347
5
5
  SHA512:
6
- metadata.gz: e0cb8a958af21db56878a78072b649f9e53ca27b688868255fab271bb6cfc99e20737df479bb08d4cdee89050c096843cd57a28eaf45bfaefd6113abcb25427f
7
- data.tar.gz: 16d0337dbaf25238c0f095498df13df9d4ba37b0aa7319c108d5bc05d11e2d582adeadceef7ce7b2e04839ed38c32ac85f7e23118a8a74ad18cac0bf9065e350
6
+ metadata.gz: ad601db1e2572791c02d691407d7f70e8a7c089b80d81308cb3249b69f2d74e62821b0a3019115abca8468dd20de845005f3a65ef0a03718e3d8ef2497deb373
7
+ data.tar.gz: db770901187876e66202799c2672cb991e0856d26ff87ace117e2d33637421d4b6103833bec91ec1708c6376421727a27be20a0f116acfd9e94c9ab21fc8e309
data/.gitignore CHANGED
@@ -7,4 +7,5 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
- *.gem
10
+ *.gem
11
+ /.idea/
@@ -1,3 +1,8 @@
1
+ # v2.3.0 (2019-09-06)
2
+
3
+ Feature:
4
+ - `RSpec::Determinator` can apply `app_version` constraints but no longer supports multiple `forced_determination` calls on the same feature. [See the PR for an in-depth write-up.](https://github.com/deliveroo/determinator/pull/63)
5
+
1
6
  # v2.2.1 (2019-07-29)
2
7
 
3
8
  Bug fix:
@@ -1,6 +1,7 @@
1
1
  require 'digest/md5'
2
2
  require 'determinator/actor_control'
3
3
  require 'semantic'
4
+ require 'securerandom'
4
5
 
5
6
  module Determinator
6
7
  class Control
@@ -0,0 +1,27 @@
1
+ module Determinator
2
+ module Retrieve
3
+
4
+ # An retriever that returns features that were previously stored
5
+ # in the retriever. Useful for testing.
6
+ class InMemoryRetriever
7
+ def initialize
8
+ @features = {}
9
+ end
10
+
11
+ # @param name [string,symbol] The name of the feature to retrieve
12
+ def retrieve(name)
13
+ @features[name.to_s]
14
+ end
15
+
16
+ # @param feature [Determinator::Feature] The feature to store
17
+ def store(feature)
18
+ @features[feature.name] = feature
19
+ end
20
+
21
+ def clear!
22
+ @features.clear
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -1,3 +1,3 @@
1
1
  module Determinator
2
- VERSION = '2.2.1'
2
+ VERSION = '2.3.0'
3
3
  end
@@ -1,13 +1,22 @@
1
1
  require 'determinator'
2
+ require_relative '../determinator/retrieve/in_memory_retriever'
2
3
 
3
4
  module RSpec
4
5
  module Determinator
5
6
  def self.included(by)
6
7
  by.extend(DSL)
7
8
 
8
- by.let(:fake_determinator) { FakeControl.new }
9
- by.before do
10
- allow(::Determinator).to receive(:instance).and_return(fake_determinator)
9
+ by.let(:fake_retriever) { ::Determinator::Retrieve::InMemoryRetriever.new }
10
+ by.let(:fake_determinator) { ::RSpec::Determinator::FakeDeterminator.new(fake_retriever) }
11
+ by.around do |example|
12
+ old_retriever = ::Determinator.instance.retrieval
13
+ begin
14
+ fake_retriever.clear!
15
+ ::Determinator.configure(retrieval: fake_retriever)
16
+ example.run
17
+ ensure
18
+ ::Determinator.configure(retrieval: old_retriever)
19
+ end
11
20
  end
12
21
  end
13
22
 
@@ -18,62 +27,59 @@ module RSpec
18
27
  # If `outcome` or `only_for` are Symbols then the example-scoped variable of that name will be referenced (ie. those
19
28
  # variables created by `let` declarations)
20
29
  #
21
- # @params name [#to_s] The name of the Feature Flag or Experiment to mock
22
- # @params outcome [Boolean,String,Symbol] The outcome which should be supplied. Will look up an example variable if a Symbol is given.
23
- # @params :only_for [Hash,Symbol] The constraints that must be matched exactly in order for the determination to be applied.
24
- def forced_determination(name, outcome, only_for: {})
30
+ # @param [String,Symbol] name The name of the Feature Flag or Experiment to mock
31
+ # @param [Boolean,String,Symbol] outcome The outcome which should be supplied. Will look up an example variable if a Symbol is given.
32
+ # @param [Hash,Symbol] :only_for The constraints that must be matched exactly in order for the determination to be applied.
33
+ def forced_determination(name, outcome, bucket_type: 'single', only_for: {})
25
34
  before do
26
35
  outcome = send(outcome) if outcome.is_a?(Symbol)
27
36
  only_for = send(only_for) if only_for.is_a?(Symbol)
28
37
 
29
- fake_determinator.mock_result(
38
+ ::RSpec::Determinator::FakeDeterminator.new(fake_retriever).mock_result(
30
39
  name,
31
40
  outcome,
41
+ bucket_type: bucket_type,
32
42
  only_for: only_for
33
43
  )
34
44
  end
35
45
  end
36
- end
37
-
38
- class FakeControl
39
- def initialize
40
- @mocked_results = Hash.new { |h, k| h[k] = {} }
41
- end
42
46
 
43
- def for_actor(**args)
44
- ::Determinator::ActorControl.new(self, **args)
45
- end
46
-
47
- def mock_result(name, result, only_for: {})
48
- @mocked_results[name.to_s][normalize_properties(only_for)] = result
49
- end
50
-
51
- def fake_determinate(name, id: nil, guid: nil, properties: {})
52
- properties[:id] = id if id
53
- properties[:guid] = guid if guid
47
+ end
54
48
 
55
- outcome_for_feature_given_properties(name.to_s, normalize_properties(properties))
49
+ class FakeDeterminator
50
+ def initialize(in_memory_retriever)
51
+ @retriever = in_memory_retriever
56
52
  end
57
- alias_method :feature_flag_on?, :fake_determinate
58
- alias_method :which_variant, :fake_determinate
59
-
60
- private
61
53
 
62
- def outcome_for_feature_given_properties(feature_name, requirements)
63
- req_array = requirements.to_a
54
+ VALID_BUCKET_TYPES = %w{ id guid single }.freeze
64
55
 
65
- keys_in_priority_order = @mocked_results[feature_name].keys.reverse
66
- key = keys_in_priority_order.find do |given|
67
- (given.to_a - req_array).empty?
56
+ def mock_result(name, outcome, bucket_type: 'single', only_for: {})
57
+ if !VALID_BUCKET_TYPES.include?(bucket_type)
58
+ raise ArgumentError.new("bad bucket type #{bucket_type}, expected one of: #{VALID_BUCKET_TYPES.join(' ')}")
68
59
  end
69
60
 
70
- @mocked_results[feature_name][key] || false
71
- end
61
+ active = !!outcome
62
+ variants = case outcome
63
+ when true, false then
64
+ []
65
+ else
66
+ { outcome => 1 }
67
+ end
68
+ target_group = ::Determinator::TargetGroup.new(
69
+ rollout: 65_536,
70
+ constraints: only_for.map { |key, value| [key.to_s, Array(value).map(&:to_s)] }.to_h
71
+ )
72
72
 
73
- def normalize_properties(properties)
74
- properties.each_with_object({}) do |(key, value), hash|
75
- hash[key.to_s] = [*value].map(&:to_s)
76
- end
73
+ feature = ::Determinator::Feature.new(
74
+ name: name.to_s,
75
+ identifier: name.to_s,
76
+ bucket_type: bucket_type,
77
+ active: active,
78
+ variants: variants,
79
+ target_groups: [target_group]
80
+ )
81
+
82
+ @retriever.store(feature)
77
83
  end
78
84
  end
79
85
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: determinator
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - JP Hastings-Spital
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-29 00:00:00.000000000 Z
11
+ date: 2019-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -198,6 +198,7 @@ files:
198
198
  - lib/determinator/retrieve/dynaconf.rb
199
199
  - lib/determinator/retrieve/file.rb
200
200
  - lib/determinator/retrieve/http_retriever.rb
201
+ - lib/determinator/retrieve/in_memory_retriever.rb
201
202
  - lib/determinator/retrieve/null_retriever.rb
202
203
  - lib/determinator/serializers/json.rb
203
204
  - lib/determinator/target_group.rb
@@ -222,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
223
  - !ruby/object:Gem::Version
223
224
  version: '0'
224
225
  requirements: []
225
- rubygems_version: 3.0.4
226
+ rubygems_version: 3.0.3
226
227
  signing_key:
227
228
  specification_version: 4
228
229
  summary: Determine which experiments and features a specific actor should see.