flipper 1.2.0 → 1.2.2

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: c4f95a5fd56395048ef3fa3f0fd4737db8136f2e814dca352dc167c0f421a8a4
4
- data.tar.gz: 2e42041673d4ddcf0a01b7ed1d21424dd421e4288595f2982c93101863c6fbc0
3
+ metadata.gz: 6ff734c4221d1ea2694fdf4e9e463085f60242e698b8702389c53ccc6a17e87b
4
+ data.tar.gz: 5666852d9f7416d30919a188c5e3c46cb202d66d332c482aba56c3d496437282
5
5
  SHA512:
6
- metadata.gz: 70fd697b619ea770334d35b97035184ce3139805fdb3613e0fe950efbfd69898b976524793fe64eabaa9fd0c6a4374eac35c78ef014e39f4fce8313cbd599f91
7
- data.tar.gz: f204a5d8518b120e9299d2bf5b114cf73889784f4bef1f836f7f290964f5cc73a753294668e9e9257ae44800c5784e9ea58f4b0d5265c49f8c056bbf352a550a
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,35 +1,42 @@
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
18
25
 
19
- if defined?(RSpec)
26
+ if defined?(RSpec) && RSpec.respond_to?(:configure)
20
27
  RSpec.configure do |config|
21
28
  config.include Flipper::TestHelp
22
- config.before(:all) { flipper_configure }
29
+ config.before(:suite) { Flipper::TestHelp.flipper_configure }
23
30
  config.before(:each) { flipper_reset }
24
31
  end
25
32
  end
26
-
27
33
  if defined?(ActiveSupport)
28
34
  ActiveSupport.on_load(:active_support_test_case) do
35
+ Flipper::TestHelp.flipper_configure
36
+
29
37
  ActiveSupport::TestCase.class_eval do
30
38
  include Flipper::TestHelp
31
39
 
32
- setup :flipper_configure
33
40
  setup :flipper_reset
34
41
  end
35
42
  end
@@ -1,5 +1,5 @@
1
1
  module Flipper
2
- VERSION = '1.2.0'.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.0
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-11 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.0
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