flipper 0.24.0 → 0.25.1

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: f74cad5c410ce4146e29c11d692fb97d500c54301af8dab6b1c4b0da95ae79c8
4
- data.tar.gz: 5e6f5613ea2166f1899e553601c555a87b9f47de169ef45b5f19c0d3aa77b3c9
3
+ metadata.gz: 8e68f84bdcc12fad64f830ad9f6bc0ab3c8c3bff0cfddcd892d854578fcd4c3a
4
+ data.tar.gz: 218f8b4e67048e6d1fcf8d1b62225f75ef1910d7975a8fa17ad5eda266af51dc
5
5
  SHA512:
6
- metadata.gz: 44f19778f0d3e35f99b909b4bd2fa2603b596b4cff77eb70d806c73453c1a1cf4a3d79ddf5c4ef593464099134505507152e1f392174f525e4815d5ca5592371
7
- data.tar.gz: e999db32f892bbbf307c38f65b98b149489c830ba1b2530f2f5d308b837eb8a4d5d1f49f95242047d989e93b253a0599df8929fece5d78a9d959a2cad9dfac52
6
+ metadata.gz: 404267d0e94b8924b1b7f45c1b97552a1d5c2cdff2edb0590da35b75580a04206a94ce693f983c34e3b88050cc6efeb6d90f823d779fab1954c1d145b18b730b
7
+ data.tar.gz: 2ce9fd6b8bf6efd66cab2438986ea1a5783bb9c65b3a00a43b881f73346f2e42042082cf40a5e64061fa98cfa4d7bd097f93adb9bb03638385fb23d9f12e824c
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
@@ -34,13 +34,13 @@ jobs:
34
34
  - name: Setup memcached
35
35
  uses: KeisukeYamashita/memcached-actions@v1
36
36
  - name: Start MongoDB
37
- uses: supercharge/mongodb-github-action@1.3.0
37
+ uses: supercharge/mongodb-github-action@1.7.0
38
38
  with:
39
39
  mongodb-version: 4.0
40
40
  - name: Check out repository code
41
- uses: actions/checkout@v2
41
+ uses: actions/checkout@v3
42
42
  - name: Do some action caching
43
- uses: actions/cache@v1
43
+ uses: actions/cache@v3
44
44
  with:
45
45
  path: vendor/bundle
46
46
  key: ${{ runner.os }}-gems-${{ matrix.ruby }}-${{ matrix.rails }}-${{ hashFiles('**/Gemfile.lock') }}
@@ -36,13 +36,13 @@ jobs:
36
36
  - name: Setup memcached
37
37
  uses: KeisukeYamashita/memcached-actions@v1
38
38
  - name: Start MongoDB
39
- uses: supercharge/mongodb-github-action@1.3.0
39
+ uses: supercharge/mongodb-github-action@1.7.0
40
40
  with:
41
41
  mongodb-version: 4.0
42
42
  - name: Check out repository code
43
- uses: actions/checkout@v2
43
+ uses: actions/checkout@v3
44
44
  - name: Do some action caching
45
- uses: actions/cache@v1
45
+ uses: actions/cache@v3
46
46
  with:
47
47
  path: vendor/bundle
48
48
  key: ${{ runner.os }}-gems-${{ matrix.ruby }}-${{ matrix.rails }}-${{ hashFiles('**/Gemfile.lock') }}
data/Changelog.md CHANGED
@@ -1,3 +1,32 @@
1
+ ## 0.25.1
2
+
3
+ ### Additions/Changes
4
+
5
+ * ActiveRecord: use provided `gate_class` option when calling `#get_all` (https://github.com/jnunemaker/flipper/pull/647)
6
+ * Relaxed the rack-protection version to support latest (https://github.com/jnunemaker/flipper/commit/f4a41c541ccf14c535a61c6bc6fe7eeabbfc7e71).
7
+ * Configure ActiveRecord adapter immediately upon require of flipper-active_record (https://github.com/jnunemaker/flipper/pull/652)
8
+
9
+ ## 0.25.0
10
+
11
+ ### Additions/Changes
12
+
13
+ * Added a prompt in Flipper UI for the 'Delete' button to prevent accidental delete of features (https://github.com/jnunemaker/flipper/pull/625)
14
+ * Added failsafe adapter (https://github.com/jnunemaker/flipper/pull/626)
15
+ * Removed previously deprecated options and settings. Those upgrading from `<0.21` should upgrade to `~>0.24` first and fix any deprecation warnings when initializing Flipper. (https://github.com/jnunemaker/flipper/pull/627)
16
+ * ActiveRecord: base class for internal models (https://github.com/jnunemaker/flipper/pull/629)
17
+ * Remove use of `Rack::BodyProxy` in the memoizer middleware (https://github.com/jnunemaker/flipper/pull/631)
18
+
19
+ ## 0.24.1
20
+
21
+ ### Additions/Changes
22
+
23
+ * flipper-api: `exclude_gates` parameter to exclude gate data in GETs (https://github.com/jnunemaker/flipper/pull/572).
24
+ * Make it possible to disable internal memoization (https://github.com/jnunemaker/flipper/pull/612).
25
+ * Add Flipper::Actor#hash so actors can be hash keys (https://github.com/jnunemaker/flipper/pull/616).
26
+ * Pretty Up `rails routes` again and make rack-protection dependency less strict (https://github.com/jnunemaker/flipper/pull/619).
27
+ * Add kwargs for method_missing using ruby 3.0 (https://github.com/jnunemaker/flipper/pull/620).
28
+ * Relax the rack-protection dependency (https://github.com/jnunemaker/flipper/commit/c1cb9cd78140c2b09123687642558101e6e5d37d).
29
+
1
30
  ## 0.24.0
2
31
 
3
32
  ### Additions/Changes
@@ -6,7 +35,7 @@
6
35
  * Removed support for Ruby 2.5 (which was end of line 9 months ago)
7
36
  * Add (alpha) client side instrumentation of events to cloud (https://github.com/jnunemaker/flipper/pull/602)
8
37
  * Fix deprecated uses of Redis#pipelined (https://github.com/jnunemaker/flipper/pull/603). redis-rb >= 3 now required.
9
- * Fix Flipper UI Rack application when `Rack::Session::Pool` is used to build it.
38
+ * Fix Flipper UI Rack application when `Rack::Session::Pool` is used to build it (https://github.com/jnunemaker/flipper/pull/606).
10
39
 
11
40
  ## 0.23.1
12
41
 
data/Gemfile CHANGED
@@ -6,7 +6,7 @@ Dir['flipper-*.gemspec'].each do |gemspec|
6
6
  gemspec(name: "flipper-#{plugin}", development_group: plugin)
7
7
  end
8
8
 
9
- gem 'pry'
9
+ gem 'debug'
10
10
  gem 'rake', '~> 12.3.3'
11
11
  gem 'shotgun', '~> 0.9'
12
12
  gem 'statsd-ruby', '~> 1.2.1'
@@ -1,5 +1,6 @@
1
1
  require 'bundler/setup'
2
2
  require 'securerandom'
3
+ require 'active_support/isolated_execution_state'
3
4
  require 'active_support/notifications'
4
5
 
5
6
  class FlipperSubscriber
@@ -1,6 +1,7 @@
1
1
  # Quick example of how to keep track of when a feature was last checked.
2
2
  require 'bundler/setup'
3
3
  require 'securerandom'
4
+ require 'active_support/isolated_execution_state'
4
5
  require 'active_support/notifications'
5
6
  require 'flipper'
6
7
 
data/lib/flipper/actor.rb CHANGED
@@ -12,5 +12,9 @@ module Flipper
12
12
  self.class.eql?(other.class) && @flipper_id == other.flipper_id
13
13
  end
14
14
  alias_method :==, :eql?
15
+
16
+ def hash
17
+ flipper_id.hash
18
+ end
15
19
  end
16
20
  end
@@ -0,0 +1,76 @@
1
+ module Flipper
2
+ module Adapters
3
+ class Failsafe
4
+ include ::Flipper::Adapter
5
+
6
+ # Public: The name of the adapter.
7
+ attr_reader :name
8
+
9
+ # Public: Build a new Failsafe instance.
10
+ #
11
+ # adapter - Flipper adapter to guard.
12
+ # options - Hash of options:
13
+ # :errors - Array of exception types for which to fail safe
14
+
15
+ def initialize(adapter, options = {})
16
+ @adapter = adapter
17
+ @errors = options.fetch(:errors, [StandardError])
18
+ @name = :failsafe
19
+ end
20
+
21
+ def features
22
+ @adapter.features
23
+ rescue *@errors
24
+ Set.new
25
+ end
26
+
27
+ def add(feature)
28
+ @adapter.add(feature)
29
+ rescue *@errors
30
+ false
31
+ end
32
+
33
+ def remove(feature)
34
+ @adapter.remove(feature)
35
+ rescue *@errors
36
+ false
37
+ end
38
+
39
+ def clear(feature)
40
+ @adapter.clear(feature)
41
+ rescue *@errors
42
+ false
43
+ end
44
+
45
+ def get(feature)
46
+ @adapter.get(feature)
47
+ rescue *@errors
48
+ {}
49
+ end
50
+
51
+ def get_multi(features)
52
+ @adapter.get_multi(features)
53
+ rescue *@errors
54
+ {}
55
+ end
56
+
57
+ def get_all
58
+ @adapter.get_all
59
+ rescue *@errors
60
+ {}
61
+ end
62
+
63
+ def enable(feature, gate, thing)
64
+ @adapter.enable(feature, gate, thing)
65
+ rescue *@errors
66
+ false
67
+ end
68
+
69
+ def disable(feature, gate, thing)
70
+ @adapter.disable(feature, gate, thing)
71
+ rescue *@errors
72
+ false
73
+ end
74
+ end
75
+ end
76
+ end
data/lib/flipper/dsl.rb CHANGED
@@ -17,10 +17,12 @@ module Flipper
17
17
  # adapter - The adapter that this DSL instance should use.
18
18
  # options - The Hash of options.
19
19
  # :instrumenter - What should be used to instrument all the things.
20
+ # :memoize - Should adapter be wrapped by memoize adapter or not.
20
21
  def initialize(adapter, options = {})
21
22
  @instrumenter = options.fetch(:instrumenter, Instrumenters::Noop)
22
- memoized = Adapters::Memoizable.new(adapter)
23
- @adapter = memoized
23
+ memoize = options.fetch(:memoize, true)
24
+ adapter = Adapters::Memoizable.new(adapter) if memoize
25
+ @adapter = adapter
24
26
  @memoized_features = {}
25
27
  end
26
28
 
@@ -12,15 +12,6 @@ module Flipper
12
12
  # Raised when attempting to declare a group name that has already been used.
13
13
  class DuplicateGroup < Error; end
14
14
 
15
- # Raised when default instance not configured but there is an attempt to
16
- # use it.
17
- class DefaultNotSet < Flipper::Error
18
- def initialize(message = nil)
19
- warn "Flipper::DefaultNotSet is deprecated and will be removed in 1.0"
20
- super
21
- end
22
- end
23
-
24
15
  # Raised when an invalid value is set to a configuration property
25
16
  class InvalidConfigurationValue < Flipper::Error
26
17
  def initialize(message = nil)
@@ -28,12 +19,4 @@ module Flipper
28
19
  super(message || default)
29
20
  end
30
21
  end
31
-
32
- # Raised when accessing a configuration property that has been deprecated
33
- class ConfigurationDeprecated < Flipper::Error
34
- def initialize(message = nil)
35
- default = "The configuration property has been deprecated"
36
- super(message || default)
37
- end
38
- end
39
22
  end
@@ -25,11 +25,6 @@ module Flipper
25
25
  raise 'Flipper::Middleware::Memoizer no longer initializes with a flipper instance or block. Read more at: https://git.io/vSo31.'
26
26
  end
27
27
 
28
- if opts[:preload_all]
29
- warn "Flipper::Middleware::Memoizer: `preload_all` is deprecated, use `preload: true`"
30
- opts[:preload] = true
31
- end
32
-
33
28
  @app = app
34
29
  @opts = opts
35
30
  @env_key = opts.fetch(:env_key, 'flipper')
@@ -74,14 +69,9 @@ module Flipper
74
69
  when Array then flipper.preload(@opts[:preload])
75
70
  end
76
71
 
77
- response = @app.call(env)
78
- response[2] = Rack::BodyProxy.new(response[2]) do
79
- flipper.memoize = false
80
- end
81
- reset_on_body_close = true
82
- response
72
+ @app.call(env)
83
73
  ensure
84
- flipper.memoize = false if flipper && !reset_on_body_close
74
+ flipper.memoize = false if flipper
85
75
  end
86
76
  end
87
77
  end
@@ -23,8 +23,14 @@ module Flipper
23
23
  super || @thing.respond_to?(*args)
24
24
  end
25
25
 
26
- def method_missing(name, *args, &block)
27
- @thing.send name, *args, &block
26
+ if RUBY_VERSION >= '3.0'
27
+ def method_missing(name, *args, **kwargs, &block)
28
+ @thing.send name, *args, **kwargs, &block
29
+ end
30
+ else
31
+ def method_missing(name, *args, &block)
32
+ @thing.send name, *args, &block
33
+ end
28
34
  end
29
35
  end
30
36
  end
@@ -1,3 +1,3 @@
1
1
  module Flipper
2
- VERSION = '0.24.0'.freeze
2
+ VERSION = '0.25.1'.freeze
3
3
  end
@@ -43,4 +43,14 @@ RSpec.describe Flipper::Actor do
43
43
  expect(actor1.==(actor2)).to be(false)
44
44
  end
45
45
  end
46
+
47
+ describe '#hash' do
48
+ it 'returns a hash-value based on the flipper id' do
49
+ h = {
50
+ described_class.new("User;123") => true
51
+ }
52
+ expect(h).to have_key(described_class.new("User;123"))
53
+ expect(h).not_to have_key(described_class.new("User;456"))
54
+ end
55
+ end
46
56
  end
@@ -0,0 +1,58 @@
1
+ require 'flipper/adapters/failsafe'
2
+
3
+ RSpec.describe Flipper::Adapters::Failsafe do
4
+ subject { described_class.new(memory_adapter, options) }
5
+
6
+ let(:memory_adapter) { Flipper::Adapters::Memory.new }
7
+ let(:options) { {} }
8
+ let(:flipper) { Flipper.new(subject) }
9
+
10
+ it_should_behave_like 'a flipper adapter'
11
+
12
+ context 'when disaster strikes' do
13
+ before do
14
+ expect(flipper[feature.name].enable).to be(true)
15
+
16
+ (subject.methods - Object.methods).each do |method_name|
17
+ allow(memory_adapter).to receive(method_name).and_raise(IOError)
18
+ end
19
+ end
20
+
21
+ let(:feature) { Flipper::Feature.new(:my_feature, subject) }
22
+
23
+ it { expect(subject.features).to eq(Set.new) }
24
+ it { expect(feature.add).to eq(false) }
25
+ it { expect(feature.remove).to eq(false) }
26
+ it { expect(feature.clear).to eq(false) }
27
+ it { expect(subject.get(feature)).to eq({}) }
28
+ it { expect(subject.get_multi([feature])).to eq({}) }
29
+ it { expect(subject.get_all).to eq({}) }
30
+ it { expect(feature.enable).to eq(false) }
31
+ it { expect(feature.disable).to eq(false) }
32
+
33
+ context 'when used via Flipper' do
34
+ it { expect(flipper.features).to eq(Set.new) }
35
+ it { expect(flipper[feature.name].enabled?).to eq(false) }
36
+ it { expect(flipper[feature.name].enable).to eq(false) }
37
+ it { expect(flipper[feature.name].disable).to eq(false) }
38
+ end
39
+
40
+ context 'when there is a syntax error' do
41
+ let(:test) { flipper[feature.name].enabled? }
42
+
43
+ before do
44
+ expect(memory_adapter).to receive(:get).and_raise(SyntaxError)
45
+ end
46
+
47
+ it 'does not catch this type of error' do
48
+ expect { test }.to raise_error(SyntaxError)
49
+ end
50
+
51
+ context 'when configured to catch SyntaxError' do
52
+ let(:options) { { errors: [SyntaxError] } }
53
+
54
+ it { expect(test).to eq(false) }
55
+ end
56
+ end
57
+ end
58
+ end
@@ -6,9 +6,19 @@ RSpec.describe Flipper::DSL do
6
6
  let(:adapter) { Flipper::Adapters::Memory.new }
7
7
 
8
8
  describe '#initialize' do
9
- it 'sets adapter' do
10
- dsl = described_class.new(adapter)
11
- expect(dsl.adapter).not_to be_nil
9
+ context 'when using default memoize strategy' do
10
+ it 'wraps the given adapter with Flipper::Adapters::Memoizable' do
11
+ dsl = described_class.new(adapter)
12
+ expect(dsl.adapter.class).to be(Flipper::Adapters::Memoizable)
13
+ expect(dsl.adapter.adapter).to be(adapter)
14
+ end
15
+ end
16
+
17
+ context 'when disabling memoization' do
18
+ it 'uses the given adapter directly' do
19
+ dsl = described_class.new(adapter, memoize: false)
20
+ expect(dsl.adapter).to be(adapter)
21
+ end
12
22
  end
13
23
 
14
24
  it 'defaults instrumenter to noop' do
@@ -38,26 +38,6 @@ RSpec.describe Flipper::Middleware::Memoizer do
38
38
  expect(called).to eq(true)
39
39
  end
40
40
 
41
- it 'disables local cache after body close' do
42
- app = ->(_env) { [200, {}, []] }
43
- middleware = described_class.new(app)
44
- body = middleware.call(env).last
45
-
46
- expect(flipper.memoizing?).to eq(true)
47
- body.close
48
- expect(flipper.memoizing?).to eq(false)
49
- end
50
-
51
- it 'clears local cache after body close' do
52
- app = ->(_env) { [200, {}, []] }
53
- middleware = described_class.new(app)
54
- body = middleware.call(env).last
55
-
56
- flipper.adapter.cache['hello'] = 'world'
57
- body.close
58
- expect(flipper.adapter.cache).to be_empty
59
- end
60
-
61
41
  it 'clears the local cache with a successful request' do
62
42
  flipper.adapter.cache['hello'] = 'world'
63
43
  get '/', {}, 'flipper' => flipper
data/spec/spec_helper.rb CHANGED
@@ -9,7 +9,7 @@ require 'bundler'
9
9
 
10
10
  Bundler.setup(:default)
11
11
 
12
- require 'pry'
12
+ require 'debug'
13
13
  require 'webmock/rspec'
14
14
  WebMock.disable_net_connect!(allow_localhost: true)
15
15
 
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flipper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.24.0
4
+ version: 0.25.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Nunemaker
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-17 00:00:00.000000000 Z
11
+ date: 2022-08-19 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description:
13
+ description:
14
14
  email:
15
15
  - nunemaker@gmail.com
16
16
  executables: []
@@ -18,6 +18,7 @@ extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
20
  - ".codeclimate.yml"
21
+ - ".github/dependabot.yml"
21
22
  - ".github/workflows/ci.yml"
22
23
  - ".github/workflows/examples.yml"
23
24
  - ".rspec"
@@ -57,6 +58,7 @@ files:
57
58
  - lib/flipper/adapter.rb
58
59
  - lib/flipper/adapters/dual_write.rb
59
60
  - lib/flipper/adapters/failover.rb
61
+ - lib/flipper/adapters/failsafe.rb
60
62
  - lib/flipper/adapters/http.rb
61
63
  - lib/flipper/adapters/http/client.rb
62
64
  - lib/flipper/adapters/http/error.rb
@@ -110,6 +112,7 @@ files:
110
112
  - spec/flipper/adapter_spec.rb
111
113
  - spec/flipper/adapters/dual_write_spec.rb
112
114
  - spec/flipper/adapters/failover_spec.rb
115
+ - spec/flipper/adapters/failsafe_spec.rb
113
116
  - spec/flipper/adapters/http_spec.rb
114
117
  - spec/flipper/adapters/instrumented_spec.rb
115
118
  - spec/flipper/adapters/memoizable_spec.rb
@@ -163,7 +166,7 @@ licenses:
163
166
  - MIT
164
167
  metadata:
165
168
  changelog_uri: https://github.com/jnunemaker/flipper/blob/master/Changelog.md
166
- post_install_message:
169
+ post_install_message:
167
170
  rdoc_options: []
168
171
  require_paths:
169
172
  - lib
@@ -178,8 +181,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
178
181
  - !ruby/object:Gem::Version
179
182
  version: '0'
180
183
  requirements: []
181
- rubygems_version: 3.1.2
182
- signing_key:
184
+ rubygems_version: 3.3.7
185
+ signing_key:
183
186
  specification_version: 4
184
187
  summary: Feature flipper for ANYTHING
185
188
  test_files:
@@ -188,6 +191,7 @@ test_files:
188
191
  - spec/flipper/adapter_spec.rb
189
192
  - spec/flipper/adapters/dual_write_spec.rb
190
193
  - spec/flipper/adapters/failover_spec.rb
194
+ - spec/flipper/adapters/failsafe_spec.rb
191
195
  - spec/flipper/adapters/http_spec.rb
192
196
  - spec/flipper/adapters/instrumented_spec.rb
193
197
  - spec/flipper/adapters/memoizable_spec.rb