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 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