flipper 1.1.2 → 1.2.1

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