flipper 0.24.0 → 0.25.1

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