flipper 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +25 -1
  3. data/.github/workflows/examples.yml +7 -1
  4. data/Changelog.md +1 -638
  5. data/Gemfile +5 -1
  6. data/README.md +21 -21
  7. data/Rakefile +2 -2
  8. data/exe/flipper +5 -0
  9. data/flipper.gemspec +6 -2
  10. data/lib/flipper/adapters/http/client.rb +25 -16
  11. data/lib/flipper/adapters/strict.rb +11 -8
  12. data/lib/flipper/cli.rb +240 -0
  13. data/lib/flipper/cloud/configuration.rb +7 -1
  14. data/lib/flipper/cloud/middleware.rb +5 -5
  15. data/lib/flipper/cloud/telemetry/submitter.rb +2 -2
  16. data/lib/flipper/cloud.rb +1 -1
  17. data/lib/flipper/engine.rb +32 -17
  18. data/lib/flipper/instrumentation/log_subscriber.rb +12 -3
  19. data/lib/flipper/metadata.rb +3 -1
  20. data/lib/flipper/test_help.rb +36 -0
  21. data/lib/flipper/version.rb +11 -1
  22. data/lib/generators/flipper/setup_generator.rb +63 -0
  23. data/lib/generators/flipper/templates/update/migrations/01_create_flipper_tables.rb.erb +22 -0
  24. data/lib/generators/flipper/templates/update/migrations/02_change_flipper_gates_value_to_text.rb.erb +18 -0
  25. data/lib/generators/flipper/update_generator.rb +35 -0
  26. data/spec/fixtures/environment.rb +1 -0
  27. data/spec/flipper/adapter_builder_spec.rb +1 -2
  28. data/spec/flipper/adapters/http/client_spec.rb +61 -0
  29. data/spec/flipper/adapters/http_spec.rb +92 -75
  30. data/spec/flipper/adapters/strict_spec.rb +11 -9
  31. data/spec/flipper/cli_spec.rb +164 -0
  32. data/spec/flipper/cloud/configuration_spec.rb +9 -2
  33. data/spec/flipper/cloud/dsl_spec.rb +5 -5
  34. data/spec/flipper/cloud/middleware_spec.rb +8 -8
  35. data/spec/flipper/cloud/telemetry/submitter_spec.rb +24 -24
  36. data/spec/flipper/cloud/telemetry_spec.rb +1 -1
  37. data/spec/flipper/cloud_spec.rb +4 -4
  38. data/spec/flipper/engine_spec.rb +76 -11
  39. data/spec/flipper/instrumentation/log_subscriber_spec.rb +9 -2
  40. data/spec/flipper_spec.rb +1 -1
  41. data/spec/spec_helper.rb +1 -0
  42. data/spec/support/spec_helpers.rb +10 -4
  43. data/test_rails/generators/flipper/setup_generator_test.rb +64 -0
  44. data/test_rails/generators/flipper/update_generator_test.rb +96 -0
  45. data/test_rails/helper.rb +19 -2
  46. data/test_rails/system/test_help_test.rb +46 -0
  47. metadata +25 -8
@@ -0,0 +1,64 @@
1
+ require "helper"
2
+ require "generators/flipper/setup_generator"
3
+
4
+ class SetupGeneratorTest < Rails::Generators::TestCase
5
+ tests Flipper::Generators::SetupGenerator
6
+ ROOT = File.expand_path("../../../tmp/generators", __dir__)
7
+ destination ROOT
8
+ setup :prepare_destination
9
+
10
+ test "invokes flipper:active_record generator if ActiveRecord adapter defined" do
11
+ begin
12
+ load 'flipper/adapters/active_record.rb'
13
+ run_generator
14
+ assert_migration "db/migrate/create_flipper_tables.rb"
15
+ ensure
16
+ Flipper::Adapters.send(:remove_const, :ActiveRecord)
17
+ end
18
+ end
19
+
20
+ test "does not invoke flipper:active_record generator if ActiveRecord adapter not defined" do
21
+ # Ensure adapter not defined
22
+ Flipper::Adapters.send(:remove_const, :ActiveRecord) rescue nil
23
+
24
+ run_generator
25
+ assert_no_migration "db/migrate/create_flipper_tables.rb"
26
+ end
27
+
28
+ %w(.env.development .env.local .env).each do |file|
29
+ test "configures Flipper Cloud token in #{file} if it exists" do
30
+ File.write("#{ROOT}/#{file}", "")
31
+ run_generator %w(--token abc123)
32
+ assert_file file, /^FLIPPER_CLOUD_TOKEN=abc123$/m
33
+ end
34
+ end
35
+
36
+ test "configures Flipper Cloud token in .env.development before .env" do
37
+ File.write("#{ROOT}/.env.development", "")
38
+ File.write("#{ROOT}/.env", "")
39
+
40
+ run_generator %w(--token abc123)
41
+ assert_file ".env.development", /^FLIPPER_CLOUD_TOKEN=abc123$/m
42
+ assert_file ".env", ""
43
+ end
44
+
45
+ test "does not write to .env if no token provided" do
46
+ File.write("#{ROOT}/.env", "")
47
+ run_generator
48
+ assert_file ".env", ""
49
+ end
50
+
51
+ test "configures Flipper Cloud token in config/credentials.yml.enc if credentials.yml.enc exist" do
52
+ Dir.chdir(ROOT) do
53
+ FileUtils.mkdir_p("config")
54
+ ENV["RAILS_MASTER_KEY"] = "a" * 32
55
+ Rails.application = Class.new(Rails::Application)
56
+ Rails.application.credentials.write("")
57
+
58
+ run_generator %w(--token abc123)
59
+ assert_file "config/credentials.yml.enc"
60
+ expected_config = { flipper: { cloud_token: "abc123" } }
61
+ assert_equal expected_config, Rails.application.credentials.config
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,96 @@
1
+ require "helper"
2
+ require "generators/flipper/update_generator"
3
+
4
+ class UpdateGeneratorTest < Rails::Generators::TestCase
5
+ tests Flipper::Generators::UpdateGenerator
6
+ ROOT = File.expand_path("../../../../tmp/generators", __FILE__)
7
+ destination ROOT
8
+ setup :prepare_destination
9
+
10
+ setup do
11
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
12
+ end
13
+
14
+ teardown do
15
+ ActiveRecord::Base.connection.close
16
+ end
17
+
18
+ test "generates migrations" do
19
+ run_generator
20
+
21
+ assert_migration "db/migrate/create_flipper_tables.rb" do |migration|
22
+ assert_method :up, migration do |up|
23
+ assert_match(/create_table :flipper_features/, up)
24
+ assert_match(/create_table :flipper_gates/, up)
25
+ end
26
+
27
+ assert_method :down, migration do |down|
28
+ assert_match(/drop_table :flipper_features/, down)
29
+ assert_match(/drop_table :flipper_gates/, down)
30
+ end
31
+ end
32
+
33
+ assert_migration "db/migrate/change_flipper_gates_value_to_text.rb" do |migration|
34
+ [:up, :down].each do |dir|
35
+ assert_method :up, migration do |method|
36
+ assert_match(/change_column/, method)
37
+ end
38
+ end
39
+ end
40
+
41
+ require_migrations
42
+
43
+ silence { CreateFlipperTables.migrate(:up) }
44
+ assert ActiveRecord::Base.connection.table_exists?(:flipper_features)
45
+ assert ActiveRecord::Base.connection.table_exists?(:flipper_gates)
46
+
47
+ assert ActiveRecord::Base.connection.column_exists?(:flipper_gates, :value, :string)
48
+ silence { ChangeFlipperGatesValueToText.migrate(:up) }
49
+ assert ActiveRecord::Base.connection.column_exists?(:flipper_gates, :value, :text)
50
+
51
+ silence { ChangeFlipperGatesValueToText.migrate(:down) }
52
+ assert ActiveRecord::Base.connection.column_exists?(:flipper_gates, :value, :string)
53
+
54
+ silence { CreateFlipperTables.migrate(:down) }
55
+ refute ActiveRecord::Base.connection.table_exists?(:flipper_features)
56
+ refute ActiveRecord::Base.connection.table_exists?(:flipper_gates)
57
+ end
58
+
59
+ test "ChangeFlipperGatesValueToText is a noop if value is already text" do
60
+ self.class.generator_class = Flipper::Generators::ActiveRecordGenerator
61
+ run_generator
62
+
63
+ self.class.generator_class = Flipper::Generators::UpdateGenerator
64
+ run_generator
65
+
66
+ assert_migration "db/migrate/create_flipper_tables.rb" do |migration|
67
+ assert_method :up, migration do |up|
68
+ assert_match /text :value/, up
69
+ end
70
+ end
71
+
72
+ assert_migration "db/migrate/change_flipper_gates_value_to_text.rb"
73
+
74
+ require_migrations
75
+
76
+ silence { CreateFlipperTables.migrate(:up) }
77
+ assert ActiveRecord::Base.connection.column_exists?(:flipper_gates, :value, :text)
78
+
79
+ assert_nothing_raised do
80
+ silence { ChangeFlipperGatesValueToText.migrate(:up) }
81
+ end
82
+ assert ActiveRecord::Base.connection.column_exists?(:flipper_gates, :value, :text)
83
+ end
84
+
85
+ def require_migrations
86
+ # If these are not reloaded, then test order can cause failures
87
+ Object.send(:remove_const, :CreateFlipperTables) if defined?(::CreateFlipperTables)
88
+ Object.send(:remove_const, :ChangeFlipperGatesValueToText) if defined?(::ChangeFlipperGatesValueToText)
89
+
90
+ Dir.glob("#{ROOT}/db/migrate/*.rb").each do |file|
91
+ assert_nothing_raised do
92
+ load file
93
+ end
94
+ end
95
+ end
96
+ end
data/test_rails/helper.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'rubygems'
2
- require 'bundler'
3
- Bundler.setup(:default)
2
+ require 'bundler/setup'
3
+ require 'minitest/autorun'
4
4
  require 'rails'
5
5
  require 'rails/test_help'
6
6
 
@@ -9,3 +9,20 @@ begin
9
9
  rescue NoMethodError
10
10
  # no biggie, means we are on older version of AS that doesn't have this option
11
11
  end
12
+
13
+ def silence
14
+ # Store the original stderr and stdout in order to restore them later
15
+ original_stderr = $stderr
16
+ original_stdout = $stdout
17
+
18
+ # Redirect stderr and stdout
19
+ output = $stderr = $stdout = StringIO.new
20
+
21
+ yield
22
+
23
+ $stderr = original_stderr
24
+ $stdout = original_stdout
25
+
26
+ # Return output
27
+ output.string
28
+ end
@@ -0,0 +1,46 @@
1
+ require_relative "../helper"
2
+
3
+ # Not worth trying to test on old Rails versions
4
+ return unless Rails::VERSION::MAJOR >= 7
5
+
6
+ require "capybara/cuprite"
7
+ require "flipper"
8
+ require "flipper/test_help"
9
+
10
+ require 'action_dispatch/system_testing/server'
11
+ ActionDispatch::SystemTesting::Server.silence_puma = true
12
+
13
+ class TestApp < Rails::Application
14
+ config.load_defaults "#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}"
15
+ config.eager_load = false
16
+ config.logger = ActiveSupport::Logger.new(StringIO.new)
17
+ routes.append do
18
+ root to: "features#index"
19
+ end
20
+ end
21
+
22
+ TestApp.initialize!
23
+
24
+ class FeaturesController < ActionController::Base
25
+ def index
26
+ render json: Flipper.enabled?(:test) ? "Enabled" : "Disabled"
27
+ end
28
+ end
29
+
30
+ class TestHelpTest < ActionDispatch::SystemTestCase
31
+ # Any driver that runs the app in a separate thread will test what we want here.
32
+ driven_by :cuprite
33
+
34
+ # Ensure this test uses this app instance
35
+ setup { Rails.application = TestApp.instance }
36
+
37
+ test "configures a shared adapter between tests and app" do
38
+ Flipper.disable(:test)
39
+ visit "/"
40
+ assert_selector "*", text: "Disabled"
41
+
42
+ Flipper.enable(:test)
43
+ visit "/"
44
+ assert_selector "*", text: "Enabled"
45
+ end
46
+ end
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.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Nunemaker
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2023-12-09 00:00:00.000000000 Z
11
+ date: 2024-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -26,7 +26,8 @@ dependencies:
26
26
  version: '2'
27
27
  description:
28
28
  email: support@flippercloud.io
29
- executables: []
29
+ executables:
30
+ - flipper
30
31
  extensions: []
31
32
  extra_rdoc_files: []
32
33
  files:
@@ -82,6 +83,7 @@ files:
82
83
  - examples/percentage_of_actors_group.rb
83
84
  - examples/percentage_of_time.rb
84
85
  - examples/strict.rb
86
+ - exe/flipper
85
87
  - flipper-cloud.gemspec
86
88
  - flipper.gemspec
87
89
  - lib/flipper.rb
@@ -107,6 +109,7 @@ files:
107
109
  - lib/flipper/adapters/sync/feature_synchronizer.rb
108
110
  - lib/flipper/adapters/sync/interval_synchronizer.rb
109
111
  - lib/flipper/adapters/sync/synchronizer.rb
112
+ - lib/flipper/cli.rb
110
113
  - lib/flipper/cloud.rb
111
114
  - lib/flipper/cloud/configuration.rb
112
115
  - lib/flipper/cloud/dsl.rb
@@ -176,6 +179,7 @@ files:
176
179
  - lib/flipper/serializers/json.rb
177
180
  - lib/flipper/spec/shared_adapter_specs.rb
178
181
  - lib/flipper/test/shared_adapter_test.rb
182
+ - lib/flipper/test_help.rb
179
183
  - lib/flipper/type.rb
180
184
  - lib/flipper/typecast.rb
181
185
  - lib/flipper/types/actor.rb
@@ -185,6 +189,11 @@ files:
185
189
  - lib/flipper/types/percentage_of_actors.rb
186
190
  - lib/flipper/types/percentage_of_time.rb
187
191
  - lib/flipper/version.rb
192
+ - lib/generators/flipper/setup_generator.rb
193
+ - lib/generators/flipper/templates/update/migrations/01_create_flipper_tables.rb.erb
194
+ - lib/generators/flipper/templates/update/migrations/02_change_flipper_gates_value_to_text.rb.erb
195
+ - lib/generators/flipper/update_generator.rb
196
+ - spec/fixtures/environment.rb
188
197
  - spec/fixtures/feature.json
189
198
  - spec/fixtures/flipper_pstore_1679087600.json
190
199
  - spec/flipper/actor_spec.rb
@@ -193,6 +202,7 @@ files:
193
202
  - spec/flipper/adapters/dual_write_spec.rb
194
203
  - spec/flipper/adapters/failover_spec.rb
195
204
  - spec/flipper/adapters/failsafe_spec.rb
205
+ - spec/flipper/adapters/http/client_spec.rb
196
206
  - spec/flipper/adapters/http_spec.rb
197
207
  - spec/flipper/adapters/instrumented_spec.rb
198
208
  - spec/flipper/adapters/memoizable_spec.rb
@@ -205,6 +215,7 @@ files:
205
215
  - spec/flipper/adapters/sync/interval_synchronizer_spec.rb
206
216
  - spec/flipper/adapters/sync/synchronizer_spec.rb
207
217
  - spec/flipper/adapters/sync_spec.rb
218
+ - spec/flipper/cli_spec.rb
208
219
  - spec/flipper/cloud/configuration_spec.rb
209
220
  - spec/flipper/cloud/dsl_spec.rb
210
221
  - spec/flipper/cloud/message_verifier_spec.rb
@@ -284,7 +295,10 @@ files:
284
295
  - test/adapters/memory_test.rb
285
296
  - test/adapters/pstore_test.rb
286
297
  - test/test_helper.rb
298
+ - test_rails/generators/flipper/setup_generator_test.rb
299
+ - test_rails/generators/flipper/update_generator_test.rb
287
300
  - test_rails/helper.rb
301
+ - test_rails/system/test_help_test.rb
288
302
  homepage: https://www.flippercloud.io/docs
289
303
  licenses:
290
304
  - MIT
@@ -293,7 +307,7 @@ metadata:
293
307
  homepage_uri: https://www.flippercloud.io
294
308
  source_code_uri: https://github.com/flippercloud/flipper
295
309
  bug_tracker_uri: https://github.com/flippercloud/flipper/issues
296
- changelog_uri: https://github.com/flippercloud/flipper/blob/main/Changelog.md
310
+ changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.2.0
297
311
  post_install_message:
298
312
  rdoc_options: []
299
313
  require_paths:
@@ -302,18 +316,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
302
316
  requirements:
303
317
  - - ">="
304
318
  - !ruby/object:Gem::Version
305
- version: '0'
319
+ version: '2.6'
306
320
  required_rubygems_version: !ruby/object:Gem::Requirement
307
321
  requirements:
308
322
  - - ">="
309
323
  - !ruby/object:Gem::Version
310
324
  version: '0'
311
325
  requirements: []
312
- rubygems_version: 3.4.10
326
+ rubygems_version: 3.5.3
313
327
  signing_key:
314
328
  specification_version: 4
315
- summary: Beautiful, performant feature flags for Ruby.
329
+ summary: Beautiful, performant feature flags for Ruby and Rails.
316
330
  test_files:
331
+ - spec/fixtures/environment.rb
317
332
  - spec/fixtures/feature.json
318
333
  - spec/fixtures/flipper_pstore_1679087600.json
319
334
  - spec/flipper/actor_spec.rb
@@ -322,6 +337,7 @@ test_files:
322
337
  - spec/flipper/adapters/dual_write_spec.rb
323
338
  - spec/flipper/adapters/failover_spec.rb
324
339
  - spec/flipper/adapters/failsafe_spec.rb
340
+ - spec/flipper/adapters/http/client_spec.rb
325
341
  - spec/flipper/adapters/http_spec.rb
326
342
  - spec/flipper/adapters/instrumented_spec.rb
327
343
  - spec/flipper/adapters/memoizable_spec.rb
@@ -334,6 +350,7 @@ test_files:
334
350
  - spec/flipper/adapters/sync/interval_synchronizer_spec.rb
335
351
  - spec/flipper/adapters/sync/synchronizer_spec.rb
336
352
  - spec/flipper/adapters/sync_spec.rb
353
+ - spec/flipper/cli_spec.rb
337
354
  - spec/flipper/cloud/configuration_spec.rb
338
355
  - spec/flipper/cloud/dsl_spec.rb
339
356
  - spec/flipper/cloud/message_verifier_spec.rb