flipper 1.2.1 → 1.2.2

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: 44c0c17f50251b0bfff9bd7cf3566b9ecffdf2f9941fcf64f0253b04e6d9b5e7
4
- data.tar.gz: 1407983190dbad2d02e07390d7acf8ac3e0fca4aaae610c02c72c4f16594d197
3
+ metadata.gz: 6ff734c4221d1ea2694fdf4e9e463085f60242e698b8702389c53ccc6a17e87b
4
+ data.tar.gz: 5666852d9f7416d30919a188c5e3c46cb202d66d332c482aba56c3d496437282
5
5
  SHA512:
6
- metadata.gz: 8e8de77bc356a0eb0e4ff147aaf2060847ccf05a71b214bdced861ae7a5d6ca83b3fbdf187b4318289530e0e1f01598687bd936a6c5fa772643af021571493d9
7
- data.tar.gz: f5ae3a78490ac77ca4a9ebd57c75ca82e62d1cf5906ee7adfa87a296342c54425aed8223115966ac16398048fea76c253fc240aedbc35366085d254f54dc85d5
6
+ metadata.gz: c48de5bfe83ff53d969d496f96a3df9335af8f1fe8d41559158930c9ae3dd94b91f245f7b4cfbceea1c85ab453a4dd94057e4a46e3f928d9b27ddc417f04c718
7
+ data.tar.gz: 2ed4dd3a74bbf07fe289d57b9545e073527971e5ab7f393ee96ea8f31904a9a550db4cda0ba492f080a14b1eb8b4982eb680e88b1c2bcfeea2e74e032207b1f4
data/Gemfile CHANGED
@@ -24,7 +24,6 @@ gem 'stackprof'
24
24
  gem 'benchmark-ips'
25
25
  gem 'stackprof-webnav'
26
26
  gem 'flamegraph'
27
- gem 'climate_control'
28
27
  gem 'mysql2'
29
28
  gem 'pg'
30
29
  gem 'cuprite'
data/lib/flipper/cli.rb CHANGED
@@ -209,8 +209,12 @@ module Flipper
209
209
  "#{count} #{count == 1 ? singular : plural}"
210
210
  end
211
211
 
212
- def colorize(text, options)
213
- IRB::Color.colorize(text, options)
212
+ def colorize(text, colors)
213
+ if defined?(Bundler)
214
+ Bundler.ui.add_color(text, *colors)
215
+ else
216
+ text
217
+ end
214
218
  end
215
219
 
216
220
  def indent(text, spaces)
@@ -1,17 +1,24 @@
1
1
  module Flipper
2
2
  module TestHelp
3
+ extend self
4
+
3
5
  def flipper_configure
4
- # Create a single shared memory adapter instance for each test
5
- @flipper_adapter = Flipper::Adapters::Memory.new
6
+ # Use a shared Memory adapter for all tests. This is instantiated outside of the
7
+ # `configure` block so the same instance is returned in new threads.
8
+ adapter = Flipper::Adapters::Memory.new
6
9
 
7
10
  Flipper.configure do |config|
8
- config.adapter { @flipper_adapter }
11
+ config.adapter { adapter }
9
12
  config.default { Flipper.new(config.adapter) }
10
13
  end
11
14
  end
12
15
 
13
16
  def flipper_reset
14
- Flipper.instance = nil # Reset previous flipper instance
17
+ # Remove all features
18
+ Flipper.features.each(&:remove) rescue nil
19
+
20
+ # Reset previous DSL instance
21
+ Flipper.instance = nil
15
22
  end
16
23
  end
17
24
  end
@@ -19,19 +26,17 @@ end
19
26
  if defined?(RSpec) && RSpec.respond_to?(:configure)
20
27
  RSpec.configure do |config|
21
28
  config.include Flipper::TestHelp
22
- config.before(:each) do
23
- flipper_reset
24
- flipper_configure
25
- end
29
+ config.before(:suite) { Flipper::TestHelp.flipper_configure }
30
+ config.before(:each) { flipper_reset }
26
31
  end
27
32
  end
28
-
29
33
  if defined?(ActiveSupport)
30
34
  ActiveSupport.on_load(:active_support_test_case) do
35
+ Flipper::TestHelp.flipper_configure
36
+
31
37
  ActiveSupport::TestCase.class_eval do
32
38
  include Flipper::TestHelp
33
39
 
34
- setup :flipper_configure
35
40
  setup :flipper_reset
36
41
  end
37
42
  end
@@ -1,5 +1,5 @@
1
1
  module Flipper
2
- VERSION = '1.2.1'.freeze
2
+ VERSION = '1.2.2'.freeze
3
3
 
4
4
  REQUIRED_RUBY_VERSION = '2.6'.freeze
5
5
  NEXT_REQUIRED_RUBY_VERSION = '3.0'.freeze
@@ -16,14 +16,14 @@ RSpec.describe Flipper::CLI do
16
16
  describe "enable" do
17
17
  describe "feature" do
18
18
  it do
19
- expect(subject).to have_attributes(status: 0, stdout: /feature.*enabled/)
19
+ expect(subject).to have_attributes(status: 0, stdout: /feature.*\e\[32m.*enabled/)
20
20
  expect(Flipper).to be_enabled(:feature)
21
21
  end
22
22
  end
23
23
 
24
24
  describe "-a User;1 feature" do
25
25
  it do
26
- expect(subject).to have_attributes(status: 0, stdout: /feature.*enabled.*User;1/m)
26
+ expect(subject).to have_attributes(status: 0, stdout: /feature.*\e\[33m.*enabled.*User;1/m)
27
27
  expect(Flipper).to be_enabled(:feature, Flipper::Actor.new("User;1"))
28
28
  end
29
29
  end
@@ -142,6 +142,28 @@ RSpec.describe Flipper::CLI do
142
142
  end
143
143
  end
144
144
 
145
+ context "bundler is not installed" do
146
+ let(:argv) { "list" }
147
+
148
+ around do |example|
149
+ original_bundler = Bundler
150
+ begin
151
+ Object.send(:remove_const, :Bundler)
152
+ example.run
153
+ ensure
154
+ Object.const_set(:Bundler, original_bundler)
155
+ end
156
+ end
157
+
158
+ it "should not raise an error" do
159
+ Flipper.enable(:enabled_feature)
160
+ Flipper.enable_group(:enabled_groups, :admins)
161
+ Flipper.add(:disabled_feature)
162
+
163
+ expect(subject).to have_attributes(status: 0, stdout: /enabled_feature.*enabled_groups.*disabled_feature/m)
164
+ end
165
+ end
166
+
145
167
  def run(argv)
146
168
  original_stdout = $stdout
147
169
  original_stderr = $stderr
@@ -150,6 +172,9 @@ RSpec.describe Flipper::CLI do
150
172
  $stderr = StringIO.new
151
173
  status = 0
152
174
 
175
+ # Prentend this a TTY so we can test colorization
176
+ allow($stdout).to receive(:tty?).and_return(true)
177
+
153
178
  begin
154
179
  Flipper::CLI.run(argv)
155
180
  rescue SystemExit => e
@@ -12,10 +12,9 @@ RSpec.describe Flipper::Cloud::Configuration do
12
12
  end
13
13
 
14
14
  it "can set token from ENV var" do
15
- with_env "FLIPPER_CLOUD_TOKEN" => "from_env" do
16
- instance = described_class.new(required_options.reject { |k, v| k == :token })
17
- expect(instance.token).to eq("from_env")
18
- end
15
+ ENV["FLIPPER_CLOUD_TOKEN"] = "from_env"
16
+ instance = described_class.new(required_options.reject { |k, v| k == :token })
17
+ expect(instance.token).to eq("from_env")
19
18
  end
20
19
 
21
20
  it "can set instrumenter" do
@@ -30,10 +29,9 @@ RSpec.describe Flipper::Cloud::Configuration do
30
29
  end
31
30
 
32
31
  it "can set read_timeout from ENV var" do
33
- with_env "FLIPPER_CLOUD_READ_TIMEOUT" => "9" do
34
- instance = described_class.new(required_options.reject { |k, v| k == :read_timeout })
35
- expect(instance.read_timeout).to eq(9)
36
- end
32
+ ENV["FLIPPER_CLOUD_READ_TIMEOUT"] = "9"
33
+ instance = described_class.new(required_options.reject { |k, v| k == :read_timeout })
34
+ expect(instance.read_timeout).to eq(9)
37
35
  end
38
36
 
39
37
  it "can set open_timeout" do
@@ -42,10 +40,9 @@ RSpec.describe Flipper::Cloud::Configuration do
42
40
  end
43
41
 
44
42
  it "can set open_timeout from ENV var" do
45
- with_env "FLIPPER_CLOUD_OPEN_TIMEOUT" => "9" do
46
- instance = described_class.new(required_options.reject { |k, v| k == :open_timeout })
47
- expect(instance.open_timeout).to eq(9)
48
- end
43
+ ENV["FLIPPER_CLOUD_OPEN_TIMEOUT"] = "9"
44
+ instance = described_class.new(required_options.reject { |k, v| k == :open_timeout })
45
+ expect(instance.open_timeout).to eq(9)
49
46
  end
50
47
 
51
48
  it "can set write_timeout" do
@@ -54,10 +51,9 @@ RSpec.describe Flipper::Cloud::Configuration do
54
51
  end
55
52
 
56
53
  it "can set write_timeout from ENV var" do
57
- with_env "FLIPPER_CLOUD_WRITE_TIMEOUT" => "9" do
58
- instance = described_class.new(required_options.reject { |k, v| k == :write_timeout })
59
- expect(instance.write_timeout).to eq(9)
60
- end
54
+ ENV["FLIPPER_CLOUD_WRITE_TIMEOUT"] = "9"
55
+ instance = described_class.new(required_options.reject { |k, v| k == :write_timeout })
56
+ expect(instance.write_timeout).to eq(9)
61
57
  end
62
58
 
63
59
  it "can set sync_interval" do
@@ -66,10 +62,9 @@ RSpec.describe Flipper::Cloud::Configuration do
66
62
  end
67
63
 
68
64
  it "can set sync_interval from ENV var" do
69
- with_env "FLIPPER_CLOUD_SYNC_INTERVAL" => "15" do
70
- instance = described_class.new(required_options.reject { |k, v| k == :sync_interval })
71
- expect(instance.sync_interval).to eq(15)
72
- end
65
+ ENV["FLIPPER_CLOUD_SYNC_INTERVAL"] = "15"
66
+ instance = described_class.new(required_options.reject { |k, v| k == :sync_interval })
67
+ expect(instance.sync_interval).to eq(15)
73
68
  end
74
69
 
75
70
  it "passes sync_interval into sync adapter" do
@@ -87,10 +82,9 @@ RSpec.describe Flipper::Cloud::Configuration do
87
82
  end
88
83
 
89
84
  it "defaults debug_output to STDOUT if FLIPPER_CLOUD_DEBUG_OUTPUT_STDOUT set to true" do
90
- with_env "FLIPPER_CLOUD_DEBUG_OUTPUT_STDOUT" => "true" do
91
- instance = described_class.new(required_options)
85
+ ENV["FLIPPER_CLOUD_DEBUG_OUTPUT_STDOUT"] = "true"
86
+ instance = described_class.new(required_options)
92
87
  expect(instance.debug_output).to eq(STDOUT)
93
- end
94
88
  end
95
89
 
96
90
  it "defaults adapter block" do
@@ -128,10 +122,9 @@ RSpec.describe Flipper::Cloud::Configuration do
128
122
  end
129
123
 
130
124
  it "can override URL using ENV var" do
131
- with_env "FLIPPER_CLOUD_URL" => "https://example.com" do
132
- instance = described_class.new(required_options.reject { |k, v| k == :url })
133
- expect(instance.url).to eq("https://example.com")
134
- end
125
+ ENV["FLIPPER_CLOUD_URL"] = "https://example.com"
126
+ instance = described_class.new(required_options.reject { |k, v| k == :url })
127
+ expect(instance.url).to eq("https://example.com")
135
128
  end
136
129
 
137
130
  it "defaults sync_method to :poll" do
@@ -150,12 +143,11 @@ RSpec.describe Flipper::Cloud::Configuration do
150
143
  end
151
144
 
152
145
  it "sets sync_method to :webhook if FLIPPER_CLOUD_SYNC_SECRET set" do
153
- with_env "FLIPPER_CLOUD_SYNC_SECRET" => "abc" do
154
- instance = described_class.new(required_options)
146
+ ENV["FLIPPER_CLOUD_SYNC_SECRET"] = "abc"
147
+ instance = described_class.new(required_options)
155
148
 
156
- expect(instance.sync_method).to eq(:webhook)
157
- expect(instance.adapter).to be_instance_of(Flipper::Adapters::DualWrite)
158
- end
149
+ expect(instance.sync_method).to eq(:webhook)
150
+ expect(instance.adapter).to be_instance_of(Flipper::Adapters::DualWrite)
159
151
  end
160
152
 
161
153
  it "can set sync_secret" do
@@ -164,10 +156,9 @@ RSpec.describe Flipper::Cloud::Configuration do
164
156
  end
165
157
 
166
158
  it "can override sync_secret using ENV var" do
167
- with_env "FLIPPER_CLOUD_SYNC_SECRET" => "from_env" do
168
- instance = described_class.new(required_options.reject { |k, v| k == :sync_secret })
169
- expect(instance.sync_secret).to eq("from_env")
170
- end
159
+ ENV["FLIPPER_CLOUD_SYNC_SECRET"] = "from_env"
160
+ instance = described_class.new(required_options.reject { |k, v| k == :sync_secret })
161
+ expect(instance.sync_secret).to eq("from_env")
171
162
  end
172
163
 
173
164
  it "can sync with cloud" do
@@ -49,19 +49,18 @@ RSpec.describe Flipper::Cloud::Telemetry::BackoffPolicy do
49
49
  end
50
50
 
51
51
  it "from env" do
52
- env = {
52
+ ENV.update(
53
53
  "FLIPPER_BACKOFF_MIN_TIMEOUT_MS" => "1000",
54
54
  "FLIPPER_BACKOFF_MAX_TIMEOUT_MS" => "2000",
55
55
  "FLIPPER_BACKOFF_MULTIPLIER" => "1.9",
56
56
  "FLIPPER_BACKOFF_RANDOMIZATION_FACTOR" => "0.1",
57
- }
58
- with_env env do
59
- policy = described_class.new
60
- expect(policy.min_timeout_ms).to eq(1000)
61
- expect(policy.max_timeout_ms).to eq(2000)
62
- expect(policy.multiplier).to eq(1.9)
63
- expect(policy.randomization_factor).to eq(0.1)
64
- end
57
+ )
58
+
59
+ policy = described_class.new
60
+ expect(policy.min_timeout_ms).to eq(1000)
61
+ expect(policy.max_timeout_ms).to eq(2000)
62
+ expect(policy.multiplier).to eq(1.9)
63
+ expect(policy.randomization_factor).to eq(0.1)
65
64
  end
66
65
  end
67
66
 
@@ -55,9 +55,8 @@ RSpec.describe Flipper::Cloud do
55
55
  end
56
56
 
57
57
  it 'can initialize with no token explicitly provided' do
58
- with_env 'FLIPPER_CLOUD_TOKEN' => 'asdf' do
59
- expect(described_class.new).to be_instance_of(Flipper::Cloud::DSL)
60
- end
58
+ ENV['FLIPPER_CLOUD_TOKEN'] = 'asdf'
59
+ expect(described_class.new).to be_instance_of(Flipper::Cloud::DSL)
61
60
  end
62
61
 
63
62
  it 'can set instrumenter' do
@@ -33,28 +33,25 @@ RSpec.describe Flipper::Engine do
33
33
  let(:adapter) { Flipper.adapter.adapter }
34
34
 
35
35
  it 'can set strict=true from ENV' do
36
- with_env 'FLIPPER_STRICT' => 'true' do
37
- subject
38
- expect(config.strict).to eq(:raise)
39
- expect(adapter).to be_instance_of(Flipper::Adapters::Strict)
40
- end
36
+ ENV['FLIPPER_STRICT'] = 'true'
37
+ subject
38
+ expect(config.strict).to eq(:raise)
39
+ expect(adapter).to be_instance_of(Flipper::Adapters::Strict)
41
40
  end
42
41
 
43
42
  it 'can set strict=warn from ENV' do
44
- with_env 'FLIPPER_STRICT' => 'warn' do
45
- subject
46
- expect(config.strict).to eq(:warn)
47
- expect(adapter).to be_instance_of(Flipper::Adapters::Strict)
48
- expect(adapter.handler).to be(:warn)
49
- end
43
+ ENV['FLIPPER_STRICT'] = 'warn'
44
+ subject
45
+ expect(config.strict).to eq(:warn)
46
+ expect(adapter).to be_instance_of(Flipper::Adapters::Strict)
47
+ expect(adapter.handler).to be(:warn)
50
48
  end
51
49
 
52
50
  it 'can set strict=false from ENV' do
53
- with_env 'FLIPPER_STRICT' => 'false' do
54
- subject
55
- expect(config.strict).to eq(false)
56
- expect(adapter).to be_instance_of(Flipper::Adapters::Memory)
57
- end
51
+ ENV['FLIPPER_STRICT'] = 'false'
52
+ subject
53
+ expect(config.strict).to eq(false)
54
+ expect(adapter).to be_instance_of(Flipper::Adapters::Memory)
58
55
  end
59
56
 
60
57
  [true, :raise, :warn].each do |value|
@@ -104,39 +101,34 @@ RSpec.describe Flipper::Engine do
104
101
  it_behaves_like 'config.strict'
105
102
 
106
103
  it 'can set env_key from ENV' do
107
- with_env 'FLIPPER_ENV_KEY' => 'flopper' do
108
- subject
109
- expect(config.env_key).to eq('flopper')
110
- end
104
+ ENV['FLIPPER_ENV_KEY'] = 'flopper'
105
+ subject
106
+ expect(config.env_key).to eq('flopper')
111
107
  end
112
108
 
113
109
  it 'can set memoize from ENV' do
114
- with_env 'FLIPPER_MEMOIZE' => 'false' do
115
- subject
116
- expect(config.memoize).to eq(false)
117
- end
110
+ ENV['FLIPPER_MEMOIZE'] = 'false'
111
+ subject
112
+ expect(config.memoize).to eq(false)
118
113
  end
119
114
 
120
115
  it 'can set preload from ENV' do
121
- with_env 'FLIPPER_PRELOAD' => 'false' do
122
- subject
123
- expect(config.preload).to eq(false)
124
- end
116
+ ENV['FLIPPER_PRELOAD'] = 'false'
117
+ subject
118
+ expect(config.preload).to eq(false)
125
119
  end
126
120
 
127
121
  it 'can set instrumenter from ENV' do
128
122
  stub_const('My::Cool::Instrumenter', Class.new)
129
- with_env 'FLIPPER_INSTRUMENTER' => 'My::Cool::Instrumenter' do
130
- subject
131
- expect(config.instrumenter).to eq(My::Cool::Instrumenter)
132
- end
123
+ ENV['FLIPPER_INSTRUMENTER'] = 'My::Cool::Instrumenter'
124
+ subject
125
+ expect(config.instrumenter).to eq(My::Cool::Instrumenter)
133
126
  end
134
127
 
135
128
  it 'can set log from ENV' do
136
- with_env 'FLIPPER_LOG' => 'false' do
137
- subject
138
- expect(config.log).to eq(false)
139
- end
129
+ ENV['FLIPPER_LOG'] = 'false'
130
+ subject
131
+ expect(config.log).to eq(false)
140
132
  end
141
133
 
142
134
  it 'sets defaults' do
@@ -220,10 +212,8 @@ RSpec.describe Flipper::Engine do
220
212
  end
221
213
 
222
214
  context 'with cloud' do
223
- around do |example|
224
- with_env "FLIPPER_CLOUD_TOKEN" => "test-token" do
225
- example.run
226
- end
215
+ before do
216
+ ENV["FLIPPER_CLOUD_TOKEN"] = "test-token"
227
217
  end
228
218
 
229
219
  # App for Rack::Test
@@ -248,10 +238,8 @@ RSpec.describe Flipper::Engine do
248
238
  end
249
239
 
250
240
  context "with CLOUD_SYNC_SECRET" do
251
- around do |example|
252
- with_env "FLIPPER_CLOUD_SYNC_SECRET" => "test-secret" do
253
- example.run
254
- end
241
+ before do
242
+ ENV["FLIPPER_CLOUD_SYNC_SECRET"] = "test-secret"
255
243
  end
256
244
 
257
245
  let(:request_body) do
@@ -296,10 +284,9 @@ RSpec.describe Flipper::Engine do
296
284
 
297
285
  context "without FLIPPER_CLOUD_TOKEN" do
298
286
  it "gracefully skips configuring webhook app" do
299
- with_env "FLIPPER_CLOUD_TOKEN" => nil do
300
- application.initialize!
301
- expect(Flipper.instance).to be_a(Flipper::DSL)
302
- end
287
+ ENV["FLIPPER_CLOUD_TOKEN"] = nil
288
+ application.initialize!
289
+ expect(Flipper.instance).to be_a(Flipper::DSL)
303
290
 
304
291
  post "/_flipper"
305
292
  expect(last_response.status).to eq(404)
@@ -29,10 +29,15 @@ end
29
29
 
30
30
  class TestHelpTest < ActionDispatch::SystemTestCase
31
31
  # Any driver that runs the app in a separate thread will test what we want here.
32
- driven_by :cuprite
32
+ driven_by :cuprite, options: { process_timeout: 30 }
33
33
 
34
- # Ensure this test uses this app instance
35
- setup { Rails.application = TestApp.instance }
34
+ setup do
35
+ # Reconfigure Flipper since other tests change the adapter.
36
+ flipper_configure
37
+
38
+ # Ensure this test uses this app instance
39
+ Rails.application = TestApp.instance
40
+ end
36
41
 
37
42
  test "configures a shared adapter between tests and app" do
38
43
  Flipper.disable(:test)
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: 1.2.1
4
+ version: 1.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Nunemaker
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-15 00:00:00.000000000 Z
11
+ date: 2024-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -286,7 +286,6 @@ files:
286
286
  - spec/flipper_spec.rb
287
287
  - spec/spec_helper.rb
288
288
  - spec/support/actor_names.yml
289
- - spec/support/climate_control.rb
290
289
  - spec/support/descriptions.yml
291
290
  - spec/support/fake_backoff_policy.rb
292
291
  - spec/support/fake_udp_socket.rb
@@ -307,7 +306,7 @@ metadata:
307
306
  homepage_uri: https://www.flippercloud.io
308
307
  source_code_uri: https://github.com/flippercloud/flipper
309
308
  bug_tracker_uri: https://github.com/flippercloud/flipper/issues
310
- changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.2.1
309
+ changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.2.2
311
310
  post_install_message:
312
311
  rdoc_options: []
313
312
  require_paths:
@@ -421,7 +420,6 @@ test_files:
421
420
  - spec/flipper_spec.rb
422
421
  - spec/spec_helper.rb
423
422
  - spec/support/actor_names.yml
424
- - spec/support/climate_control.rb
425
423
  - spec/support/descriptions.yml
426
424
  - spec/support/fake_backoff_policy.rb
427
425
  - spec/support/fake_udp_socket.rb
@@ -1,7 +0,0 @@
1
- require 'climate_control'
2
-
3
- RSpec.configure do |config|
4
- def with_env(options = {}, &block)
5
- ClimateControl.modify(options, &block)
6
- end
7
- end