unleash 3.2.3 → 4.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 70d64956aa703576336ee95064ef909655a664159b571be5417ebf073f0de224
4
- data.tar.gz: 36cff93bb8203971721e3eeace2d24d9db4075926d2c2609e5c6acd01179c2fd
3
+ metadata.gz: 14f988b84b07e45401ad61a5814c1ca44185fc9358cef33f050b1d3bae45dd4e
4
+ data.tar.gz: afda9cf356088ef976047fe58d38d3b457fb1d8797cb7f519de6bdb953f43267
5
5
  SHA512:
6
- metadata.gz: 7b8c366cc799582a672646c796858381189e9286149929bb5e37afc2404cce9ac140b0c004ba8a3a7f774b0d83c705c2c714932656121054ab920f58afa55b34
7
- data.tar.gz: 6a4f8aa92aa80e17eb2477cc77a534dcbe44b2b63b3ff7c05867392252e808ec76750094adaf476c739c2641db1ef0f8a7c3729001fd7efe8ab209a255ebe968
6
+ metadata.gz: c1ac85ea8b774a230212583b33b9fdab3110fadab2fa1652810ea0913312c1fd20abe4471761b5ccd399d66a52995c0ddb6b803ee42aa4c4432add8a5524e51d
7
+ data.tar.gz: b03da5caf2bf25683b2d61599a37f15582d26664553ef72096dfd3073aceb96224eaa46fd19c948f9f4fc143e3226ee176a4e66d762016aedf736fb903edae85
@@ -0,0 +1,73 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+
10
+ runs-on: ${{ matrix.os }}-latest
11
+
12
+ strategy:
13
+ matrix:
14
+ os:
15
+ - ubuntu
16
+ - macos
17
+ ruby-version:
18
+ - jruby-9.2
19
+ - jruby-9.3
20
+ - 3.1
21
+ - 3.0
22
+ - 2.7
23
+ - 2.6
24
+ - 2.5
25
+
26
+ steps:
27
+ - uses: actions/checkout@v2
28
+ - name: Set up Ruby ${{ matrix.ruby-version }}
29
+ uses: ruby/setup-ruby@v1
30
+ with:
31
+ bundler-cache: true
32
+ ruby-version: ${{ matrix.ruby-version }}
33
+ - name: Install dependencies
34
+ run: bundle install
35
+ - name: Download test cases
36
+ run: git clone --depth 5 --branch v4.0.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
+ - name: Run tests
45
+ run: bundle exec rake
46
+ env:
47
+ COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48
+ - name: Coveralls Parallel
49
+ uses: coverallsapp/github-action@master
50
+ with:
51
+ github-token: ${{ secrets.GITHUB_TOKEN }}
52
+ flag-name: run-${{ matrix.test_number }}
53
+ parallel: true
54
+ - name: Notify Slack of pipeline completion
55
+ uses: 8398a7/action-slack@v3
56
+ if: ${{ github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name }}
57
+ with:
58
+ status: ${{ job.status }}
59
+ text: Built on ${{ matrix.os }} - Ruby ${{ matrix.ruby-version }}
60
+ fields: repo,message,commit,author,action,eventName,ref,workflow,job,took
61
+ env:
62
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
63
+
64
+ finish:
65
+ needs: test
66
+ runs-on: ubuntu-latest
67
+ steps:
68
+ - name: Coveralls Finished
69
+ uses: coverallsapp/github-action@master
70
+ with:
71
+ github-token: ${{ secrets.GITHUB_TOKEN }}
72
+ parallel-finished: true
73
+
data/.gitignore CHANGED
@@ -9,6 +9,9 @@
9
9
  /tmp/
10
10
  /vendor
11
11
 
12
+ # IntelliJ
13
+ .idea/
14
+
12
15
  # rspec failure tracking
13
16
  .rspec_status
14
17
 
data/.rubocop.yml CHANGED
@@ -14,17 +14,19 @@ Layout/LineLength:
14
14
  Metrics/MethodLength:
15
15
  Max: 20
16
16
  Metrics/BlockLength:
17
- Max: 100
17
+ Max: 110
18
18
  Exclude:
19
+ - 'spec/unleash/configuration_spec.rb'
19
20
  - 'spec/unleash/client_spec.rb'
21
+ - 'spec/unleash/context_spec.rb'
20
22
  - 'spec/unleash/feature_toggle_spec.rb'
21
23
 
22
24
  Metrics/AbcSize:
23
- Max: 25
25
+ Max: 28
24
26
  Metrics/CyclomaticComplexity:
25
27
  Max: 9
26
28
  Metrics/PerceivedComplexity:
27
- Max: 9
29
+ Max: 10
28
30
 
29
31
  Style/Documentation:
30
32
  Enabled: false
@@ -51,6 +53,12 @@ Style/HashTransformKeys:
51
53
  Enabled: true
52
54
  Style/HashTransformValues:
53
55
  Enabled: true
56
+ Style/EmptyElse:
57
+ Exclude:
58
+ - 'lib/unleash/strategy/flexible_rollout.rb'
59
+
60
+ Style/DoubleNegation:
61
+ Enabled: false
54
62
 
55
63
  Style/IfInsideElse:
56
64
  Exclude:
@@ -60,6 +68,61 @@ Style/Next:
60
68
  Exclude:
61
69
  - 'lib/unleash/scheduled_executor.rb'
62
70
 
71
+
72
+ Style/AccessorGrouping:
73
+ Enabled: true
74
+ Style/BisectedAttrAccessor:
75
+ Enabled: true
76
+ Style/CaseLikeIf:
77
+ Enabled: true
78
+ #Style/ClassEqualityComparison:
79
+ # Enabled: true
80
+ Style/CombinableLoops:
81
+ Enabled: true
82
+ Style/ExplicitBlockArgument:
83
+ Enabled: true
84
+ Style/ExponentialNotation:
85
+ Enabled: true
86
+ #Style/GlobalStdStream:
87
+ # Enabled: true
88
+ Style/HashAsLastArrayItem:
89
+ Enabled: true
90
+ Style/HashLikeCase:
91
+ Enabled: true
92
+ Style/KeywordParametersOrder:
93
+ Enabled: true
94
+ #Style/OptionalBooleanParameter:
95
+ # Enabled: false
96
+ Style/RedundantAssignment:
97
+ Enabled: true
98
+ Style/RedundantFetchBlock:
99
+ Enabled: true
100
+ Style/RedundantFileExtensionInRequire:
101
+ Enabled: true
102
+ Style/RedundantRegexpCharacterClass:
103
+ Enabled: true
104
+ Style/RedundantRegexpEscape:
105
+ Enabled: true
106
+ Style/RedundantSelfAssignment:
107
+ Enabled: true
108
+ Style/SingleArgumentDig:
109
+ Enabled: true
110
+ Style/SlicingWithRange:
111
+ Enabled: true
112
+ Style/SoleNestedConditional:
113
+ Enabled: true
114
+ Style/StringConcatenation:
115
+ Enabled: false
116
+ Style/TrailingCommaInHashLiteral:
117
+ Enabled: true
118
+ # EnforcedStyleForMultiline: consistent_comma
119
+
120
+ Layout/BeginEndAlignment:
121
+ Enabled: true
122
+ Layout/EmptyLinesAroundAttributeAccessor:
123
+ Enabled: true
124
+ Layout/SpaceAroundMethodCallOperator:
125
+ Enabled: true
63
126
  Layout/MultilineMethodCallIndentation:
64
127
  EnforcedStyle: indented
65
128
 
@@ -68,3 +131,50 @@ Layout/SpaceBeforeBlockBraces:
68
131
  Exclude:
69
132
  - 'unleash-client.gemspec'
70
133
  - 'spec/**/*.rb'
134
+
135
+ Lint/BinaryOperatorWithIdenticalOperands:
136
+ Enabled: true
137
+ Lint/ConstantDefinitionInBlock:
138
+ Enabled: false
139
+ Lint/DeprecatedOpenSSLConstant:
140
+ Enabled: true
141
+ Lint/DuplicateElsifCondition:
142
+ Enabled: true
143
+ Lint/DuplicateRequire:
144
+ Enabled: true
145
+ Lint/DuplicateRescueException:
146
+ Enabled: true
147
+ Lint/EmptyConditionalBody:
148
+ Enabled: true
149
+ Lint/EmptyFile:
150
+ Enabled: true
151
+ Lint/FloatComparison:
152
+ Enabled: true
153
+ Lint/HashCompareByIdentity:
154
+ Enabled: true
155
+ Lint/IdentityComparison:
156
+ Enabled: true
157
+ Lint/MissingSuper:
158
+ Enabled: false
159
+ Lint/MixedRegexpCaptureTypes:
160
+ Enabled: true
161
+ Lint/OutOfRangeRegexpRef:
162
+ Enabled: true
163
+ Lint/RaiseException:
164
+ Enabled: true
165
+ Lint/RedundantSafeNavigation:
166
+ Enabled: true
167
+ Lint/SelfAssignment:
168
+ Enabled: true
169
+ Lint/StructNewOverride:
170
+ Enabled: true
171
+ Lint/TopLevelReturnWithArgument:
172
+ Enabled: true
173
+ Lint/TrailingCommaInAttributeDeclaration:
174
+ Enabled: true
175
+ Lint/UnreachableLoop:
176
+ Enabled: true
177
+ Lint/UselessMethodDefinition:
178
+ Enabled: true
179
+ Lint/UselessTimes:
180
+ Enabled: true
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Unleash::Client
2
2
 
3
- [![Build Status](https://travis-ci.org/Unleash/unleash-client-ruby.svg?branch=master)](https://travis-ci.org/Unleash/unleash-client-ruby)
4
- [![Coverage Status](https://coveralls.io/repos/github/Unleash/unleash-client-ruby/badge.svg?branch=master)](https://coveralls.io/github/Unleash/unleash-client-ruby?branch=master)
3
+ ![Build Status](https://github.com/Unleash/unleash-client-ruby/actions/workflows/pull_request.yml/badge.svg?branch=main)
4
+ [![Coverage Status](https://coveralls.io/repos/github/Unleash/unleash-client-ruby/badge.svg?branch=main)](https://coveralls.io/github/Unleash/unleash-client-ruby?branch=main)
5
5
  [![Gem Version](https://badge.fury.io/rb/unleash.svg)](https://badge.fury.io/rb/unleash)
6
6
 
7
7
  Unleash client so you can roll out your features with confidence.
@@ -10,18 +10,20 @@ Leverage the [Unleash Server](https://github.com/Unleash/unleash) for powerful f
10
10
 
11
11
  ## Supported Ruby Interpreters
12
12
 
13
+ * MRI 3.1
13
14
  * MRI 3.0
14
15
  * MRI 2.7
15
16
  * MRI 2.6
16
17
  * MRI 2.5
17
- * jruby
18
+ * jruby 9.3
19
+ * jruby 9.2
18
20
 
19
21
  ## Installation
20
22
 
21
23
  Add this line to your application's Gemfile:
22
24
 
23
25
  ```ruby
24
- gem 'unleash', '~> 3.2.3'
26
+ gem 'unleash', '~> 4.0.0'
25
27
  ```
26
28
 
27
29
  And then execute:
@@ -34,22 +36,29 @@ Or install it yourself as:
34
36
 
35
37
  ## Configure
36
38
 
37
- It is **required** to configure the `url` of the unleash server and `app_name` with the name of the runninng application. Please substitute the sample `'http://unleash.herokuapp.com/api'` for the url of your own instance.
39
+ It is **required** to configure:
40
+ - `url` of the unleash server
41
+ - `app_name` with the name of the runninng application.
42
+ - `custom_http_headers` with `{'Authorization': '<API token>'}` when using Unleash v4.0.0 and later.
38
43
 
39
- It is **highly recommended** to configure the `instance_id` parameter as well.
44
+ Please substitute the example `'http://unleash.herokuapp.com/api'` for the url of your own instance.
45
+
46
+ It is **highly recommended** to configure:
47
+ - `instance_id` parameter with a unique identifier for the running instance.
40
48
 
41
49
 
42
50
  ```ruby
43
51
  Unleash.configure do |config|
44
- config.url = 'http://unleash.herokuapp.com/api'
45
- config.app_name = 'my_ruby_app'
52
+ config.app_name = 'my_ruby_app'
53
+ config.url = 'http://unleash.herokuapp.com/api'
54
+ config.custom_http_headers = {'Authorization': '<API token>'}
46
55
  end
47
56
  ```
48
57
 
49
58
  or instantiate the client with the valid configuration:
50
59
 
51
60
  ```ruby
52
- UNLEASH = Unleash::Client.new(url: 'http://unleash.herokuapp.com/api', app_name: 'my_ruby_app')
61
+ UNLEASH = Unleash::Client.new(url: 'http://unleash.herokuapp.com/api', app_name: 'my_ruby_app', custom_http_headers: {'Authorization': '<API token>'})
53
62
  ```
54
63
 
55
64
  #### List of Arguments
@@ -60,19 +69,25 @@ Argument | Description | Required? | Type | Default Value|
60
69
  `app_name` | Name of your program. | Y | String | N/A |
61
70
  `instance_id` | Identifier for the running instance of program. Important so you can trace back to where metrics are being collected from. **Highly recommended be be set.** | N | String | random UUID |
62
71
  `environment` | Environment the program is running on. Could be for example `prod` or `dev`. Not yet in use. | N | String | `default` |
72
+ `project_name` | Name of the project to retrieve features from. If not set, all feature flags will be retrieved. | N | String | nil |
63
73
  `refresh_interval` | How often the unleash client should check with the server for configuration changes. | N | Integer | 15 |
64
- `metrics_interval` | How often the unleash client should send metrics to server. | N | Integer | 10 |
74
+ `metrics_interval` | How often the unleash client should send metrics to server. | N | Integer | 60 |
65
75
  `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` |
66
76
  `disable_metrics` | Disables sending metrics to Unleash server. | N | Boolean | `false` |
67
- `custom_http_headers` | Custom headers to send to Unleash. | N | Hash | {} |
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 | {} |
68
78
  `timeout` | How long to wait for the connection to be established or wait in reading state (open_timeout/read_timeout) | N | Integer | 30 |
69
79
  `retry_limit` | How many consecutive failures in connecting to the Unleash server are allowed before giving up. Use `Float::INFINITY` if you would like it to never give up. | N | Numeric | 5 |
70
80
  `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` |
71
81
  `logger` | Specify a custom `Logger` class to handle logs for the Unleash client. | N | Class | `Logger.new(STDOUT)` |
72
- `log_level` | Change the log level for the `Logger` class. Constant from `Logger::Severity`. | N | Constant | `Logger::ERROR` |
82
+ `log_level` | Change the log level for the `Logger` class. Constant from `Logger::Severity`. | N | Constant | `Logger::WARN` |
83
+ `bootstrap_config` | Bootstrap config on how to loaded data on start-up. This is useful for loading large states on startup without (or before) hitting the network. | N | Unleash::Bootstrap::Configuration | `nil` |
73
84
 
74
- For in a more in depth look, please see `lib/unleash/configuration.rb`.
85
+ For a more in-depth look, please see `lib/unleash/configuration.rb`.
75
86
 
87
+ Environment Variable | Description
88
+ ---------|---------
89
+ `UNLEASH_BOOTSTRAP_FILE` | File to read bootstrap data from
90
+ `UNLEASH_BOOTSTRAP_URL` | URL to read bootstrap data from
76
91
 
77
92
  ## Usage in a plain Ruby Application
78
93
 
@@ -80,7 +95,7 @@ For in a more in depth look, please see `lib/unleash/configuration.rb`.
80
95
  require 'unleash'
81
96
  require 'unleash/context'
82
97
 
83
- @unleash = Unleash::Client.new(url: 'http://unleash.herokuapp.com/api', app_name: 'my_ruby_app')
98
+ @unleash = Unleash::Client.new(app_name: 'my_ruby_app', url: 'http://unleash.herokuapp.com/api', custom_http_headers: { 'Authorization': '<API token>' })
84
99
 
85
100
  feature_name = "AwesomeFeature"
86
101
  unleash_context = Unleash::Context.new
@@ -101,8 +116,8 @@ Put in `config/initializers/unleash.rb`:
101
116
 
102
117
  ```ruby
103
118
  Unleash.configure do |config|
104
- config.url = 'http://unleash.herokuapp.com/api'
105
119
  config.app_name = Rails.application.class.parent.to_s
120
+ config.url = 'http://unleash.herokuapp.com/api'
106
121
  # config.instance_id = "#{Socket.gethostname}"
107
122
  config.logger = Rails.logger
108
123
  config.environment = Rails.env
@@ -122,9 +137,10 @@ on_worker_boot do
122
137
  # ...
123
138
 
124
139
  Unleash.configure do |config|
125
- config.url = 'http://unleash.herokuapp.com/api'
126
- config.app_name = Rails.application.class.parent.to_s
140
+ config.app_name = Rails.application.class.parent.to_s
127
141
  config.environment = Rails.env
142
+ config.url = 'http://unleash.herokuapp.com/api'
143
+ config.custom_http_headers = {'Authorization': '<API token>'}
128
144
  end
129
145
  Rails.configuration.unleash = Unleash::Client.new
130
146
  end
@@ -132,6 +148,28 @@ end
132
148
 
133
149
  Instead of the configuration in `config/initializers/unleash.rb`.
134
150
 
151
+ #### Add Initializer if using [Phusion Passenger](https://github.com/phusion/passenger)
152
+
153
+ The unleash client needs to be configured and instantiated inside the `PhusionPassenger.on_event(:starting_worker_process)` code block due to [smart spawning](https://www.phusionpassenger.com/library/indepth/ruby/spawn_methods/#smart-spawning-caveats):
154
+
155
+ The initializer in `config/initializers/unleash.rb` should look like:
156
+
157
+ ```ruby
158
+ PhusionPassenger.on_event(:starting_worker_process) do |forked|
159
+ if forked
160
+ Unleash.configure do |config|
161
+ config.app_name = Rails.application.class.parent.to_s
162
+ # config.instance_id = "#{Socket.gethostname}"
163
+ config.logger = Rails.logger
164
+ config.environment = Rails.env
165
+ config.url = 'http://unleash.herokuapp.com/api'
166
+ config.custom_http_headers = {'Authorization': '<API token>'}
167
+ end
168
+
169
+ UNLEASH = Unleash::Client.new
170
+ end
171
+ end
172
+ ```
135
173
 
136
174
  #### Set Unleash::Context
137
175
 
@@ -180,6 +218,40 @@ if UNLEASH.is_enabled? "AwesomeFeature", @unleash_context, true
180
218
  end
181
219
  ```
182
220
 
221
+ Another possibility is to send a block, [Lambda](https://ruby-doc.org/core-3.0.1/Kernel.html#method-i-lambda) or [Proc](https://ruby-doc.org/core-3.0.1/Proc.html#method-i-yield)
222
+ to evaluate the default value:
223
+
224
+ ```ruby
225
+ net_check_proc = proc do |feature_name, context|
226
+ context.remote_address.starts_with?("10.0.0.")
227
+ end
228
+
229
+ if UNLEASH.is_enabled?("AwesomeFeature", @unleash_context, &net_check_proc)
230
+ puts "AwesomeFeature is enabled by default if you are in the 10.0.0.* network."
231
+ end
232
+ ```
233
+
234
+ or
235
+
236
+ ```ruby
237
+ awesomeness = 10
238
+ @unleash_context.properties[:coolness] = 10
239
+
240
+ if UNLEASH.is_enabled?("AwesomeFeature", @unleash_context) { |feat, ctx| awesomeness >= 6 && ctx.properties[:coolness] >= 8 }
241
+ puts "AwesomeFeature is enabled by default if both the user has a high enought coolness and the application has a high enough awesomeness"
242
+ end
243
+ ```
244
+
245
+ Note:
246
+ - The block/lambda/proc can use feature name and context as an arguments.
247
+ - The client will evaluate the fallback function once per call of `is_enabled()`.
248
+ Please keep this in mind when creating your fallback function!
249
+ - The returned value of the block should be a boolean.
250
+ However the client will coerce the result to boolean via `!!`.
251
+ - If both a `default_value` and `fallback_function` are supplied,
252
+ the client will define the default value by `OR`ing the default value and the output of the fallback function.
253
+
254
+
183
255
  Alternatively by using `if_enabled` you can send a code block to be executed as a parameter:
184
256
 
185
257
  ```ruby
@@ -188,6 +260,8 @@ UNLEASH.if_enabled "AwesomeFeature", @unleash_context, true do
188
260
  end
189
261
  ```
190
262
 
263
+ Note: `if_enabled` only supports `default_value`, but not `fallback_function`.
264
+
191
265
  ##### Variations
192
266
 
193
267
  If no variant is found in the server, use the fallback variant.
@@ -199,6 +273,62 @@ variant = UNLEASH.get_variant "ColorVariants", @unleash_context, fallback_varian
199
273
  puts "variant color is: #{variant.payload.fetch('color')}"
200
274
  ```
201
275
 
276
+ ## Bootstrapping
277
+
278
+ Bootstrap configuration allows the client to be initialized with a predefined set of toggle states. Bootstrapping can be configured by providing a bootstrap configuration when initializing the client.
279
+ ```ruby
280
+ @unleash = Unleash::Client.new(
281
+ url: 'http://unleash.herokuapp.com/api',
282
+ app_name: 'my_ruby_app',
283
+ custom_http_headers: { 'Authorization': '<API token>' },
284
+ bootstrap_config: Unleash::Bootstrap::Configuration.new({
285
+ url: "http://unleash.herokuapp.com/api/client/features",
286
+ url_headers: {'Authorization': '<API token>'}
287
+ })
288
+ )
289
+ ```
290
+ The `Bootstrap::Configuration` initializer takes a hash with one of the following options specified:
291
+
292
+ * `file_path` - An absolute or relative path to a file containing a JSON string of the response body from the Unleash server. This can also be set though the `UNLEASH_BOOTSTRAP_FILE` environment variable.
293
+ * `url` - A url pointing to an Unleash server's features endpoint, the code sample above is illustrative. This can also be set though the `UNLEASH_BOOTSTRAP_URL` environment variable.
294
+ * `url_headers` - Headers for the GET http request to the `url` above. Only used if the `url` parameter is also set. If this option isn't set then the bootstrapper will use the same url headers as the Unleash client.
295
+ * `data` - A raw JSON string as returned by the Unleash server.
296
+ * `block` - A lambda containing custom logic if you need it, an example is provided below.
297
+
298
+ You should only specify one type of bootstrapping since only one will be invoked and the others will be ignored. The order of preference is as follows:
299
+
300
+ - Select a data bootstrapper if it exists.
301
+ - If no data bootstrapper exists, select the block bootstrapper.
302
+ - If no block bootstrapper exists, select the file bootstrapper from either parameters or the specified environment variable.
303
+ - If no file bootstrapper exists, then check for a URL bootstrapper from either the parameters or the specified environment variable.
304
+
305
+
306
+ Example usage:
307
+
308
+ First saving the toggles locally:
309
+ ```shell
310
+ curl -H 'Authorization: <API token>' -XGET 'http://unleash.herokuapp.com/api' > ./default-toggles.json
311
+ ```
312
+
313
+ Now using them on start up:
314
+
315
+ ```ruby
316
+
317
+ custom_boostrapper = lambda {
318
+ File.read('./default-toggles.json')
319
+ }
320
+
321
+ @unleash = Unleash::Client.new(
322
+ app_name: 'my_ruby_app',
323
+ url: 'http://unleash.herokuapp.com/api',
324
+ custom_http_headers: { 'Authorization': '<API token>' },
325
+ bootstrap_config: Unleash::Bootstrap::Configuration.new({
326
+ block: custom_boostrapper
327
+ }
328
+ )
329
+ ```
330
+
331
+ This example could be easily achieved with a file bootstrapper, this is just to illustrate the usage of custom bootstrapping. Be aware that the client initializer will block until bootstrapping is complete.
202
332
 
203
333
  #### Client methods
204
334
 
@@ -211,6 +341,7 @@ Method Name | Description | Return Type |
211
341
  `shutdown` | Save metrics to disk, flush metrics to server, and then kill ToggleFetcher and MetricsReporter threads. A safe shutdown. Not really useful in long running applications, like web applications. | nil |
212
342
  `shutdown!` | Kill ToggleFetcher and MetricsReporter threads immediately. | nil |
213
343
 
344
+ For the full method signatures, please see [client.rb](lib/unleash/client.rb)
214
345
 
215
346
  ## Local test client
216
347
 
@@ -228,6 +359,7 @@ This client comes with the all the required strategies out of the box:
228
359
 
229
360
  * ApplicationHostnameStrategy
230
361
  * DefaultStrategy
362
+ * FlexibleRolloutStrategy
231
363
  * GradualRolloutRandomStrategy
232
364
  * GradualRolloutSessionIdStrategy
233
365
  * GradualRolloutUserIdStrategy
@@ -235,7 +367,6 @@ This client comes with the all the required strategies out of the box:
235
367
  * UnknownStrategy
236
368
  * UserWithIdStrategy
237
369
 
238
-
239
370
  ## Development
240
371
 
241
372
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/bin/unleash-client CHANGED
@@ -12,11 +12,13 @@ options = {
12
12
  url: 'http://localhost:4242',
13
13
  demo: false,
14
14
  disable_metrics: true,
15
+ custom_http_headers: {},
15
16
  sleep: 0.1
16
17
  }
17
18
 
18
19
  OptionParser.new do |opts|
19
- opts.banner = "Usage: #{__FILE__} [options] feature [key1=val1] [key2=val2]"
20
+ opts.banner = "Usage: #{__FILE__} [options] feature [contextKey1=val1] [contextKey2=val2] \n\n" \
21
+ "Where contextKey1 could be user_id, session_id, remote_address or any field in the Context class (or any property within it).\n"
20
22
 
21
23
  opts.on("-V", "--variant", "Fetch variant for feature") do |v|
22
24
  options[:variant] = v
@@ -46,6 +48,13 @@ OptionParser.new do |opts|
46
48
  options[:sleep] = s
47
49
  end
48
50
 
51
+ opts.on("-H", "--http-headers='Authorization: *:developement.secretstring'",
52
+ "Adds http headers to all requests on the unleash server. Use multiple times for multiple headers.") do |h|
53
+ http_header_as_hash = [h].to_h{ |l| l.split(": ") }.transform_keys(&:to_sym)
54
+
55
+ options[:custom_http_headers].merge!(http_header_as_hash)
56
+ end
57
+
49
58
  opts.on("-h", "--help", "Prints this help") do
50
59
  puts opts
51
60
  exit
@@ -70,10 +79,11 @@ log_level = \
70
79
  url: options[:url],
71
80
  app_name: 'unleash-client-ruby-cli',
72
81
  disable_metrics: options[:metrics],
82
+ custom_http_headers: options[:custom_http_headers],
73
83
  log_level: log_level
74
84
  )
75
85
 
76
- context_params = ARGV.map{ |e| e.split("=") }.map{ |k, v| [k.to_sym, v] }.to_h
86
+ context_params = ARGV.to_h{ |l| l.split("=") }.transform_keys(&:to_sym)
77
87
  context_properties = context_params.reject{ |k, _v| [:user_id, :session_id, :remote_address].include? k }
78
88
  context_params.select!{ |k, _v| [:user_id, :session_id, :remote_address].include? k }
79
89
  context_params.merge!(properties: context_properties) unless context_properties.nil?
@@ -97,12 +107,12 @@ if options[:demo]
97
107
  end
98
108
  elsif options[:variant]
99
109
  variant = @unleash.get_variant(feature_name, unleash_context)
100
- puts " For feature \'#{feature_name}\' got variant \'#{variant}\'"
110
+ puts " For feature '#{feature_name}' got variant '#{variant}'"
101
111
  else
102
112
  if @unleash.is_enabled?(feature_name, unleash_context)
103
- puts " \'#{feature_name}\' is enabled according to unleash"
113
+ puts " '#{feature_name}' is enabled according to unleash"
104
114
  else
105
- puts " \'#{feature_name}\' is disabled according to unleash"
115
+ puts " '#{feature_name}' is disabled according to unleash"
106
116
  end
107
117
  end
108
118
 
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'unleash'
4
+ require 'unleash/context'
5
+ require 'unleash/bootstrap/configuration'
6
+
7
+ puts ">> START bootstrap.rb"
8
+
9
+ @unleash = Unleash::Client.new(
10
+ url: 'http://unleash.herokuapp.com/api',
11
+ custom_http_headers: { 'Authorization': '943ca9171e2c884c545c5d82417a655fb77cec970cc3b78a8ff87f4406b495d0' },
12
+ app_name: 'bootstrap-test',
13
+ instance_id: 'local-test-cli',
14
+ refresh_interval: 2,
15
+ disable_client: true,
16
+ disable_metrics: true,
17
+ metrics_interval: 2,
18
+ retry_limit: 2,
19
+ bootstrap_config: Unleash::Bootstrap::Configuration.new(file_path: "examples/default-toggles.json")
20
+ )
21
+
22
+ feature_name = "featureX"
23
+ unleash_context = Unleash::Context.new
24
+ unleash_context.user_id = 123
25
+
26
+ sleep 1
27
+ 3.times do
28
+ if @unleash.is_enabled?(feature_name, unleash_context)
29
+ puts "> #{feature_name} is enabled"
30
+ else
31
+ puts "> #{feature_name} is not enabled"
32
+ end
33
+ sleep 1
34
+ puts "---"
35
+ puts ""
36
+ puts ""
37
+ end
38
+
39
+ sleep 3
40
+ feature_name = "foobar"
41
+ if @unleash.is_enabled?(feature_name, unleash_context, true)
42
+ puts "> #{feature_name} is enabled"
43
+ else
44
+ puts "> #{feature_name} is not enabled"
45
+ end
46
+
47
+ puts "> shutting down client..."
48
+
49
+ @unleash.shutdown
50
+
51
+ puts ">> END bootstrap.rb"
@@ -0,0 +1,42 @@
1
+ {
2
+ "version": 1,
3
+ "features": [
4
+ {
5
+ "name": "featureX",
6
+ "enabled": true,
7
+ "strategies": [
8
+ {
9
+ "name": "default"
10
+ }
11
+ ]
12
+ },
13
+ {
14
+ "name": "featureY",
15
+ "enabled": false,
16
+ "strategies": [
17
+ {
18
+ "name": "baz",
19
+ "parameters": {
20
+ "foo": "bar"
21
+ }
22
+ }
23
+ ]
24
+ },
25
+ {
26
+ "name": "featureZ",
27
+ "enabled": true,
28
+ "strategies": [
29
+ {
30
+ "name": "default"
31
+ },
32
+ {
33
+ "name": "hola",
34
+ "parameters": {
35
+ "name": "val"
36
+ }
37
+ }
38
+ ]
39
+ }
40
+ ]
41
+ }
42
+