flipper 0.11.0 → 0.12.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/.codeclimate.yml +2 -0
- data/.rubocop.yml +3 -0
- data/Changelog.md +19 -2
- data/Rakefile +1 -6
- data/docs/Gates.md +3 -3
- data/lib/flipper.rb +10 -2
- data/lib/flipper/dsl.rb +5 -0
- data/lib/flipper/feature.rb +8 -0
- data/lib/flipper/middleware/memoizer.rb +4 -4
- data/lib/flipper/spec/shared_adapter_specs.rb +11 -0
- data/lib/flipper/test/shared_adapter_test.rb +11 -0
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/adapter_spec.rb +7 -0
- data/spec/flipper/dsl_spec.rb +17 -0
- data/spec/flipper/feature_spec.rb +20 -0
- data/spec/flipper/middleware/memoizer_spec.rb +4 -4
- data/spec/flipper_spec.rb +18 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc4f086ed26b95a195d65b0ef2162c09bf7d4878
|
4
|
+
data.tar.gz: 4360d2c7f218cc2790248497827ac55b866e617f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cafced6f460315fb925d0e8b849dd68bcc1c81bd719075378727095a2921ad80b4b3dce30ed616f5f9b13ac2f7a90e9521e27b01ea72957cc1a44176693caf77
|
7
|
+
data.tar.gz: 446d33765b51edda016f98ebf4fbf88cbd51ea5248b4e750fc8c26d72bcb24ac2d45b97929e206620b8ddbd47e46b2d57ec8b827a1554a801d4261aeadd8f98d
|
data/.codeclimate.yml
ADDED
data/.rubocop.yml
CHANGED
data/Changelog.md
CHANGED
@@ -1,10 +1,24 @@
|
|
1
|
+
## 0.12
|
2
|
+
|
3
|
+
### Additions/Changes
|
4
|
+
|
5
|
+
* Added Flipper.instance= writer method for explicitly setting the default instance (https://github.com/jnunemaker/flipper/pull/309).
|
6
|
+
* Added Flipper::UI configuration instance for changing text and things (https://github.com/jnunemaker/flipper/pull/306).
|
7
|
+
* Delegate memoize= and memoizing? for Flipper and Flipper::DSL (https://github.com/jnunemaker/flipper/pull/310).
|
8
|
+
* Fixed error when enabling the same group or actor more than once (https://github.com/jnunemaker/flipper/pull/313).
|
9
|
+
* Fixed redis cache adapter key (and thus cache misses) (https://github.com/jnunemaker/flipper/pull/325).
|
10
|
+
* Added Rollout adapter to make it easy to import rollout data into Flipper (https://github.com/jnunemaker/flipper/pull/319).
|
11
|
+
* Relaxed redis gem dependency constraint to allow redis-rb 4 (https://github.com/jnunemaker/flipper/pull/317).
|
12
|
+
* Added configuration option for Flipper::UI to disable feature removal (https://github.com/jnunemaker/flipper/pull/322).
|
13
|
+
|
1
14
|
## 0.11
|
2
15
|
|
3
16
|
### Backwards Compatibility Breaks
|
4
17
|
|
5
|
-
* Set flipper from env for API and UI (https://github.com/jnunemaker/flipper/pull/223 and https://github.com/jnunemaker/flipper/pull/229). It is documented, but now the memoizing middleware requires that the SetupEnv middleware is used first.
|
18
|
+
* Set flipper from env for API and UI (https://github.com/jnunemaker/flipper/pull/223 and https://github.com/jnunemaker/flipper/pull/229). It is documented, but now the memoizing middleware requires that the SetupEnv middleware is used first, unless you are configuring a Flipper default instance.
|
6
19
|
* Drop support for Ruby 2.0 as it is end of lined (https://github.com/jnunemaker/flipper/commit/c2c81ed89938155ce91acb5173ac38580f630e3d).
|
7
20
|
* Allow unregistered groups (https://github.com/jnunemaker/flipper/pull/244). Only break in compatibility is that previously unregistered groups could not be enabled and now they can be.
|
21
|
+
* Removed support for metriks (https://github.com/jnunemaker/flipper/pull/291).
|
8
22
|
|
9
23
|
### Additions/Changes
|
10
24
|
|
@@ -22,9 +36,12 @@
|
|
22
36
|
* Add DSL#preload_all and Adapter#get_all to allow for making even more efficient loading of features (https://github.com/jnunemaker/flipper/pull/255).
|
23
37
|
* Allow setting debug output of http adapter (https://github.com/jnunemaker/flipper/pull/256 and https://github.com/jnunemaker/flipper/pull/258).
|
24
38
|
* Allow setting env key for middleware (https://github.com/jnunemaker/flipper/pull/259).
|
25
|
-
* Added ActiveSupport cache store adapter for use with Rails.cache (https://github.com/jnunemaker/flipper/pull/265).
|
39
|
+
* Added ActiveSupport cache store adapter for use with Rails.cache (https://github.com/jnunemaker/flipper/pull/265 and https://github.com/jnunemaker/flipper/pull/297).
|
26
40
|
* Added support for up to 3 decimal places in percentage based rollouts (https://github.com/jnunemaker/flipper/pull/274).
|
27
41
|
* Removed Flipper::GroupNotRegistered error as it is now unused (https://github.com/jnunemaker/flipper/pull/270).
|
42
|
+
* Added get_all to all adapters (https://github.com/jnunemaker/flipper/pull/298).
|
43
|
+
* Added support for Rails 5.1 (https://github.com/jnunemaker/flipper/pull/299).
|
44
|
+
* Added Flipper default instance generation (https://github.com/jnunemaker/flipper/pull/279).
|
28
45
|
|
29
46
|
## 0.10.2
|
30
47
|
|
data/Rakefile
CHANGED
@@ -41,9 +41,4 @@ Rake::TestTask.new do |t|
|
|
41
41
|
t.pattern = 'test/**/*_test.rb'
|
42
42
|
end
|
43
43
|
|
44
|
-
|
45
|
-
t.libs = %w(lib test)
|
46
|
-
t.pattern = 'lib/flipper/shared/test/**_test.rb'
|
47
|
-
end
|
48
|
-
|
49
|
-
task default: [:spec, :test, :shared_test]
|
44
|
+
task default: [:spec, :test]
|
data/docs/Gates.md
CHANGED
@@ -15,7 +15,7 @@ flipper[:stats].enabled? # check
|
|
15
15
|
|
16
16
|
## 2. Group
|
17
17
|
|
18
|
-
Turn on feature based on the return value of block. Super flexible way to turn on a feature for multiple things (users, people, accounts, etc.) as long as the thing returns true when passed to the block.
|
18
|
+
Turn on feature based on the return value of block. Super flexible way to turn on a feature for multiple things (users, people, accounts, etc.) as long as the thing returns true when passed to the block.
|
19
19
|
|
20
20
|
```ruby
|
21
21
|
# this registers a group
|
@@ -71,8 +71,8 @@ In your application code, you can do something like this now:
|
|
71
71
|
if flipper[:stats].enabled?(some_admin)
|
72
72
|
# do thing...
|
73
73
|
else
|
74
|
-
|
75
|
-
end
|
74
|
+
# do not do thing
|
75
|
+
end
|
76
76
|
```
|
77
77
|
|
78
78
|
## 3. Individual Actor
|
data/lib/flipper.rb
CHANGED
@@ -32,7 +32,7 @@ module Flipper
|
|
32
32
|
# Public: Sets Flipper::Configuration instance.
|
33
33
|
def configuration=(configuration)
|
34
34
|
# need to reset flipper instance if configuration changes
|
35
|
-
|
35
|
+
self.instance = nil
|
36
36
|
@configuration = configuration
|
37
37
|
end
|
38
38
|
|
@@ -46,6 +46,13 @@ module Flipper
|
|
46
46
|
Thread.current[:flipper_instance] ||= configuration.default
|
47
47
|
end
|
48
48
|
|
49
|
+
# Public: Set the flipper instance. It is most common to use the
|
50
|
+
# Configuration#default to set this instance, but for things like the test
|
51
|
+
# environment, this writer is actually useful.
|
52
|
+
def instance=(flipper)
|
53
|
+
Thread.current[:flipper_instance] = flipper
|
54
|
+
end
|
55
|
+
|
49
56
|
# Public: All the methods delegated to instance. These should match the
|
50
57
|
# interface of Flipper::DSL.
|
51
58
|
def_delegators :instance,
|
@@ -57,7 +64,8 @@ module Flipper
|
|
57
64
|
:enable_percentage_of_time, :disable_percentage_of_time,
|
58
65
|
:time, :percentage_of_time,
|
59
66
|
:features, :feature, :[], :preload, :preload_all,
|
60
|
-
:adapter, :add, :remove, :import
|
67
|
+
:adapter, :add, :remove, :import,
|
68
|
+
:memoize=, :memoizing?
|
61
69
|
|
62
70
|
# Public: Use this to register a group by name.
|
63
71
|
#
|
data/lib/flipper/dsl.rb
CHANGED
@@ -1,14 +1,19 @@
|
|
1
|
+
require 'forwardable'
|
1
2
|
require 'flipper/adapters/memoizable'
|
2
3
|
require 'flipper/instrumenters/noop'
|
3
4
|
|
4
5
|
module Flipper
|
5
6
|
class DSL
|
7
|
+
extend Forwardable
|
8
|
+
|
6
9
|
# Private
|
7
10
|
attr_reader :adapter
|
8
11
|
|
9
12
|
# Private: What is being used to instrument all the things.
|
10
13
|
attr_reader :instrumenter
|
11
14
|
|
15
|
+
def_delegators :@adapter, :memoize=, :memoizing?
|
16
|
+
|
12
17
|
# Public: Returns a new instance of the DSL.
|
13
18
|
#
|
14
19
|
# adapter - The adapter that this DSL instance should use.
|
data/lib/flipper/feature.rb
CHANGED
@@ -6,6 +6,7 @@ require 'flipper/gate_values'
|
|
6
6
|
require 'flipper/instrumenters/noop'
|
7
7
|
|
8
8
|
module Flipper
|
9
|
+
# rubocop:disable Metrics/ClassLength
|
9
10
|
class Feature
|
10
11
|
# Private: The name of feature instrumentation events.
|
11
12
|
InstrumentationName = "feature_operation.#{InstrumentationNamespace}".freeze
|
@@ -83,6 +84,13 @@ module Flipper
|
|
83
84
|
instrument(:remove) { adapter.remove(self) }
|
84
85
|
end
|
85
86
|
|
87
|
+
# Public: Clears all gate values for this feature.
|
88
|
+
#
|
89
|
+
# Returns the result of Adapter#clear.
|
90
|
+
def clear
|
91
|
+
instrument(:clear) { adapter.clear(self) }
|
92
|
+
end
|
93
|
+
|
86
94
|
# Public: Check if a feature is enabled for a thing.
|
87
95
|
#
|
88
96
|
# Returns true if enabled, false if not.
|
@@ -52,8 +52,8 @@ module Flipper
|
|
52
52
|
def memoized_call(env)
|
53
53
|
reset_on_body_close = false
|
54
54
|
flipper = env.fetch(@env_key) { Flipper }
|
55
|
-
original = flipper.
|
56
|
-
flipper.
|
55
|
+
original = flipper.memoizing?
|
56
|
+
flipper.memoize = true
|
57
57
|
|
58
58
|
flipper.preload_all if @opts[:preload_all]
|
59
59
|
|
@@ -63,12 +63,12 @@ module Flipper
|
|
63
63
|
|
64
64
|
response = @app.call(env)
|
65
65
|
response[2] = Rack::BodyProxy.new(response[2]) do
|
66
|
-
flipper.
|
66
|
+
flipper.memoize = original
|
67
67
|
end
|
68
68
|
reset_on_body_close = true
|
69
69
|
response
|
70
70
|
ensure
|
71
|
-
flipper.
|
71
|
+
flipper.memoize = original if flipper && !reset_on_body_close
|
72
72
|
end
|
73
73
|
end
|
74
74
|
end
|
@@ -258,4 +258,15 @@ RSpec.shared_examples_for 'a flipper adapter' do
|
|
258
258
|
expect(stats).to eq(subject.default_config.merge(boolean: 'true'))
|
259
259
|
expect(search).to eq(subject.default_config)
|
260
260
|
end
|
261
|
+
|
262
|
+
it 'can double enable an actor without error' do
|
263
|
+
actor = Flipper::Actor.new('Flipper::Actor;22')
|
264
|
+
expect(subject.enable(feature, actor_gate, flipper.actor(actor))).to eq(true)
|
265
|
+
expect(subject.enable(feature, actor_gate, flipper.actor(actor))).to eq(true)
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'can double enable a group without error' do
|
269
|
+
expect(subject.enable(feature, group_gate, flipper.group(:admins))).to eq(true)
|
270
|
+
expect(subject.enable(feature, group_gate, flipper.group(:admins))).to eq(true)
|
271
|
+
end
|
261
272
|
end
|
@@ -253,6 +253,17 @@ module Flipper
|
|
253
253
|
assert_equal @adapter.default_config.merge(boolean: 'true'), stats
|
254
254
|
assert_equal @adapter.default_config, search
|
255
255
|
end
|
256
|
+
|
257
|
+
def test_can_double_enable_an_actor_without_error
|
258
|
+
actor = Flipper::Actor.new('Flipper::Actor;22')
|
259
|
+
assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor))
|
260
|
+
assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor))
|
261
|
+
end
|
262
|
+
|
263
|
+
def test_can_double_enable_a_group_without_error
|
264
|
+
assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
|
265
|
+
assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
|
266
|
+
end
|
256
267
|
end
|
257
268
|
end
|
258
269
|
end
|
data/lib/flipper/version.rb
CHANGED
@@ -65,6 +65,13 @@ RSpec.describe Flipper::Adapter do
|
|
65
65
|
|
66
66
|
destination_flipper.import(source_flipper)
|
67
67
|
|
68
|
+
feature = destination_flipper[:yep]
|
69
|
+
expect(feature.boolean_value).to be(true)
|
70
|
+
expect(feature.groups_value).to eq(Set[])
|
71
|
+
expect(feature.actors_value).to eq(Set[])
|
72
|
+
expect(feature.percentage_of_actors_value).to be(0)
|
73
|
+
expect(feature.percentage_of_time_value).to be(0)
|
74
|
+
|
68
75
|
feature = destination_flipper[:preview_features]
|
69
76
|
expect(feature.boolean_value).to be(false)
|
70
77
|
expect(feature.actors_value).to eq(Set['1', '2', '3'])
|
data/spec/flipper/dsl_spec.rb
CHANGED
@@ -329,4 +329,21 @@ RSpec.describe Flipper::DSL do
|
|
329
329
|
subject.import(destination_flipper)
|
330
330
|
end
|
331
331
|
end
|
332
|
+
|
333
|
+
describe '#memoize=' do
|
334
|
+
it 'delegates to adapter' do
|
335
|
+
expect(subject.adapter).not_to be_memoizing
|
336
|
+
subject.memoize = true
|
337
|
+
expect(subject.adapter).to be_memoizing
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
describe '#memoizing?' do
|
342
|
+
it 'delegates to adapter' do
|
343
|
+
subject.memoize = false
|
344
|
+
expect(subject.adapter.memoizing?).to eq(subject.memoizing?)
|
345
|
+
subject.memoize = true
|
346
|
+
expect(subject.adapter.memoizing?).to eq(subject.memoizing?)
|
347
|
+
end
|
348
|
+
end
|
332
349
|
end
|
@@ -106,6 +106,15 @@ RSpec.describe Flipper::Feature do
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
+
describe '#clear' do
|
110
|
+
it 'clears feature using adapter' do
|
111
|
+
subject.enable
|
112
|
+
expect(subject).to be_enabled
|
113
|
+
subject.clear
|
114
|
+
expect(subject).not_to be_enabled
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
109
118
|
describe '#inspect' do
|
110
119
|
it 'returns easy to read string representation' do
|
111
120
|
string = subject.inspect
|
@@ -234,6 +243,17 @@ RSpec.describe Flipper::Feature do
|
|
234
243
|
expect(event.payload[:result]).not_to be_nil
|
235
244
|
end
|
236
245
|
|
246
|
+
it 'is recorded for clear' do
|
247
|
+
subject.clear
|
248
|
+
|
249
|
+
event = instrumenter.events.last
|
250
|
+
expect(event).not_to be_nil
|
251
|
+
expect(event.name).to eq('feature_operation.flipper')
|
252
|
+
expect(event.payload[:feature_name]).to eq(:search)
|
253
|
+
expect(event.payload[:operation]).to eq(:clear)
|
254
|
+
expect(event.payload[:result]).not_to be_nil
|
255
|
+
end
|
256
|
+
|
237
257
|
it 'is recorded for enabled?' do
|
238
258
|
thing = Flipper::Types::Actor.new(Flipper::Actor.new('1'))
|
239
259
|
gate = subject.gate_for(thing)
|
@@ -18,7 +18,7 @@ RSpec.describe Flipper::Middleware::Memoizer do
|
|
18
18
|
let(:env) { { 'flipper' => flipper } }
|
19
19
|
|
20
20
|
after do
|
21
|
-
flipper.
|
21
|
+
flipper.memoize = nil
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'raises if initialized with app and flipper instance' do
|
@@ -51,9 +51,9 @@ RSpec.describe Flipper::Middleware::Memoizer do
|
|
51
51
|
middleware = described_class.new(app)
|
52
52
|
body = middleware.call(env).last
|
53
53
|
|
54
|
-
expect(flipper.
|
54
|
+
expect(flipper.memoizing?).to eq(true)
|
55
55
|
body.close
|
56
|
-
expect(flipper.
|
56
|
+
expect(flipper.memoizing?).to eq(false)
|
57
57
|
end
|
58
58
|
|
59
59
|
it 'clears local cache after body close' do
|
@@ -231,7 +231,7 @@ RSpec.describe Flipper::Middleware::Memoizer do
|
|
231
231
|
middleware = described_class.new(app)
|
232
232
|
middleware.call(env)
|
233
233
|
rescue RuntimeError
|
234
|
-
expect(flipper.
|
234
|
+
expect(flipper.memoizing?).to be(false)
|
235
235
|
end
|
236
236
|
end
|
237
237
|
end
|
data/spec/flipper_spec.rb
CHANGED
@@ -54,6 +54,14 @@ RSpec.describe Flipper do
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
describe '.instance=' do
|
58
|
+
it 'updates Flipper.instance' do
|
59
|
+
instance = described_class.new(Flipper::Adapters::Memory.new)
|
60
|
+
described_class.instance = instance
|
61
|
+
expect(described_class.instance).to be(instance)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
57
65
|
describe "delegation to instance" do
|
58
66
|
let(:group) { Flipper::Types::Group.new(:admins) }
|
59
67
|
let(:actor) { Flipper::Actor.new("1") }
|
@@ -193,6 +201,16 @@ RSpec.describe Flipper do
|
|
193
201
|
it 'delegates adapter to instance' do
|
194
202
|
expect(described_class.adapter).to eq(described_class.instance.adapter)
|
195
203
|
end
|
204
|
+
|
205
|
+
it 'delegates memoize= to instance' do
|
206
|
+
expect(described_class.adapter.memoizing?).to be(false)
|
207
|
+
described_class.memoize = true
|
208
|
+
expect(described_class.adapter.memoizing?).to be(true)
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'delegates memoizing? to instance' do
|
212
|
+
expect(described_class.memoizing?).to eq(described_class.adapter.memoizing?)
|
213
|
+
end
|
196
214
|
end
|
197
215
|
|
198
216
|
describe '.register' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flipper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Nunemaker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Feature flipper is the act of enabling/disabling features in your application,
|
14
14
|
ideally without re-deploying or changing anything in your code base. Flipper makes
|
@@ -19,6 +19,7 @@ executables: []
|
|
19
19
|
extensions: []
|
20
20
|
extra_rdoc_files: []
|
21
21
|
files:
|
22
|
+
- ".codeclimate.yml"
|
22
23
|
- ".rubocop.yml"
|
23
24
|
- ".rubocop_todo.yml"
|
24
25
|
- Changelog.md
|