unleash 4.2.1 → 4.3.0
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 +4 -4
- data/.github/workflows/add-to-project.yml +14 -0
- data/.github/workflows/pull_request.yml +15 -9
- data/.gitignore +1 -1
- data/README.md +29 -13
- data/examples/bootstrap.rb +1 -1
- data/examples/simple.rb +2 -2
- data/lib/unleash/configuration.rb +16 -9
- data/lib/unleash/toggle_fetcher.rb +19 -30
- data/lib/unleash/version.rb +1 -1
- data/unleash-client.gemspec +1 -1
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f05a01bdf6013184b6948fb5c38f6b1da1cde9d18f9a0eeecd69b54cbed8ff18
|
4
|
+
data.tar.gz: 6343830fd945d00decd331acade205d605e0d496ed1d4afd4736affcb2f538ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ac4a4b89f787b5ae27acda02865def0eb68f261da10b83c01a6b34f6706b1b29443375eb82418b9834db555fbe54c1a1dfe49e9bf4c761556145edce88f76c9
|
7
|
+
data.tar.gz: c7a2332c7e6ab54872b08432af4c5c2cf092b7586664eb0267e45e416fb9a72c46246dd6cdedf68b4a9421678e4cb9f9507365e40fc5c2113b9fba8e703a19dd
|
@@ -5,8 +5,21 @@ on:
|
|
5
5
|
pull_request:
|
6
6
|
|
7
7
|
jobs:
|
8
|
-
|
8
|
+
lint:
|
9
|
+
name: RuboCop
|
10
|
+
timeout-minutes: 30
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
steps:
|
13
|
+
- uses: actions/checkout@v2
|
14
|
+
- name: Set up Ruby
|
15
|
+
uses: ruby/setup-ruby@v1
|
16
|
+
with:
|
17
|
+
ruby-version: "2.7"
|
18
|
+
bundler-cache: true
|
19
|
+
- name: Run RuboCop
|
20
|
+
run: bundle exec rubocop
|
9
21
|
|
22
|
+
test:
|
10
23
|
runs-on: ${{ matrix.os }}-latest
|
11
24
|
|
12
25
|
strategy:
|
@@ -18,7 +31,7 @@ jobs:
|
|
18
31
|
- jruby-9.2
|
19
32
|
- jruby-9.3
|
20
33
|
- 3.1
|
21
|
-
- 3.0
|
34
|
+
- '3.0'
|
22
35
|
- 2.7
|
23
36
|
- 2.6
|
24
37
|
- 2.5
|
@@ -34,13 +47,6 @@ jobs:
|
|
34
47
|
run: bundle install
|
35
48
|
- name: Download test cases
|
36
49
|
run: git clone --depth 5 --branch v4.1.0 https://github.com/Unleash/client-specification.git client-specification
|
37
|
-
- name: rubocop
|
38
|
-
uses: reviewdog/action-rubocop@v2
|
39
|
-
with:
|
40
|
-
github_token: ${{ secrets.GITHUB_TOKEN }}
|
41
|
-
rubocop_version: gemfile
|
42
|
-
rubocop_extensions: rubocop-rspec:gemfile
|
43
|
-
reporter: github-pr-review # Default is github-pr-check
|
44
50
|
- name: Run tests
|
45
51
|
run: bundle exec rake
|
46
52
|
env:
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -41,7 +41,7 @@ It is **required** to configure:
|
|
41
41
|
- `app_name` with the name of the runninng application.
|
42
42
|
- `custom_http_headers` with `{'Authorization': '<API token>'}` when using Unleash v4.0.0 and later.
|
43
43
|
|
44
|
-
Please substitute the example `'
|
44
|
+
Please substitute the example `'https://unleash.herokuapp.com/api'` for the url of your own instance.
|
45
45
|
|
46
46
|
It is **highly recommended** to configure:
|
47
47
|
- `instance_id` parameter with a unique identifier for the running instance.
|
@@ -50,7 +50,7 @@ It is **highly recommended** to configure:
|
|
50
50
|
```ruby
|
51
51
|
Unleash.configure do |config|
|
52
52
|
config.app_name = 'my_ruby_app'
|
53
|
-
config.url = '
|
53
|
+
config.url = 'https://unleash.herokuapp.com/api'
|
54
54
|
config.custom_http_headers = {'Authorization': '<API token>'}
|
55
55
|
end
|
56
56
|
```
|
@@ -58,7 +58,23 @@ end
|
|
58
58
|
or instantiate the client with the valid configuration:
|
59
59
|
|
60
60
|
```ruby
|
61
|
-
UNLEASH = Unleash::Client.new(url: '
|
61
|
+
UNLEASH = Unleash::Client.new(url: 'https://unleash.herokuapp.com/api', app_name: 'my_ruby_app', custom_http_headers: {'Authorization': '<API token>'})
|
62
|
+
```
|
63
|
+
|
64
|
+
## Dynamic custom HTTP headers
|
65
|
+
If you need custom HTTP headers that change during the lifetime of the client, the `custom_http_headers` can be given as a `Proc`.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
Unleash.configure do |config|
|
69
|
+
config.app_name = 'my_ruby_app'
|
70
|
+
config.url = 'https://unleash.herokuapp.com/api'
|
71
|
+
config.custom_http_headers = proc do
|
72
|
+
{
|
73
|
+
'Authorization': '<API token>',
|
74
|
+
'X-Client-Request-Time': Time.now.iso8601
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
62
78
|
```
|
63
79
|
|
64
80
|
#### List of Arguments
|
@@ -74,7 +90,7 @@ Argument | Description | Required? | Type | Default Value|
|
|
74
90
|
`metrics_interval` | How often the unleash client should send metrics to server. | N | Integer | 60 |
|
75
91
|
`disable_client` | Disables all communication with the Unleash server, effectively taking it *offline*. If set, `is_enabled?` will always answer with the `default_value` and configuration validation is skipped. Defeats the entire purpose of using unleash, but can be useful in when running tests. | N | Boolean | `false` |
|
76
92
|
`disable_metrics` | Disables sending metrics to Unleash server. | N | Boolean | `false` |
|
77
|
-
`custom_http_headers` | Custom headers to send to Unleash. As of Unleash v4.0.0, the `Authorization` header is required. For example: `{'Authorization': '<API token>'}` | N | Hash | {} |
|
93
|
+
`custom_http_headers` | Custom headers to send to Unleash. As of Unleash v4.0.0, the `Authorization` header is required. For example: `{'Authorization': '<API token>'}` | N | Hash/Proc | {} |
|
78
94
|
`timeout` | How long to wait for the connection to be established or wait in reading state (open_timeout/read_timeout) | N | Integer | 30 |
|
79
95
|
`retry_limit` | How many consecutive failures in connecting to the Unleash server are allowed before giving up. The default is to retry indefinitely. | N | Float::INFINITY | 5 |
|
80
96
|
`backup_file` | Filename to store the last known state from the Unleash server. Best to not change this from the default. | N | String | `Dir.tmpdir + "/unleash-#{app_name}-repo.json` |
|
@@ -95,7 +111,7 @@ Environment Variable | Description
|
|
95
111
|
require 'unleash'
|
96
112
|
require 'unleash/context'
|
97
113
|
|
98
|
-
@unleash = Unleash::Client.new(app_name: 'my_ruby_app', url: '
|
114
|
+
@unleash = Unleash::Client.new(app_name: 'my_ruby_app', url: 'https://unleash.herokuapp.com/api', custom_http_headers: { 'Authorization': '<API token>' })
|
99
115
|
|
100
116
|
feature_name = "AwesomeFeature"
|
101
117
|
unleash_context = Unleash::Context.new
|
@@ -117,7 +133,7 @@ Put in `config/initializers/unleash.rb`:
|
|
117
133
|
```ruby
|
118
134
|
Unleash.configure do |config|
|
119
135
|
config.app_name = Rails.application.class.parent.to_s
|
120
|
-
config.url = '
|
136
|
+
config.url = 'https://unleash.herokuapp.com/api'
|
121
137
|
# config.instance_id = "#{Socket.gethostname}"
|
122
138
|
config.logger = Rails.logger
|
123
139
|
config.environment = Rails.env
|
@@ -156,7 +172,7 @@ Then you may keep the client configuration still in `config/initializers/unleash
|
|
156
172
|
Unleash.configure do |config|
|
157
173
|
config.app_name = Rails.application.class.parent.to_s
|
158
174
|
config.environment = Rails.env
|
159
|
-
config.url = '
|
175
|
+
config.url = 'https://unleash.herokuapp.com/api'
|
160
176
|
config.custom_http_headers = {'Authorization': '<API token>'}
|
161
177
|
end
|
162
178
|
```
|
@@ -204,7 +220,7 @@ on_worker_boot do
|
|
204
220
|
::UNLEASH = Unleash::Client.new(
|
205
221
|
app_name: 'my_rails_app',
|
206
222
|
environment: 'development',
|
207
|
-
url: '
|
223
|
+
url: 'https://unleash.herokuapp.com/api',
|
208
224
|
custom_http_headers: {'Authorization': '<API token>'},
|
209
225
|
)
|
210
226
|
end
|
@@ -230,7 +246,7 @@ PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
|
230
246
|
# config.instance_id = "#{Socket.gethostname}"
|
231
247
|
config.logger = Rails.logger
|
232
248
|
config.environment = Rails.env
|
233
|
-
config.url = '
|
249
|
+
config.url = 'https://unleash.herokuapp.com/api'
|
234
250
|
config.custom_http_headers = {'Authorization': '<API token>'}
|
235
251
|
end
|
236
252
|
|
@@ -365,11 +381,11 @@ Bootstrap configuration allows the client to be initialized with a predefined se
|
|
365
381
|
Bootstrapping can be configured by providing a bootstrap configuration when initializing the client.
|
366
382
|
```ruby
|
367
383
|
@unleash = Unleash::Client.new(
|
368
|
-
url: '
|
384
|
+
url: 'https://unleash.herokuapp.com/api',
|
369
385
|
app_name: 'my_ruby_app',
|
370
386
|
custom_http_headers: { 'Authorization': '<API token>' },
|
371
387
|
bootstrap_config: Unleash::Bootstrap::Configuration.new({
|
372
|
-
url: "
|
388
|
+
url: "https://unleash.herokuapp.com/api/client/features",
|
373
389
|
url_headers: {'Authorization': '<API token>'}
|
374
390
|
})
|
375
391
|
)
|
@@ -395,7 +411,7 @@ Example usage:
|
|
395
411
|
|
396
412
|
First saving the toggles locally:
|
397
413
|
```shell
|
398
|
-
curl -H 'Authorization: <API token>' -XGET '
|
414
|
+
curl -H 'Authorization: <API token>' -XGET 'https://unleash.herokuapp.com/api' > ./default-toggles.json
|
399
415
|
```
|
400
416
|
|
401
417
|
Now using them on start up:
|
@@ -408,7 +424,7 @@ custom_boostrapper = lambda {
|
|
408
424
|
|
409
425
|
@unleash = Unleash::Client.new(
|
410
426
|
app_name: 'my_ruby_app',
|
411
|
-
url: '
|
427
|
+
url: 'https://unleash.herokuapp.com/api',
|
412
428
|
custom_http_headers: { 'Authorization': '<API token>' },
|
413
429
|
bootstrap_config: Unleash::Bootstrap::Configuration.new({
|
414
430
|
block: custom_boostrapper
|
data/examples/bootstrap.rb
CHANGED
@@ -7,7 +7,7 @@ require 'unleash/bootstrap/configuration'
|
|
7
7
|
puts ">> START bootstrap.rb"
|
8
8
|
|
9
9
|
@unleash = Unleash::Client.new(
|
10
|
-
url: '
|
10
|
+
url: 'https://unleash.herokuapp.com/api',
|
11
11
|
custom_http_headers: { 'Authorization': '943ca9171e2c884c545c5d82417a655fb77cec970cc3b78a8ff87f4406b495d0' },
|
12
12
|
app_name: 'bootstrap-test',
|
13
13
|
instance_id: 'local-test-cli',
|
data/examples/simple.rb
CHANGED
@@ -6,7 +6,7 @@ require 'unleash/context'
|
|
6
6
|
puts ">> START simple.rb"
|
7
7
|
|
8
8
|
# Unleash.configure do |config|
|
9
|
-
# config.url = '
|
9
|
+
# config.url = 'https://unleash.herokuapp.com/api'
|
10
10
|
# config.custom_http_headers = { 'Authorization': '943ca9171e2c884c545c5d82417a655fb77cec970cc3b78a8ff87f4406b495d0' }
|
11
11
|
# config.app_name = 'simple-test'
|
12
12
|
# config.refresh_interval = 2
|
@@ -18,7 +18,7 @@ puts ">> START simple.rb"
|
|
18
18
|
# or:
|
19
19
|
|
20
20
|
@unleash = Unleash::Client.new(
|
21
|
-
url: '
|
21
|
+
url: 'https://unleash.herokuapp.com/api',
|
22
22
|
custom_http_headers: { 'Authorization': '943ca9171e2c884c545c5d82417a655fb77cec970cc3b78a8ff87f4406b495d0' },
|
23
23
|
app_name: 'simple-test',
|
24
24
|
instance_id: 'local-test-cli',
|
@@ -23,7 +23,7 @@ module Unleash
|
|
23
23
|
:bootstrap_config
|
24
24
|
|
25
25
|
def initialize(opts = {})
|
26
|
-
|
26
|
+
validate_custom_http_headers!(opts[:custom_http_headers]) if opts.has_key?(:custom_http_headers)
|
27
27
|
set_defaults
|
28
28
|
|
29
29
|
initialize_default_logger if opts[:logger].nil?
|
@@ -40,7 +40,8 @@ module Unleash
|
|
40
40
|
return if self.disable_client
|
41
41
|
|
42
42
|
raise ArgumentError, "URL and app_name are required parameters." if self.app_name.nil? || self.url.nil?
|
43
|
-
|
43
|
+
|
44
|
+
validate_custom_http_headers!(self.custom_http_headers)
|
44
45
|
end
|
45
46
|
|
46
47
|
def refresh_backup_file!
|
@@ -51,7 +52,7 @@ module Unleash
|
|
51
52
|
{
|
52
53
|
'UNLEASH-INSTANCEID' => self.instance_id,
|
53
54
|
'UNLEASH-APPNAME' => self.app_name
|
54
|
-
}.merge(
|
55
|
+
}.merge!(generate_custom_http_headers)
|
55
56
|
end
|
56
57
|
|
57
58
|
def fetch_toggles_uri
|
@@ -78,12 +79,6 @@ module Unleash
|
|
78
79
|
|
79
80
|
private
|
80
81
|
|
81
|
-
def ensure_valid_opts(opts)
|
82
|
-
unless opts[:custom_http_headers].is_a?(Hash) || opts[:custom_http_headers].nil?
|
83
|
-
raise ArgumentError, "custom_http_headers must be a hash."
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
82
|
def set_defaults
|
88
83
|
self.app_name = nil
|
89
84
|
self.environment = 'default'
|
@@ -118,6 +113,18 @@ module Unleash
|
|
118
113
|
self
|
119
114
|
end
|
120
115
|
|
116
|
+
def validate_custom_http_headers!(custom_http_headers)
|
117
|
+
return if custom_http_headers.is_a?(Hash) || custom_http_headers.respond_to?(:call)
|
118
|
+
|
119
|
+
raise ArgumentError, "custom_http_headers must be a Hash or a Proc."
|
120
|
+
end
|
121
|
+
|
122
|
+
def generate_custom_http_headers
|
123
|
+
return self.custom_http_headers.call if self.custom_http_headers.respond_to?(:call)
|
124
|
+
|
125
|
+
self.custom_http_headers
|
126
|
+
end
|
127
|
+
|
121
128
|
def set_option(opt, val)
|
122
129
|
__send__("#{opt}=", val)
|
123
130
|
rescue NoMethodError
|
@@ -65,24 +65,20 @@ module Unleash
|
|
65
65
|
|
66
66
|
def save!
|
67
67
|
Unleash.logger.debug "Will save toggles to disk now"
|
68
|
-
begin
|
69
|
-
backup_file = Unleash.configuration.backup_file
|
70
|
-
backup_file_tmp = "#{backup_file}.tmp"
|
71
68
|
|
72
|
-
|
73
|
-
|
69
|
+
backup_file = Unleash.configuration.backup_file
|
70
|
+
backup_file_tmp = "#{backup_file}.tmp"
|
71
|
+
|
72
|
+
self.toggle_lock.synchronize do
|
73
|
+
File.open(backup_file_tmp, "w") do |file|
|
74
74
|
file.write(self.toggle_cache.to_json)
|
75
|
-
file.close
|
76
|
-
File.rename(backup_file_tmp, backup_file)
|
77
75
|
end
|
78
|
-
|
79
|
-
# This is not really the end of the world. Swallowing the exception.
|
80
|
-
Unleash.logger.error "Unable to save backup file. Exception thrown #{e.class}:'#{e}'"
|
81
|
-
Unleash.logger.error "stacktrace: #{e.backtrace}"
|
82
|
-
ensure
|
83
|
-
file&.close if defined?(file)
|
84
|
-
self.toggle_lock.unlock if self.toggle_lock.locked?
|
76
|
+
File.rename(backup_file_tmp, backup_file)
|
85
77
|
end
|
78
|
+
rescue StandardError => e
|
79
|
+
# This is not really the end of the world. Swallowing the exception.
|
80
|
+
Unleash.logger.error "Unable to save backup file. Exception thrown #{e.class}:'#{e}'"
|
81
|
+
Unleash.logger.error "stacktrace: #{e.backtrace}"
|
86
82
|
end
|
87
83
|
|
88
84
|
private
|
@@ -110,22 +106,15 @@ module Unleash
|
|
110
106
|
backup_file = Unleash.configuration.backup_file
|
111
107
|
return nil unless File.exist?(backup_file)
|
112
108
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
rescue JSON::ParserError => e
|
123
|
-
Unleash.logger.error "Unable to parse JSON from existing backup_file: #{e}"
|
124
|
-
rescue StandardError => e
|
125
|
-
Unleash.logger.error "Unable to extract valid data from backup_file. Exception thrown: #{e}"
|
126
|
-
ensure
|
127
|
-
file&.close
|
128
|
-
end
|
109
|
+
backup_as_hash = JSON.parse(File.read(backup_file))
|
110
|
+
synchronize_with_local_cache!(backup_as_hash)
|
111
|
+
update_running_client!
|
112
|
+
rescue IOError => e
|
113
|
+
Unleash.logger.error "Unable to read the backup_file: #{e}"
|
114
|
+
rescue JSON::ParserError => e
|
115
|
+
Unleash.logger.error "Unable to parse JSON from existing backup_file: #{e}"
|
116
|
+
rescue StandardError => e
|
117
|
+
Unleash.logger.error "Unable to extract valid data from backup_file. Exception thrown: #{e}"
|
129
118
|
end
|
130
119
|
|
131
120
|
def bootstrap
|
data/lib/unleash/version.rb
CHANGED
data/unleash-client.gemspec
CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_development_dependency "rspec-json_expectations", "~> 2.2"
|
32
32
|
spec.add_development_dependency "webmock", "~> 3.8"
|
33
33
|
|
34
|
-
spec.add_development_dependency "rubocop", "
|
34
|
+
spec.add_development_dependency "rubocop", "< 1.0.0"
|
35
35
|
spec.add_development_dependency "simplecov", "~> 0.21.2"
|
36
36
|
spec.add_development_dependency "simplecov-lcov", "~> 0.8.0"
|
37
37
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unleash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Renato Arruda
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: murmurhash3
|
@@ -98,16 +98,16 @@ dependencies:
|
|
98
98
|
name: rubocop
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - "<"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
103
|
+
version: 1.0.0
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - "
|
108
|
+
- - "<"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
110
|
+
version: 1.0.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: simplecov
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -146,6 +146,7 @@ executables:
|
|
146
146
|
extensions: []
|
147
147
|
extra_rdoc_files: []
|
148
148
|
files:
|
149
|
+
- ".github/workflows/add-to-project.yml"
|
149
150
|
- ".github/workflows/pull_request.yml"
|
150
151
|
- ".gitignore"
|
151
152
|
- ".rspec"
|