flipper 1.4.1 → 1.4.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: b53cde688da0c42de8705aa6d3adbcb7c43f2771a75bb49ccb2b500637b10f07
4
- data.tar.gz: 65532d9f52b340a85028101e7e31538c5b2165e16fb453e74ca2d65f5041bd07
3
+ metadata.gz: c886665703939f49361ef42fb82e951383cb53bd99f2b1d902add786f6793da0
4
+ data.tar.gz: b7af2d5972cc409f075390871dc96b225e495133917e0c5024db297760252e73
5
5
  SHA512:
6
- metadata.gz: a250b1d0b4928a0f060fc699cbf4ff69550158732bcfb3f5cf567d088a207daa1607b6da342ec3cc2888353032ad42f66096f2281e2751a0948ff1a5bed8e02b
7
- data.tar.gz: 8dd06e0a50cf2f80efb2fbbb8ad42ddbc3140befd7d0b28a9a9124b7432365aa4c5e541d5f4d3749d3cb70e4d67ba53c9b2c05ecac50f564b1c426b53314de3e
6
+ metadata.gz: 338ccb2e6d9ddeaa6f6a1f20755e7799dcda40341c22831f8eda1f25df5f08bf4c61d67333e9bdebf94172107842b07e7ddb3ec7a54a2d057663f109e78f5a5d
7
+ data.tar.gz: bbfdb72c366e7fa334d8c3903b799366bed22d755cf6771c532d1335cccf7e9480c8a752c700a449f1ae837ae273be5b9c06ef58bc38b56570d96ef417edbded
@@ -142,7 +142,8 @@ module Flipper
142
142
  private
143
143
 
144
144
  def app_adapter
145
- Flipper::Adapters::DualWrite.new(poll_adapter, http_adapter)
145
+ read_adapter = sync_method == :webhook ? local_adapter : poll_adapter
146
+ Flipper::Adapters::DualWrite.new(read_adapter, http_adapter)
146
147
  end
147
148
 
148
149
  def poller
@@ -201,13 +202,8 @@ module Flipper
201
202
  end
202
203
 
203
204
  def setup_sync(options)
205
+ set_option :sync_interval, options, default: 10, typecast: :float, minimum: 10
204
206
  set_option :sync_secret, options
205
-
206
- # 1 hour for webhook, 10 seconds for poll. If using webhooks we don't
207
- # need to sync as often but we should still sync occasionally to avoid
208
- # any chance of stale data.
209
- default_interval = sync_method == :webhook ? 3600 : 10
210
- set_option :sync_interval, options, default: default_interval, typecast: :float, minimum: 10
211
207
  end
212
208
 
213
209
  def setup_adapter(options)
@@ -99,9 +99,7 @@ module Flipper
99
99
  private
100
100
 
101
101
  def jitter
102
- # Cap jitter at 30 seconds to prevent excessive delays for large intervals
103
- max_jitter = [interval * 0.1, 30].min
104
- rand * max_jitter
102
+ rand
105
103
  end
106
104
 
107
105
  def forked?
@@ -1,5 +1,5 @@
1
1
  module Flipper
2
- VERSION = '1.4.1'.freeze
2
+ VERSION = '1.4.2'.freeze
3
3
 
4
4
  REQUIRED_RUBY_VERSION = '2.6'.freeze
5
5
  NEXT_REQUIRED_RUBY_VERSION = '3.0'.freeze
@@ -135,9 +135,6 @@ RSpec.describe Flipper::Cloud::Configuration do
135
135
  end
136
136
 
137
137
  it "sets sync_method to :webhook if sync_secret provided" do
138
- # The initial sync of http to local invokes this web request.
139
- stub_request(:get, /flippercloud\.io/).to_return(status: 200, body: "{}")
140
-
141
138
  instance = described_class.new(required_options.merge({
142
139
  sync_secret: "secret",
143
140
  }))
@@ -147,9 +144,6 @@ RSpec.describe Flipper::Cloud::Configuration do
147
144
  end
148
145
 
149
146
  it "sets sync_method to :webhook if FLIPPER_CLOUD_SYNC_SECRET set" do
150
- # The initial sync of http to local invokes this web request.
151
- stub_request(:get, /flippercloud\.io/).to_return(status: 200, body: "{}")
152
-
153
147
  ENV["FLIPPER_CLOUD_SYNC_SECRET"] = "abc"
154
148
  instance = described_class.new(required_options)
155
149
 
@@ -5,9 +5,6 @@ require 'flipper/adapters/instrumented'
5
5
 
6
6
  RSpec.describe Flipper::Cloud::DSL do
7
7
  it 'delegates everything to flipper instance' do
8
- # stub the initial sync of http to local
9
- stub_request(:get, /flippercloud\.io/).to_return(status: 200, body: "{}")
10
-
11
8
  cloud_configuration = Flipper::Cloud::Configuration.new({
12
9
  token: "asdf",
13
10
  sync_secret: "tasty",
@@ -30,13 +27,10 @@ RSpec.describe Flipper::Cloud::DSL do
30
27
  })
31
28
  dsl = described_class.new(cloud_configuration)
32
29
  dsl.sync
33
- expect(stub).to have_been_requested.at_least_once
30
+ expect(stub).to have_been_requested
34
31
  end
35
32
 
36
33
  it 'delegates sync_secret to cloud configuration' do
37
- # stub the initial sync of http to local
38
- stub_request(:get, /flippercloud\.io/).to_return(status: 200, body: "{}")
39
-
40
34
  cloud_configuration = Flipper::Cloud::Configuration.new({
41
35
  token: "asdf",
42
36
  sync_secret: "tasty",
@@ -59,15 +53,13 @@ RSpec.describe Flipper::Cloud::DSL do
59
53
  end
60
54
 
61
55
  subject do
62
- # stub the initial sync of http to local
63
- stub_request(:get, /flippercloud\.io/).to_return(status: 200, body: "{}")
64
56
  described_class.new(cloud_configuration)
65
57
  end
66
58
 
67
59
  it "sends reads to local adapter" do
68
60
  subject.features
69
61
  subject.enabled?(:foo)
70
- expect(local_adapter.count(:features)).to be(2)
62
+ expect(local_adapter.count(:features)).to be(1)
71
63
  expect(local_adapter.count(:get)).to be(1)
72
64
  end
73
65
 
@@ -62,7 +62,7 @@ RSpec.describe Flipper::Cloud::Middleware do
62
62
  {"name" => "premium"},
63
63
  ],
64
64
  })
65
- expect(stub).to have_been_made.at_least_once
65
+ expect(stub).to have_been_requested
66
66
  end
67
67
  end
68
68
 
@@ -72,17 +72,15 @@ RSpec.describe Flipper::Cloud::Middleware do
72
72
  Flipper::Cloud::MessageVerifier.new(secret: "nope").generate(request_body, timestamp)
73
73
  }
74
74
 
75
- it 'does not perform webhook sync' do
76
- webhook_regular_stub = stub_request_for_token('regular', from_webhook: true)
77
- poll_regular_stub = stub_request_for_token('regular', from_webhook: false)
75
+ it 'uses instance to sync' do
76
+ stub = stub_request_for_token('regular')
78
77
  env = {
79
78
  "HTTP_FLIPPER_CLOUD_SIGNATURE" => signature_header_value,
80
79
  }
81
80
  post '/', request_body, env
82
81
 
83
82
  expect(last_response.status).to eq(400)
84
- expect(poll_regular_stub).to have_been_requested.at_least_once
85
- expect(webhook_regular_stub).not_to have_been_requested
83
+ expect(stub).not_to have_been_requested
86
84
  end
87
85
  end
88
86
 
@@ -105,7 +103,7 @@ RSpec.describe Flipper::Cloud::Middleware do
105
103
  expect(last_response.status).to eq(402)
106
104
  expect(last_response.headers["flipper-cloud-response-error-class"]).to eq("Flipper::Adapters::Http::Error")
107
105
  expect(last_response.headers["flipper-cloud-response-error-message"]).to include("Failed with status: 402")
108
- expect(stub).to have_been_made.at_least_once
106
+ expect(stub).to have_been_requested
109
107
  end
110
108
  end
111
109
 
@@ -128,7 +126,7 @@ RSpec.describe Flipper::Cloud::Middleware do
128
126
  expect(last_response.status).to eq(500)
129
127
  expect(last_response.headers["flipper-cloud-response-error-class"]).to eq("Flipper::Adapters::Http::Error")
130
128
  expect(last_response.headers["flipper-cloud-response-error-message"]).to include("Failed with status: 503")
131
- expect(stub).to have_been_made.at_least_once
129
+ expect(stub).to have_been_requested
132
130
  end
133
131
  end
134
132
 
@@ -151,7 +149,7 @@ RSpec.describe Flipper::Cloud::Middleware do
151
149
  expect(last_response.status).to eq(500)
152
150
  expect(last_response.headers["flipper-cloud-response-error-class"]).to eq("Net::OpenTimeout")
153
151
  expect(last_response.headers["flipper-cloud-response-error-message"]).to eq("execution expired")
154
- expect(stub).to have_been_made.at_least_once
152
+ expect(stub).to have_been_requested
155
153
  end
156
154
  end
157
155
 
@@ -162,8 +160,7 @@ RSpec.describe Flipper::Cloud::Middleware do
162
160
  }
163
161
 
164
162
  it 'uses env instance to sync' do
165
- regular_stub = stub_request_for_token('regular')
166
- env_stub = stub_request_for_token('env')
163
+ stub = stub_request_for_token('env')
167
164
  env = {
168
165
  "HTTP_FLIPPER_CLOUD_SIGNATURE" => signature_header_value,
169
166
  'flipper' => env_flipper,
@@ -171,8 +168,7 @@ RSpec.describe Flipper::Cloud::Middleware do
171
168
  post '/', request_body, env
172
169
 
173
170
  expect(last_response.status).to eq(200)
174
- expect(regular_stub).to have_been_made.at_least_once
175
- expect(env_stub).to have_been_made.at_least_once
171
+ expect(stub).to have_been_requested
176
172
  end
177
173
  end
178
174
 
@@ -191,7 +187,7 @@ RSpec.describe Flipper::Cloud::Middleware do
191
187
  post '/', request_body, env
192
188
 
193
189
  expect(last_response.status).to eq(200)
194
- expect(stub).to have_been_made.at_least_once
190
+ expect(stub).to have_been_requested
195
191
  end
196
192
  end
197
193
 
@@ -202,9 +198,7 @@ RSpec.describe Flipper::Cloud::Middleware do
202
198
  }
203
199
 
204
200
  it 'uses provided env key instead of default' do
205
- regular_poll_stub = stub_request_for_token('regular')
206
- env_poll_stub = stub_request_for_token('env')
207
- env_webhook_stub = stub_request_for_token('env', from_webhook: true)
201
+ stub = stub_request_for_token('env')
208
202
  env = {
209
203
  "HTTP_FLIPPER_CLOUD_SIGNATURE" => signature_header_value,
210
204
  'flipper' => flipper,
@@ -213,9 +207,7 @@ RSpec.describe Flipper::Cloud::Middleware do
213
207
  post '/', request_body, env
214
208
 
215
209
  expect(last_response.status).to eq(200)
216
- expect(regular_poll_stub).to have_been_made.at_least_once
217
- expect(env_poll_stub).to have_been_made.at_least_once
218
- expect(env_webhook_stub).not_to have_been_requested
210
+ expect(stub).to have_been_requested
219
211
  end
220
212
  end
221
213
 
@@ -230,7 +222,7 @@ RSpec.describe Flipper::Cloud::Middleware do
230
222
  post '/', request_body, env
231
223
 
232
224
  expect(last_response.status).to eq(200)
233
- expect(stub).to have_been_made.at_least_once
225
+ expect(stub).to have_been_requested
234
226
  end
235
227
  end
236
228
 
@@ -260,13 +252,12 @@ RSpec.describe Flipper::Cloud::Middleware do
260
252
  {"name" => "premium"},
261
253
  ],
262
254
  })
263
- expect(stub).to have_been_made.at_least_once
255
+ expect(stub).to have_been_requested
264
256
  end
265
257
  end
266
258
 
267
259
  describe 'Request method unsupported' do
268
260
  it 'skips middleware' do
269
- stub_request(:get, /flippercloud\.io/).to_return(status: 200, body: "{}")
270
261
  get '/'
271
262
  expect(last_response.status).to eq(404)
272
263
  expect(last_response.content_type).to eq("application/json")
@@ -276,23 +267,14 @@ RSpec.describe Flipper::Cloud::Middleware do
276
267
 
277
268
  describe 'Inspecting the built Rack app' do
278
269
  it 'returns a String' do
279
- stub_request(:get, /flippercloud\.io/).to_return(status: 200, body: "{}")
280
270
  expect(Flipper::Cloud.app(flipper).inspect).to eq("Flipper::Cloud")
281
271
  end
282
272
  end
283
273
 
284
274
  private
285
275
 
286
- def stub_request_for_token(token, status: 200, from_webhook: false)
287
- if from_webhook
288
- # Match URL with both exclude_gate_names=true and _cb=integer
289
- url_pattern = %r{https://www\.flippercloud\.io/adapter/features\?.*exclude_gate_names=true.*&_cb=\d+}
290
- else
291
- # Match URL with just exclude_gate_names=true
292
- url_pattern = %r{https://www\.flippercloud\.io/adapter/features\?.*exclude_gate_names=true}
293
- end
294
-
295
- stub = stub_request(:get, url_pattern).
276
+ def stub_request_for_token(token, status: 200)
277
+ stub = stub_request(:get, %r{\Ahttps://www\.flippercloud\.io/adapter/features\?(?=.*\bexclude_gate_names=true\b)(?=.*\b_cb=\d+\b)}).
296
278
  with({
297
279
  headers: {
298
280
  'flipper-cloud-token' => token,
data/spec/flipper_spec.rb CHANGED
@@ -259,7 +259,7 @@ RSpec.describe Flipper do
259
259
  end
260
260
  described_class.sync
261
261
  expect(described_class.sync_secret).to eq("tasty")
262
- expect(stub).to have_been_made.at_least_once
262
+ expect(stub).to have_been_requested
263
263
  end
264
264
  end
265
265
 
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.4.1
4
+ version: 1.4.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: 2026-03-25 00:00:00.000000000 Z
11
+ date: 2026-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -323,7 +323,7 @@ metadata:
323
323
  homepage_uri: https://www.flippercloud.io
324
324
  source_code_uri: https://github.com/flippercloud/flipper
325
325
  bug_tracker_uri: https://github.com/flippercloud/flipper/issues
326
- changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.4.1
326
+ changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.4.2
327
327
  funding_uri: https://github.com/sponsors/flippercloud
328
328
  post_install_message:
329
329
  rdoc_options: []