flipper 0.11.0 → 0.12.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
  SHA1:
3
- metadata.gz: fd726feaa644639324560bd944c759d63dcb4a49
4
- data.tar.gz: c02113838e6c7cfaa712dbddda0d4fb8c26317af
3
+ metadata.gz: cc4f086ed26b95a195d65b0ef2162c09bf7d4878
4
+ data.tar.gz: 4360d2c7f218cc2790248497827ac55b866e617f
5
5
  SHA512:
6
- metadata.gz: 3190149f9463a3938e5a8c773fc622356f6608bfd07c0c40ba5e8fc3ac3c4bafbb4e3351073d1346edd2171c90c47e360e1b2c9a6fa38b83150bd256ae6fdcce
7
- data.tar.gz: d4bc9f0af41052af9a2bf62fee2839f67717da4065d810165014a6fc8247dcc016f9dc16d6d9f15ba9e8d94280ea7fe425e66d610a9342c1eb632e44469e76e8
6
+ metadata.gz: cafced6f460315fb925d0e8b849dd68bcc1c81bd719075378727095a2921ad80b4b3dce30ed616f5f9b13ac2f7a90e9521e27b01ea72957cc1a44176693caf77
7
+ data.tar.gz: 446d33765b51edda016f98ebf4fbf88cbd51ea5248b4e750fc8c26d72bcb24ac2d45b97929e206620b8ddbd47e46b2d57ec8b827a1554a801d4261aeadd8f98d
data/.codeclimate.yml ADDED
@@ -0,0 +1,2 @@
1
+ exclude_patterns:
2
+ - "lib/flipper/ui/public"
data/.rubocop.yml CHANGED
@@ -43,3 +43,6 @@ RSpec/InstanceVariable:
43
43
 
44
44
  Style/AccessorMethodName:
45
45
  Enabled: false
46
+
47
+ Lint/HandleExceptions:
48
+ Enabled: false
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
- Rake::TestTask.new(:shared_test) do |t|
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
- raise "Your are not authorized to view this page"
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
- Thread.current[:flipper_instance] = nil
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.
@@ -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.adapter.memoizing?
56
- flipper.adapter.memoize = true
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.adapter.memoize = original
66
+ flipper.memoize = original
67
67
  end
68
68
  reset_on_body_close = true
69
69
  response
70
70
  ensure
71
- flipper.adapter.memoize = original if flipper && !reset_on_body_close
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
@@ -1,3 +1,3 @@
1
1
  module Flipper
2
- VERSION = '0.11.0'.freeze
2
+ VERSION = '0.12.0'.freeze
3
3
  end
@@ -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'])
@@ -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.adapter.memoize = nil
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.adapter.memoizing?).to eq(true)
54
+ expect(flipper.memoizing?).to eq(true)
55
55
  body.close
56
- expect(flipper.adapter.memoizing?).to eq(false)
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.adapter.memoizing?).to be(false)
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.11.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: 2017-11-07 00:00:00.000000000 Z
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