flipper 1.1.2 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +7 -1
  3. data/.github/workflows/examples.yml +7 -1
  4. data/Changelog.md +1 -647
  5. data/Gemfile +3 -1
  6. data/README.md +1 -1
  7. data/Rakefile +2 -2
  8. data/exe/flipper +5 -0
  9. data/flipper.gemspec +5 -1
  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 +38 -0
  21. data/lib/flipper/version.rb +11 -1
  22. data/lib/generators/flipper/setup_generator.rb +63 -0
  23. data/spec/fixtures/environment.rb +1 -0
  24. data/spec/flipper/adapter_builder_spec.rb +1 -2
  25. data/spec/flipper/adapters/http/client_spec.rb +61 -0
  26. data/spec/flipper/adapters/http_spec.rb +92 -75
  27. data/spec/flipper/adapters/strict_spec.rb +11 -9
  28. data/spec/flipper/cli_spec.rb +164 -0
  29. data/spec/flipper/cloud/configuration_spec.rb +9 -2
  30. data/spec/flipper/cloud/dsl_spec.rb +5 -5
  31. data/spec/flipper/cloud/middleware_spec.rb +8 -8
  32. data/spec/flipper/cloud/telemetry/submitter_spec.rb +24 -24
  33. data/spec/flipper/cloud/telemetry_spec.rb +1 -1
  34. data/spec/flipper/cloud_spec.rb +4 -4
  35. data/spec/flipper/engine_spec.rb +76 -11
  36. data/spec/flipper/instrumentation/log_subscriber_spec.rb +9 -2
  37. data/spec/flipper_spec.rb +1 -1
  38. data/spec/spec_helper.rb +1 -0
  39. data/spec/support/spec_helpers.rb +10 -4
  40. data/test_rails/generators/flipper/setup_generator_test.rb +64 -0
  41. data/test_rails/system/test_help_test.rb +46 -0
  42. metadata +20 -7
@@ -101,8 +101,8 @@ RSpec.describe Flipper::Cloud::Middleware do
101
101
  post '/', request_body, env
102
102
 
103
103
  expect(last_response.status).to eq(402)
104
- expect(last_response.headers["Flipper-Cloud-Response-Error-Class"]).to eq("Flipper::Adapters::Http::Error")
105
- expect(last_response.headers["Flipper-Cloud-Response-Error-Message"]).to include("Failed with status: 402")
104
+ expect(last_response.headers["flipper-cloud-response-error-class"]).to eq("Flipper::Adapters::Http::Error")
105
+ expect(last_response.headers["flipper-cloud-response-error-message"]).to include("Failed with status: 402")
106
106
  expect(stub).to have_been_requested
107
107
  end
108
108
  end
@@ -124,8 +124,8 @@ RSpec.describe Flipper::Cloud::Middleware do
124
124
  post '/', request_body, env
125
125
 
126
126
  expect(last_response.status).to eq(500)
127
- expect(last_response.headers["Flipper-Cloud-Response-Error-Class"]).to eq("Flipper::Adapters::Http::Error")
128
- expect(last_response.headers["Flipper-Cloud-Response-Error-Message"]).to include("Failed with status: 503")
127
+ expect(last_response.headers["flipper-cloud-response-error-class"]).to eq("Flipper::Adapters::Http::Error")
128
+ expect(last_response.headers["flipper-cloud-response-error-message"]).to include("Failed with status: 503")
129
129
  expect(stub).to have_been_requested
130
130
  end
131
131
  end
@@ -147,8 +147,8 @@ RSpec.describe Flipper::Cloud::Middleware do
147
147
  post '/', request_body, env
148
148
 
149
149
  expect(last_response.status).to eq(500)
150
- expect(last_response.headers["Flipper-Cloud-Response-Error-Class"]).to eq("Net::OpenTimeout")
151
- expect(last_response.headers["Flipper-Cloud-Response-Error-Message"]).to eq("execution expired")
150
+ expect(last_response.headers["flipper-cloud-response-error-class"]).to eq("Net::OpenTimeout")
151
+ expect(last_response.headers["flipper-cloud-response-error-message"]).to eq("execution expired")
152
152
  expect(stub).to have_been_requested
153
153
  end
154
154
  end
@@ -277,13 +277,13 @@ RSpec.describe Flipper::Cloud::Middleware do
277
277
  stub = stub_request(:get, "https://www.flippercloud.io/adapter/features?exclude_gate_names=true").
278
278
  with({
279
279
  headers: {
280
- 'Flipper-Cloud-Token' => token,
280
+ 'flipper-cloud-token' => token,
281
281
  },
282
282
  })
283
283
  if status == :timeout
284
284
  stub.to_timeout
285
285
  else
286
- stub.to_return(status: status, body: response_body, headers: {})
286
+ stub.to_return(status: status, body: response_body)
287
287
  end
288
288
  end
289
289
  end
@@ -43,33 +43,33 @@ RSpec.describe Flipper::Cloud::Telemetry::Submitter do
43
43
  ]
44
44
  }
45
45
  expected_headers = {
46
- 'Accept' => 'application/json',
47
- 'Client-Engine' => defined?(RUBY_ENGINE) ? RUBY_ENGINE : "",
48
- 'Client-Hostname' => Socket.gethostname,
49
- 'Client-Language' => 'ruby',
50
- 'Client-Language-Version' => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})",
51
- 'Client-Pid' => Process.pid.to_s,
52
- 'Client-Platform' => RUBY_PLATFORM,
53
- 'Client-Thread' => Thread.current.object_id.to_s,
54
- 'Content-Encoding' => 'gzip',
55
- 'Content-Type' => 'application/json',
56
- 'Flipper-Cloud-Token' => 'asdf',
57
- 'Schema-Version' => 'V1',
58
- 'User-Agent' => "Flipper HTTP Adapter v#{Flipper::VERSION}",
46
+ 'accept' => 'application/json',
47
+ 'client-engine' => defined?(RUBY_ENGINE) ? RUBY_ENGINE : "",
48
+ 'client-hostname' => Socket.gethostname,
49
+ 'client-language' => 'ruby',
50
+ 'client-language-version' => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})",
51
+ 'client-pid' => Process.pid.to_s,
52
+ 'client-platform' => RUBY_PLATFORM,
53
+ 'client-thread' => Thread.current.object_id.to_s,
54
+ 'content-encoding' => 'gzip',
55
+ 'content-type' => 'application/json',
56
+ 'flipper-cloud-token' => 'asdf',
57
+ 'schema-version' => 'V1',
58
+ 'user-agent' => "Flipper HTTP Adapter v#{Flipper::VERSION}",
59
59
  }
60
60
  stub_request(:post, "https://www.flippercloud.io/adapter/telemetry").
61
61
  with(headers: expected_headers) { |request|
62
62
  gunzipped = Flipper::Typecast.from_gzip(request.body)
63
63
  body = Flipper::Typecast.from_json(gunzipped)
64
64
  body == expected_body
65
- }.to_return(status: 200, body: "{}", headers: {})
65
+ }.to_return(status: 200, body: "{}")
66
66
  subject.call(enabled_metrics)
67
67
  end
68
68
 
69
69
  it "defaults backoff_policy" do
70
70
  stub_request(:post, "https://www.flippercloud.io/adapter/telemetry").
71
- to_return(status: 429, body: "{}", headers: {}).
72
- to_return(status: 200, body: "{}", headers: {})
71
+ to_return(status: 429, body: "{}").
72
+ to_return(status: 200, body: "{}")
73
73
  instance = described_class.new(cloud_configuration)
74
74
  expect(instance.backoff_policy.min_timeout_ms).to eq(1_000)
75
75
  expect(instance.backoff_policy.max_timeout_ms).to eq(30_000)
@@ -77,7 +77,7 @@ RSpec.describe Flipper::Cloud::Telemetry::Submitter do
77
77
 
78
78
  it "tries 10 times by default" do
79
79
  stub_request(:post, "https://www.flippercloud.io/adapter/telemetry").
80
- to_return(status: 500, body: "{}", headers: {})
80
+ to_return(status: 500, body: "{}")
81
81
  subject.call(enabled_metrics)
82
82
  expect(subject.backoff_policy.retries).to eq(9) # 9 retries + 1 initial attempt
83
83
  end
@@ -111,19 +111,19 @@ RSpec.describe Flipper::Cloud::Telemetry::Submitter do
111
111
 
112
112
  it "retries on 429" do
113
113
  stub_request(:post, "https://www.flippercloud.io/adapter/telemetry").
114
- to_return(status: 429, body: "{}", headers: {}).
115
- to_return(status: 429, body: "{}", headers: {}).
116
- to_return(status: 200, body: "{}", headers: {})
114
+ to_return(status: 429, body: "{}").
115
+ to_return(status: 429, body: "{}").
116
+ to_return(status: 200, body: "{}")
117
117
  subject.call(enabled_metrics)
118
118
  expect(subject.backoff_policy.retries).to eq(2)
119
119
  end
120
120
 
121
121
  it "retries on 500" do
122
122
  stub_request(:post, "https://www.flippercloud.io/adapter/telemetry").
123
- to_return(status: 500, body: "{}", headers: {}).
124
- to_return(status: 503, body: "{}", headers: {}).
125
- to_return(status: 502, body: "{}", headers: {}).
126
- to_return(status: 200, body: "{}", headers: {})
123
+ to_return(status: 500, body: "{}").
124
+ to_return(status: 503, body: "{}").
125
+ to_return(status: 502, body: "{}").
126
+ to_return(status: 200, body: "{}")
127
127
  subject.call(enabled_metrics)
128
128
  expect(subject.backoff_policy.retries).to eq(3)
129
129
  end
@@ -4,7 +4,7 @@ require 'flipper/cloud/configuration'
4
4
  RSpec.describe Flipper::Cloud::Telemetry do
5
5
  it "phones home and does not update telemetry interval if missing" do
6
6
  stub = stub_request(:post, "https://www.flippercloud.io/adapter/telemetry").
7
- to_return(status: 200, body: "{}", headers: {})
7
+ to_return(status: 200, body: "{}")
8
8
 
9
9
  cloud_configuration = Flipper::Cloud::Configuration.new(token: "test")
10
10
 
@@ -35,7 +35,7 @@ RSpec.describe Flipper::Cloud do
35
35
  expect(client.uri.scheme).to eq('https')
36
36
  expect(client.uri.host).to eq('www.flippercloud.io')
37
37
  expect(client.uri.path).to eq('/adapter')
38
- expect(client.headers['Flipper-Cloud-Token']).to eq(token)
38
+ expect(client.headers["flipper-cloud-token"]).to eq(token)
39
39
  expect(@instance.instrumenter).to be(Flipper::Instrumenters::Noop)
40
40
  end
41
41
  end
@@ -104,7 +104,7 @@ RSpec.describe Flipper::Cloud do
104
104
 
105
105
  it 'can import' do
106
106
  stub_request(:post, /www\.flippercloud\.io\/adapter\/features.*/).
107
- with(headers: {'Flipper-Cloud-Token'=>'asdf'}).to_return(status: 200, body: "{}", headers: {})
107
+ with(headers: {'flipper-cloud-token'=>'asdf'}).to_return(status: 200, body: "{}", headers: {})
108
108
 
109
109
  flipper = Flipper.new(Flipper::Adapters::Memory.new)
110
110
 
@@ -130,7 +130,7 @@ RSpec.describe Flipper::Cloud do
130
130
 
131
131
  it 'raises error for failure while importing' do
132
132
  stub_request(:post, /www\.flippercloud\.io\/adapter\/features.*/).
133
- with(headers: {'Flipper-Cloud-Token'=>'asdf'}).to_return(status: 500, body: "{}")
133
+ with(headers: {'flipper-cloud-token'=>'asdf'}).to_return(status: 500, body: "{}")
134
134
 
135
135
  flipper = Flipper.new(Flipper::Adapters::Memory.new)
136
136
 
@@ -155,7 +155,7 @@ RSpec.describe Flipper::Cloud do
155
155
 
156
156
  it 'raises error for timeout while importing' do
157
157
  stub_request(:post, /www\.flippercloud\.io\/adapter\/features.*/).
158
- with(headers: {'Flipper-Cloud-Token'=>'asdf'}).to_timeout
158
+ with(headers: {'flipper-cloud-token'=>'asdf'}).to_timeout
159
159
 
160
160
  flipper = Flipper.new(Flipper::Adapters::Memory.new)
161
161
 
@@ -45,7 +45,7 @@ RSpec.describe Flipper::Engine do
45
45
  subject
46
46
  expect(config.strict).to eq(:warn)
47
47
  expect(adapter).to be_instance_of(Flipper::Adapters::Strict)
48
- expect(adapter.handler).to be(Flipper::Adapters::Strict::HANDLERS.fetch(:warn))
48
+ expect(adapter.handler).to be(:warn)
49
49
  end
50
50
  end
51
51
 
@@ -57,23 +57,47 @@ RSpec.describe Flipper::Engine do
57
57
  end
58
58
  end
59
59
 
60
- it "defaults to strict=false in RAILS_ENV=production" do
61
- Rails.env = "production"
60
+ [true, :raise, :warn].each do |value|
61
+ it "can set strict=#{value.inspect} in initializer" do
62
+ initializer { config.strict = value }
62
63
  subject
63
- expect(config.strict).to eq(false)
64
- expect(adapter).to be_instance_of(Flipper::Adapters::Memory)
64
+ expect(adapter).to be_instance_of(Flipper::Adapters::Strict)
65
+ expect(adapter.handler).to be(value)
66
+ end
67
+ end
68
+
69
+ it "can set strict=false in initializer" do
70
+ initializer { config.strict = false }
71
+ subject
72
+ expect(config.strict).to eq(false)
73
+ expect(adapter).to be_instance_of(Flipper::Adapters::Memory)
74
+ end
75
+
76
+ it "defaults to strict=:warn in RAILS_ENV=development" do
77
+ Rails.env = "development"
78
+ subject
79
+ expect(config.strict).to eq(:warn)
80
+ expect(adapter).to be_instance_of(Flipper::Adapters::Strict)
65
81
  end
66
82
 
67
- %w(development test).each do |env|
83
+ %w(production test).each do |env|
68
84
  it "defaults to strict=warn in RAILS_ENV=#{env}" do
69
85
  Rails.env = env
70
86
  expect(Rails.env).to eq(env)
71
87
  subject
72
- expect(config.strict).to eq(:warn)
73
- expect(adapter).to be_instance_of(Flipper::Adapters::Strict)
74
- expect(adapter.handler).to be(Flipper::Adapters::Strict::HANDLERS.fetch(:warn))
88
+ expect(config.strict).to eq(false)
89
+ expect(adapter).to be_instance_of(Flipper::Adapters::Memory)
75
90
  end
76
91
  end
92
+
93
+ it "defaults to strict=warn in RAILS_ENV=development" do
94
+ Rails.env = "development"
95
+ expect(Rails.env).to eq("development")
96
+ subject
97
+ expect(config.strict).to eq(:warn)
98
+ expect(adapter).to be_instance_of(Flipper::Adapters::Strict)
99
+ expect(adapter.handler).to be(:warn)
100
+ end
77
101
  end
78
102
 
79
103
  context 'cloudless' do
@@ -153,6 +177,46 @@ RSpec.describe Flipper::Engine do
153
177
  if: nil
154
178
  })
155
179
  end
180
+
181
+ context "test_help" do
182
+ it "is loaded if RAILS_ENV=test" do
183
+ Rails.env = "test"
184
+ allow(Flipper::Engine.instance).to receive(:require).and_call_original
185
+ expect(Flipper::Engine.instance).to receive(:require).with("flipper/test_help")
186
+ subject
187
+ expect(config.test_help).to eq(true)
188
+ end
189
+
190
+ it "is loaded if FLIPPER_TEST_HELP=true" do
191
+ ENV["FLIPPER_TEST_HELP"] = "true"
192
+ allow(Flipper::Engine.instance).to receive(:require).and_call_original
193
+ expect(Flipper::Engine.instance).to receive(:require).with("flipper/test_help")
194
+ subject
195
+ expect(config.test_help).to eq(true)
196
+ end
197
+
198
+ it "is loaded if config.flipper.test_help = true" do
199
+ initializer { config.test_help = true }
200
+ allow(Flipper::Engine.instance).to receive(:require).and_call_original
201
+ expect(Flipper::Engine.instance).to receive(:require).with("flipper/test_help")
202
+ subject
203
+ end
204
+
205
+ it "is not loaded if FLIPPER_TEST_HELP=false" do
206
+ ENV["FLIPPER_TEST_HELP"] = "false"
207
+ allow(Flipper::Engine.instance).to receive(:require).and_call_original
208
+ expect(Flipper::Engine.instance).to receive(:require).with("flipper/test_help").never
209
+ subject
210
+ end
211
+
212
+ it "is not loaded if config.flipper.test_help = false" do
213
+ Rails.env = "true"
214
+ initializer { config.test_help = false }
215
+ allow(Flipper::Engine.instance).to receive(:require).and_call_original
216
+ expect(Flipper::Engine.instance).to receive(:require).with("flipper/test_help").never
217
+ subject
218
+ end
219
+ end
156
220
  end
157
221
 
158
222
  context 'with cloud' do
@@ -167,7 +231,8 @@ RSpec.describe Flipper::Engine do
167
231
 
168
232
  it_behaves_like 'config.strict' do
169
233
  let(:adapter) do
170
- dual_write = Flipper.adapter.adapter
234
+ memoizable = Flipper.adapter
235
+ dual_write = memoizable.adapter
171
236
  poll = dual_write.local
172
237
  poll.adapter
173
238
  end
@@ -210,7 +275,7 @@ RSpec.describe Flipper::Engine do
210
275
  application.initialize!
211
276
 
212
277
  stub = stub_request(:get, "https://www.flippercloud.io/adapter/features?exclude_gate_names=true").with({
213
- headers: { "Flipper-Cloud-Token" => ENV["FLIPPER_CLOUD_TOKEN"] },
278
+ headers: { "flipper-cloud-token" => ENV["FLIPPER_CLOUD_TOKEN"] },
214
279
  }).to_return(status: 200, body: JSON.generate({ features: {} }), headers: {})
215
280
 
216
281
  post "/_flipper", request_body, { "HTTP_FLIPPER_CLOUD_SIGNATURE" => signature_header_value }
@@ -1,6 +1,6 @@
1
1
  require 'logger'
2
- require 'flipper/adapters/instrumented'
3
2
  require 'flipper/instrumentation/log_subscriber'
3
+ require 'flipper/adapters/instrumented'
4
4
 
5
5
  begin
6
6
  require 'active_support/isolated_execution_state'
@@ -8,6 +8,9 @@ rescue LoadError
8
8
  # ActiveSupport::IsolatedExecutionState is only available in Rails 5.2+
9
9
  end
10
10
 
11
+ # Don't log in other tests, we'll manually re-attach when this one starts
12
+ Flipper::Instrumentation::LogSubscriber.detach
13
+
11
14
  RSpec.describe Flipper::Instrumentation::LogSubscriber do
12
15
  let(:adapter) do
13
16
  memory = Flipper::Adapters::Memory.new
@@ -32,8 +35,12 @@ RSpec.describe Flipper::Instrumentation::LogSubscriber do
32
35
  described_class.logger = nil
33
36
  end
34
37
 
38
+ before(:all) do
39
+ described_class.attach
40
+ end
41
+
35
42
  after(:all) do
36
- ActiveSupport::Notifications.unsubscribe("flipper")
43
+ described_class.detach
37
44
  end
38
45
 
39
46
  let(:log) { @io.string }
data/spec/flipper_spec.rb CHANGED
@@ -241,7 +241,7 @@ RSpec.describe Flipper do
241
241
  stub = stub_request(:get, "https://www.flippercloud.io/adapter/features?exclude_gate_names=true").
242
242
  with({
243
243
  headers: {
244
- 'Flipper-Cloud-Token'=>'asdf',
244
+ 'flipper-cloud-token'=>'asdf',
245
245
  },
246
246
  }).to_return(status: 200, body: '{"features": {}}', headers: {})
247
247
  cloud_configuration = Flipper::Cloud::Configuration.new({
data/spec/spec_helper.rb CHANGED
@@ -18,6 +18,7 @@ require 'flipper'
18
18
  require 'flipper/api'
19
19
  require 'flipper/spec/shared_adapter_specs'
20
20
  require 'flipper/ui'
21
+ require 'flipper/test_help'
21
22
 
22
23
  Dir[FlipperRoot.join('spec/support/**/*.rb')].sort.each { |f| require f }
23
24
 
@@ -3,6 +3,8 @@ require 'json'
3
3
  require 'rack/test'
4
4
 
5
5
  module SpecHelpers
6
+ extend self
7
+
6
8
  def self.included(base)
7
9
  base.let(:flipper) { build_flipper }
8
10
  base.let(:app) { build_app(flipper) }
@@ -27,7 +29,11 @@ module SpecHelpers
27
29
  end
28
30
 
29
31
  def json_response
30
- JSON.parse(last_response.body)
32
+ body = last_response.body
33
+ if last_response["content-encoding"] == 'gzip'
34
+ body = Flipper::Typecast.from_gzip(body)
35
+ end
36
+ JSON.parse(body)
31
37
  end
32
38
 
33
39
  def api_error_code_reference_url
@@ -76,11 +82,11 @@ module SpecHelpers
76
82
 
77
83
  yield
78
84
 
79
- $stderr = original_stderr
80
- $stdout = original_stdout
81
-
82
85
  # Return output
83
86
  output.string
87
+ ensure
88
+ $stderr = original_stderr
89
+ $stdout = original_stdout
84
90
  end
85
91
  end
86
92
 
@@ -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,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.2
4
+ version: 1.2.1
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-12 00:00:00.000000000 Z
11
+ date: 2024-01-15 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,9 +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
188
193
  - lib/generators/flipper/templates/update/migrations/01_create_flipper_tables.rb.erb
189
194
  - lib/generators/flipper/templates/update/migrations/02_change_flipper_gates_value_to_text.rb.erb
190
195
  - lib/generators/flipper/update_generator.rb
196
+ - spec/fixtures/environment.rb
191
197
  - spec/fixtures/feature.json
192
198
  - spec/fixtures/flipper_pstore_1679087600.json
193
199
  - spec/flipper/actor_spec.rb
@@ -196,6 +202,7 @@ files:
196
202
  - spec/flipper/adapters/dual_write_spec.rb
197
203
  - spec/flipper/adapters/failover_spec.rb
198
204
  - spec/flipper/adapters/failsafe_spec.rb
205
+ - spec/flipper/adapters/http/client_spec.rb
199
206
  - spec/flipper/adapters/http_spec.rb
200
207
  - spec/flipper/adapters/instrumented_spec.rb
201
208
  - spec/flipper/adapters/memoizable_spec.rb
@@ -208,6 +215,7 @@ files:
208
215
  - spec/flipper/adapters/sync/interval_synchronizer_spec.rb
209
216
  - spec/flipper/adapters/sync/synchronizer_spec.rb
210
217
  - spec/flipper/adapters/sync_spec.rb
218
+ - spec/flipper/cli_spec.rb
211
219
  - spec/flipper/cloud/configuration_spec.rb
212
220
  - spec/flipper/cloud/dsl_spec.rb
213
221
  - spec/flipper/cloud/message_verifier_spec.rb
@@ -287,8 +295,10 @@ files:
287
295
  - test/adapters/memory_test.rb
288
296
  - test/adapters/pstore_test.rb
289
297
  - test/test_helper.rb
298
+ - test_rails/generators/flipper/setup_generator_test.rb
290
299
  - test_rails/generators/flipper/update_generator_test.rb
291
300
  - test_rails/helper.rb
301
+ - test_rails/system/test_help_test.rb
292
302
  homepage: https://www.flippercloud.io/docs
293
303
  licenses:
294
304
  - MIT
@@ -297,7 +307,7 @@ metadata:
297
307
  homepage_uri: https://www.flippercloud.io
298
308
  source_code_uri: https://github.com/flippercloud/flipper
299
309
  bug_tracker_uri: https://github.com/flippercloud/flipper/issues
300
- changelog_uri: https://github.com/flippercloud/flipper/blob/main/Changelog.md
310
+ changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.2.1
301
311
  post_install_message:
302
312
  rdoc_options: []
303
313
  require_paths:
@@ -306,18 +316,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
306
316
  requirements:
307
317
  - - ">="
308
318
  - !ruby/object:Gem::Version
309
- version: '0'
319
+ version: '2.6'
310
320
  required_rubygems_version: !ruby/object:Gem::Requirement
311
321
  requirements:
312
322
  - - ">="
313
323
  - !ruby/object:Gem::Version
314
324
  version: '0'
315
325
  requirements: []
316
- rubygems_version: 3.4.10
326
+ rubygems_version: 3.5.3
317
327
  signing_key:
318
328
  specification_version: 4
319
329
  summary: Beautiful, performant feature flags for Ruby and Rails.
320
330
  test_files:
331
+ - spec/fixtures/environment.rb
321
332
  - spec/fixtures/feature.json
322
333
  - spec/fixtures/flipper_pstore_1679087600.json
323
334
  - spec/flipper/actor_spec.rb
@@ -326,6 +337,7 @@ test_files:
326
337
  - spec/flipper/adapters/dual_write_spec.rb
327
338
  - spec/flipper/adapters/failover_spec.rb
328
339
  - spec/flipper/adapters/failsafe_spec.rb
340
+ - spec/flipper/adapters/http/client_spec.rb
329
341
  - spec/flipper/adapters/http_spec.rb
330
342
  - spec/flipper/adapters/instrumented_spec.rb
331
343
  - spec/flipper/adapters/memoizable_spec.rb
@@ -338,6 +350,7 @@ test_files:
338
350
  - spec/flipper/adapters/sync/interval_synchronizer_spec.rb
339
351
  - spec/flipper/adapters/sync/synchronizer_spec.rb
340
352
  - spec/flipper/adapters/sync_spec.rb
353
+ - spec/flipper/cli_spec.rb
341
354
  - spec/flipper/cloud/configuration_spec.rb
342
355
  - spec/flipper/cloud/dsl_spec.rb
343
356
  - spec/flipper/cloud/message_verifier_spec.rb