flipper 0.22.0 → 0.23.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.
- checksums.yaml +4 -4
- data/.codeclimate.yml +1 -0
- data/.github/workflows/ci.yml +6 -6
- data/.github/workflows/examples.yml +57 -0
- data/.rspec +1 -0
- data/Changelog.md +48 -3
- data/Gemfile +2 -2
- data/README.md +15 -67
- data/docker-compose.yml +37 -34
- data/docs/README.md +1 -0
- data/docs/images/banner.jpg +0 -0
- data/examples/instrumentation_last_accessed_at.rb +37 -0
- data/lib/flipper/adapters/dual_write.rb +9 -15
- data/lib/flipper/adapters/failover.rb +83 -0
- data/lib/flipper/adapters/http/client.rb +11 -1
- data/lib/flipper/adapters/http/error.rb +19 -1
- data/lib/flipper/adapters/memoizable.rb +8 -16
- data/lib/flipper/adapters/pstore.rb +2 -5
- data/lib/flipper/adapters/sync/interval_synchronizer.rb +1 -6
- data/lib/flipper/adapters/sync/synchronizer.rb +2 -1
- data/lib/flipper/adapters/sync.rb +9 -15
- data/lib/flipper/instrumenters/memory.rb +6 -2
- data/lib/flipper/railtie.rb +18 -17
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/actor_spec.rb +0 -2
- data/spec/flipper/adapter_spec.rb +0 -2
- data/spec/flipper/adapters/dual_write_spec.rb +0 -2
- data/spec/flipper/adapters/failover_spec.rb +129 -0
- data/spec/flipper/adapters/http_spec.rb +39 -3
- data/spec/flipper/adapters/instrumented_spec.rb +0 -2
- data/spec/flipper/adapters/memoizable_spec.rb +0 -2
- data/spec/flipper/adapters/memory_spec.rb +0 -3
- data/spec/flipper/adapters/operation_logger_spec.rb +0 -2
- data/spec/flipper/adapters/pstore_spec.rb +0 -2
- data/spec/flipper/adapters/read_only_spec.rb +0 -1
- data/spec/flipper/adapters/sync/feature_synchronizer_spec.rb +0 -1
- data/spec/flipper/adapters/sync/interval_synchronizer_spec.rb +4 -5
- data/spec/flipper/adapters/sync/synchronizer_spec.rb +0 -1
- data/spec/flipper/adapters/sync_spec.rb +0 -2
- data/spec/flipper/configuration_spec.rb +0 -1
- data/spec/flipper/dsl_spec.rb +0 -1
- data/spec/flipper/feature_check_context_spec.rb +0 -2
- data/spec/flipper/feature_spec.rb +0 -1
- data/spec/flipper/gate_spec.rb +0 -2
- data/spec/flipper/gate_values_spec.rb +0 -1
- data/spec/flipper/gates/actor_spec.rb +0 -2
- data/spec/flipper/gates/boolean_spec.rb +0 -2
- data/spec/flipper/gates/group_spec.rb +0 -2
- data/spec/flipper/gates/percentage_of_actors_spec.rb +0 -2
- data/spec/flipper/gates/percentage_of_time_spec.rb +0 -2
- data/spec/flipper/identifier_spec.rb +0 -1
- data/spec/flipper/instrumentation/log_subscriber_spec.rb +0 -1
- data/spec/flipper/instrumentation/statsd_subscriber_spec.rb +0 -1
- data/spec/flipper/instrumenters/memory_spec.rb +18 -1
- data/spec/flipper/instrumenters/noop_spec.rb +14 -8
- data/spec/flipper/middleware/memoizer_spec.rb +0 -3
- data/spec/flipper/middleware/setup_env_spec.rb +0 -2
- data/spec/flipper/railtie_spec.rb +37 -33
- data/spec/flipper/registry_spec.rb +0 -1
- data/spec/flipper/typecast_spec.rb +0 -1
- data/spec/flipper/types/actor_spec.rb +0 -1
- data/spec/flipper/types/boolean_spec.rb +0 -1
- data/spec/flipper/types/group_spec.rb +0 -1
- data/spec/flipper/types/percentage_of_actors_spec.rb +0 -1
- data/spec/flipper/types/percentage_of_time_spec.rb +0 -1
- data/spec/flipper/types/percentage_spec.rb +0 -1
- data/spec/flipper_integration_spec.rb +0 -1
- data/spec/flipper_spec.rb +0 -1
- data/spec/{helper.rb → spec_helper.rb} +2 -1
- data/spec/support/spec_helpers.rb +2 -6
- metadata +12 -13
- data/docs/Adapters.md +0 -124
- data/docs/Caveats.md +0 -4
- data/docs/Gates.md +0 -167
- data/docs/Instrumentation.md +0 -27
- data/docs/Optimization.md +0 -137
- data/docs/api/README.md +0 -884
- data/docs/http/README.md +0 -36
- data/docs/read-only/README.md +0 -24
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a41bf1dd43734d1d6c6b56a46ea393af74164d46aadd7671994bdcc10e4eb646
|
|
4
|
+
data.tar.gz: e935dc1375a66156f0d0f7ba967269d184b8babaf119333c614943643f760ed7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 82d249a9f90b96fcf88713890a2df5a7fa5f05927b7a1903630e276507ee709b5426b91fba46aa6ef034e15dc6b50b35781d61b56afe512a46673e4de3eb559d
|
|
7
|
+
data.tar.gz: c986d6fb7c1a773ab56e6b7cb35734648485562690799dff901578b2c31566f5582bb8390268228f48eda9fba6797f8b72bd7fd385e45a9a04155c14a4c8b95f
|
data/.codeclimate.yml
CHANGED
data/.github/workflows/ci.yml
CHANGED
|
@@ -16,7 +16,12 @@ jobs:
|
|
|
16
16
|
strategy:
|
|
17
17
|
matrix:
|
|
18
18
|
ruby: ['2.5', '2.6', '2.7']
|
|
19
|
-
rails: ['5.2', '6.0.0', '6.1.0']
|
|
19
|
+
rails: ['5.2', '6.0.0', '6.1.0', '7.0.0']
|
|
20
|
+
exclude:
|
|
21
|
+
- ruby: "2.5"
|
|
22
|
+
rails: "7.0.0"
|
|
23
|
+
- ruby: "2.6"
|
|
24
|
+
rails: "7.0.0"
|
|
20
25
|
env:
|
|
21
26
|
SQLITE3_VERSION: 1.4.1
|
|
22
27
|
REDIS_URL: redis://localhost:6379/0
|
|
@@ -51,8 +56,3 @@ jobs:
|
|
|
51
56
|
run: |
|
|
52
57
|
bundle install --jobs 4 --retry 3
|
|
53
58
|
bundle exec rake
|
|
54
|
-
- name: Run Examples with Rails ${{ matrix.rails }}
|
|
55
|
-
env:
|
|
56
|
-
FLIPPER_CLOUD_TOKEN: ${{ secrets.FLIPPER_CLOUD_TOKEN }}
|
|
57
|
-
RAILS_VERSION: ${{ matrix.rails }}
|
|
58
|
-
run: script/examples
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Examples
|
|
2
|
+
on: [push, pull_request]
|
|
3
|
+
jobs:
|
|
4
|
+
test:
|
|
5
|
+
if: github.repository_owner == 'jnunemaker'
|
|
6
|
+
name: Test on ruby ${{ matrix.ruby }} and rails ${{ matrix.rails }}
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
services:
|
|
9
|
+
redis:
|
|
10
|
+
image: redis
|
|
11
|
+
ports: ['6379:6379']
|
|
12
|
+
options: >-
|
|
13
|
+
--health-cmd "redis-cli ping"
|
|
14
|
+
--health-interval 10s
|
|
15
|
+
--health-timeout 5s
|
|
16
|
+
--health-retries 5
|
|
17
|
+
strategy:
|
|
18
|
+
matrix:
|
|
19
|
+
ruby: ['2.5', '2.6', '2.7']
|
|
20
|
+
rails: ['5.2', '6.0.0', '6.1.0']
|
|
21
|
+
env:
|
|
22
|
+
SQLITE3_VERSION: 1.4.1
|
|
23
|
+
REDIS_URL: redis://localhost:6379/0
|
|
24
|
+
CI: true
|
|
25
|
+
steps:
|
|
26
|
+
- name: Setup memcached
|
|
27
|
+
uses: KeisukeYamashita/memcached-actions@v1
|
|
28
|
+
- name: Start MongoDB
|
|
29
|
+
uses: supercharge/mongodb-github-action@1.3.0
|
|
30
|
+
with:
|
|
31
|
+
mongodb-version: 4.0
|
|
32
|
+
- name: Check out repository code
|
|
33
|
+
uses: actions/checkout@v2
|
|
34
|
+
- name: Do some action caching
|
|
35
|
+
uses: actions/cache@v1
|
|
36
|
+
with:
|
|
37
|
+
path: vendor/bundle
|
|
38
|
+
key: ${{ runner.os }}-gems-${{ matrix.ruby }}-${{ matrix.rails }}-${{ hashFiles('**/Gemfile.lock') }}
|
|
39
|
+
restore-keys: |
|
|
40
|
+
${{ runner.os }}-gems-${{ matrix.ruby }}-${{ matrix.rails }}-
|
|
41
|
+
- name: Set up Ruby ${{ matrix.ruby }}
|
|
42
|
+
uses: actions/setup-ruby@v1
|
|
43
|
+
with:
|
|
44
|
+
ruby-version: ${{ matrix.ruby }}
|
|
45
|
+
- name: Install libpq-dev
|
|
46
|
+
run: sudo apt-get -yqq install libpq-dev
|
|
47
|
+
- name: Install bundler
|
|
48
|
+
run: gem install bundler
|
|
49
|
+
- name: Bundle install with Rails ${{ matrix.rails }}
|
|
50
|
+
env:
|
|
51
|
+
RAILS_VERSION: ${{ matrix.rails }}
|
|
52
|
+
run: bundle install --jobs 4 --retry 3
|
|
53
|
+
- name: Run Examples with Rails ${{ matrix.rails }}
|
|
54
|
+
env:
|
|
55
|
+
FLIPPER_CLOUD_TOKEN: ${{ secrets.FLIPPER_CLOUD_TOKEN }}
|
|
56
|
+
RAILS_VERSION: ${{ matrix.rails }}
|
|
57
|
+
run: script/examples
|
data/.rspec
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--require spec_helper
|
data/Changelog.md
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
|
+
## 0.23.1
|
|
2
|
+
|
|
3
|
+
### Additions/Changes
|
|
4
|
+
|
|
5
|
+
* Relax dalli version constraint (https://github.com/jnunemaker/flipper/pull/596)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
* Fix railtie initialization to mount middleware after config/intializers/* (https://github.com/jnunemaker/flipper/pull/586)
|
|
10
|
+
|
|
11
|
+
## 0.23.0
|
|
12
|
+
|
|
13
|
+
### Additions/Changes
|
|
14
|
+
|
|
15
|
+
* Allow some HTML in banner and descriptions (https://github.com/jnunemaker/flipper/pull/570).
|
|
16
|
+
* Moved some cloud headers to http client (https://github.com/jnunemaker/flipper/pull/567).
|
|
17
|
+
* Update flipper-ui jquery and bootstrap versions (https://github.com/jnunemaker/flipper/issues/565 and https://github.com/jnunemaker/flipper/pull/566).
|
|
18
|
+
* Moved docs to www.flippercloud.io/docs (https://github.com/jnunemaker/flipper/pull/574).
|
|
19
|
+
* PStore adapter now defaults to thread safe and no longer supports `.thread_safe` (https://github.com/jnunemaker/flipper/commit/4048704fefe41b716015294a19a0b94546637630).
|
|
20
|
+
* Add failover adapter (https://github.com/jnunemaker/flipper/pull/584).
|
|
21
|
+
* Improve http adapter error message (https://github.com/jnunemaker/flipper/pull/587).
|
|
22
|
+
* Rails 7 support (mostly in https://github.com/jnunemaker/flipper/pull/592).
|
|
23
|
+
|
|
24
|
+
## 0.22.2
|
|
25
|
+
|
|
26
|
+
### Additions/Changes
|
|
27
|
+
|
|
28
|
+
* Allow adding multiple actors at once in flipper-ui via comma separation (configurable via `Flipper::UI.configuration.actors_separator`) (https://github.com/jnunemaker/flipper/pull/556)
|
|
29
|
+
|
|
30
|
+
### Bug Fixes
|
|
31
|
+
|
|
32
|
+
* Fix railtie initialization to avoid altering middleware order (https://github.com/jnunemaker/flipper/pull/563)
|
|
33
|
+
|
|
34
|
+
## 0.22.1
|
|
35
|
+
|
|
36
|
+
### Additions/Changes
|
|
37
|
+
|
|
38
|
+
* Remove Octicons and replace with a pure CSS status circle (https://github.com/jnunemaker/flipper/pull/547)
|
|
39
|
+
* Rescue unique errors in AR and Sequel when setting value (https://github.com/jnunemaker/flipper/commit/87f5a98bce7baad7a27b75b5bce3256967769f27)
|
|
40
|
+
* Add a Content-Security-Policy to flipper-ui (https://github.com/jnunemaker/flipper/pull/552)
|
|
41
|
+
* Fix Synchronizer issue that occurs for ActiveRecord adapter (https://github.com/jnunemaker/flipper/pull/554)
|
|
42
|
+
|
|
1
43
|
## 0.22.0
|
|
2
44
|
|
|
3
|
-
|
|
45
|
+
### Additions/Changes
|
|
4
46
|
|
|
5
47
|
* Enable log subscriber by default in Rails (https://github.com/jnunemaker/flipper/pull/525)
|
|
6
48
|
* Remove memoizer from API and UI (https://github.com/jnunemaker/flipper/pull/527). If you are using the UI or API without configuring the default instance of Flipper, you'll need to enable memoization if you want it. For examples, see the examples/ui and examples/api directories.
|
|
@@ -16,7 +58,7 @@
|
|
|
16
58
|
* Added cloud recommendation to flipper-ui. Can be disabled with `Flipper::UI.configure { |config| config.cloud_recommendation = false }`. Just want to raise awareness that more is available if people want it (https://github.com/jnunemaker/flipper/pull/504)
|
|
17
59
|
* Added default `flipper_id` implementation via `Flipper::Identifier` and automatically included it in ActiveRecord and Sequel models (https://github.com/jnunemaker/flipper/pull/505)
|
|
18
60
|
* Deprecate superflous sync_method setting (https://github.com/jnunemaker/flipper/pull/511)
|
|
19
|
-
* Flipper is now pre-configured when used with Rails. By default, it will [memoize and preload all features for each request](docs/
|
|
61
|
+
* Flipper is now pre-configured when used with Rails. By default, it will [memoize and preload all features for each request](https://flippercloud.io/docs/optimization#memoization). (https://github.com/jnunemaker/flipper/pull/506)
|
|
20
62
|
|
|
21
63
|
### Upgrading
|
|
22
64
|
|
|
@@ -31,7 +73,7 @@ You should be able to upgrade to 0.21 without any breaking changes. However, if
|
|
|
31
73
|
- end
|
|
32
74
|
```
|
|
33
75
|
|
|
34
|
-
2. `Flipper::Middleware::Memoizer` will be enabled by default.
|
|
76
|
+
2. `Flipper::Middleware::Memoizer` will be enabled by default -- including preloading. **Note**: You may want to disable preloading (see below) if you have > 100 features.
|
|
35
77
|
|
|
36
78
|
```diff
|
|
37
79
|
# config/initializers/flipper.rb
|
|
@@ -40,6 +82,9 @@ You should be able to upgrade to 0.21 without any breaking changes. However, if
|
|
|
40
82
|
+ Rails.application.configure do
|
|
41
83
|
+ # Uncomment to configure which features to preload on all requests
|
|
42
84
|
+ # config.flipper.preload = [:stats, :search, :some_feature]
|
|
85
|
+
+ #
|
|
86
|
+
+ # Or, you may want to disable preloading entirely:
|
|
87
|
+
+ # config.flipper.preload = false
|
|
43
88
|
+ end
|
|
44
89
|
```
|
|
45
90
|
|
data/Gemfile
CHANGED
|
@@ -13,11 +13,11 @@ gem 'statsd-ruby', '~> 1.2.1'
|
|
|
13
13
|
gem 'rspec', '~> 3.0'
|
|
14
14
|
gem 'rack-test', '~> 0.6.3'
|
|
15
15
|
gem 'sqlite3', "~> #{ENV['SQLITE3_VERSION'] || '1.4.1'}"
|
|
16
|
-
gem 'rails', "~> #{ENV['RAILS_VERSION'] || '
|
|
16
|
+
gem 'rails', "~> #{ENV['RAILS_VERSION'] || '7.0.0'}"
|
|
17
17
|
gem 'minitest', '~> 5.8'
|
|
18
18
|
gem 'minitest-documentation'
|
|
19
19
|
gem 'webmock', '~> 3.0'
|
|
20
|
-
gem '
|
|
20
|
+
gem 'ice_age'
|
|
21
21
|
gem 'redis-namespace'
|
|
22
22
|
gem 'webrick'
|
|
23
23
|
|
data/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
[](https://www.flippercloud.io)
|
|
2
2
|
|
|
3
|
+
[Website](https://flippercloud.io) | [Documentation](https://flippercloud.io/docs) | [Examples](examples) | [Twitter](https://twitter.com/flipper_cloud)
|
|
4
|
+
|
|
3
5
|
# Flipper
|
|
4
6
|
|
|
5
7
|
> Beautiful, performant feature flags for Ruby.
|
|
@@ -19,7 +21,7 @@ Add this line to your application's Gemfile:
|
|
|
19
21
|
|
|
20
22
|
gem 'flipper'
|
|
21
23
|
|
|
22
|
-
You'll also want to pick a storage [adapter](
|
|
24
|
+
You'll also want to pick a storage [adapter](https://flippercloud.io/docs/adapters), for example:
|
|
23
25
|
|
|
24
26
|
gem 'flipper-active_record'
|
|
25
27
|
|
|
@@ -31,6 +33,10 @@ Or install it yourself with:
|
|
|
31
33
|
|
|
32
34
|
$ gem install flipper
|
|
33
35
|
|
|
36
|
+
## Subscribe & Ship
|
|
37
|
+
|
|
38
|
+
[💌 Subscribe](https://buttondown.email/flipper) - I'll send you short and sweet emails when we release new versions.
|
|
39
|
+
|
|
34
40
|
## Getting Started
|
|
35
41
|
|
|
36
42
|
Use `Flipper#enabled?` in your app to check if a feature is enabled.
|
|
@@ -46,74 +52,25 @@ end
|
|
|
46
52
|
|
|
47
53
|
All features are disabled by default, so you'll need to explicitly enable them.
|
|
48
54
|
|
|
49
|
-
#### Enable a feature for everyone
|
|
50
|
-
|
|
51
55
|
```ruby
|
|
56
|
+
# Enable a feature for everyone
|
|
52
57
|
Flipper.enable :search
|
|
53
|
-
```
|
|
54
58
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
```ruby
|
|
59
|
+
# Enable a feature for a specific actor
|
|
58
60
|
Flipper.enable_actor :search, current_user
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
#### Enable a feature for a group of actors
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
```ruby
|
|
66
|
-
# config/initializers/flipper.rb
|
|
67
|
-
Flipper.register(:admin) do |actor|
|
|
68
|
-
actor.respond_to?(:admin?) && actor.admin?
|
|
69
|
-
end
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
Then enable the feature for that group:
|
|
73
|
-
|
|
74
|
-
```ruby
|
|
62
|
+
# Enable a feature for a group of actors
|
|
75
63
|
Flipper.enable_group :search, :admin
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
#### Enable a feature for a percentage of actors
|
|
79
64
|
|
|
80
|
-
|
|
65
|
+
# Enable a feature for a percentage of actors
|
|
81
66
|
Flipper.enable_percentage_of_actors :search, 2
|
|
82
67
|
```
|
|
83
68
|
|
|
84
|
-
|
|
85
|
-
Read more about enabling and disabling features with [Gates](docs/Gates.md). Check out the [examples directory](examples/) for more, and take a peek at the [DSL](lib/flipper/dsl.rb) and [Feature](lib/flipper/feature.rb) classes for code/docs.
|
|
86
|
-
|
|
87
|
-
## Adapters
|
|
88
|
-
|
|
89
|
-
Flipper is built on adapters for maximum flexibility. Regardless of what data store you are using, Flipper can performantly store data in it.
|
|
90
|
-
|
|
91
|
-
Pick one of our [supported adapters](docs/Adapters.md#officially-supported) and follow the installation instructions:
|
|
92
|
-
|
|
93
|
-
* [Active Record](docs/active_record/README.md)
|
|
94
|
-
* [Sequel](docs/sequel/README.md)
|
|
95
|
-
* [Redis](docs/redis/README.md)
|
|
96
|
-
* [Mongo](docs/mongo/README.md)
|
|
97
|
-
* [Moneta](docs/moneta/README.md)
|
|
98
|
-
* [Rollout](docs/rollout/README.md)
|
|
99
|
-
|
|
100
|
-
Or [roll your own](docs/Adapters.md#roll-your-own). We even provide automatic (rspec and minitest) tests for you, so you know you've built your custom adapter correctly.
|
|
101
|
-
|
|
102
|
-
Read more about [Adapters](docs/Adapters.md).
|
|
103
|
-
|
|
104
|
-
## Flipper UI
|
|
105
|
-
|
|
106
|
-
If you prefer a web UI to an IRB console, you can setup the [Flipper UI](docs/ui/README.md).
|
|
107
|
-
|
|
108
|
-
It's simple and pretty.
|
|
109
|
-
|
|
110
|
-

|
|
111
|
-
|
|
112
|
-
|
|
69
|
+
Read more about [getting started with Flipper](https://flippercloud.io/docs) and [enabling features](https://flippercloud.io/docs/features).
|
|
113
70
|
|
|
114
71
|
## Flipper Cloud
|
|
115
72
|
|
|
116
|
-
|
|
73
|
+
Like Flipper and want more? Check out [Flipper Cloud](https://www.flippercloud.io), which comes with:
|
|
117
74
|
|
|
118
75
|
* **everything in one place** — no need to bounce around from different application UIs or IRB consoles.
|
|
119
76
|
* **permissions** — grant access to everyone in your organization or lockdown each project to particular people.
|
|
@@ -127,21 +84,11 @@ Or, (even better than OSS + UI) use [Flipper Cloud](https://www.flippercloud.io)
|
|
|
127
84
|
|
|
128
85
|
Cloud is super simple to integrate with Rails ([demo app](https://github.com/fewerandfaster/flipper-rails-demo)), Sinatra or any other framework.
|
|
129
86
|
|
|
130
|
-
## Advanced
|
|
131
|
-
|
|
132
|
-
A few miscellaneous docs with more info for the hungry.
|
|
133
|
-
|
|
134
|
-
* [Instrumentation](docs/Instrumentation.md) - ActiveSupport::Notifications and Statsd
|
|
135
|
-
* [Optimization](docs/Optimization.md) - Memoization middleware and Cache adapters
|
|
136
|
-
* [API](docs/api/README.md) - HTTP API interface
|
|
137
|
-
* [Caveats](docs/Caveats.md) - Flipper beware! (see what I did there)
|
|
138
|
-
* [Docker-Compose](docs/DockerCompose.md) - Using docker-compose in contributing
|
|
139
|
-
|
|
140
87
|
## Contributing
|
|
141
88
|
|
|
142
89
|
1. Fork it
|
|
143
90
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
144
|
-
3. Run the tests (`bundle exec rake`)
|
|
91
|
+
3. Run the tests (`bundle exec rake`). Check out [Docker-Compose](docs/DockerCompose.md) if you need help getting all the adapters running.
|
|
145
92
|
4. Commit your changes (`git commit -am 'Added some feature'`)
|
|
146
93
|
5. Push to the branch (`git push origin my-new-feature`)
|
|
147
94
|
6. Create new Pull Request
|
|
@@ -158,6 +105,7 @@ A few miscellaneous docs with more info for the hungry.
|
|
|
158
105
|
|---|---|---|
|
|
159
106
|
|  | [@jnunemaker](https://github.com/jnunemaker) | most things |
|
|
160
107
|
|  | [@bkeepers](https://github.com/bkeepers) | most things |
|
|
108
|
+
|  | [@dpep](https://github.com/dpep) | tbd |
|
|
161
109
|
|  | [@alexwheeler](https://github.com/alexwheeler) | api |
|
|
162
110
|
|  | [@thetimbanks](https://github.com/thetimbanks) | ui |
|
|
163
111
|
|  | [@lazebny](https://github.com/lazebny) | docker |
|
data/docker-compose.yml
CHANGED
|
@@ -1,34 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
1
|
+
version: "2.4"
|
|
2
|
+
services:
|
|
3
|
+
# postgres:
|
|
4
|
+
# container_name: flipper_postgres
|
|
5
|
+
# image: postgres:9.4
|
|
6
|
+
redis:
|
|
7
|
+
container_name: flipper_redis
|
|
8
|
+
image: redis:6.2.5
|
|
9
|
+
mongo:
|
|
10
|
+
container_name: flipper_mongo
|
|
11
|
+
image: mongo:4.4.8
|
|
12
|
+
memcached:
|
|
13
|
+
container_name: flipper_memcached
|
|
14
|
+
image: memcached:1.4.33
|
|
15
|
+
app:
|
|
16
|
+
container_name: flipper_app
|
|
17
|
+
build:
|
|
18
|
+
context: .
|
|
19
|
+
dockerfile: Dockerfile
|
|
20
|
+
volumes:
|
|
21
|
+
- .:/srv/app
|
|
22
|
+
volumes_from:
|
|
23
|
+
- bundle_cache
|
|
24
|
+
links:
|
|
25
|
+
# - postgres
|
|
26
|
+
- redis
|
|
27
|
+
- mongo
|
|
28
|
+
- memcached
|
|
29
|
+
environment:
|
|
30
|
+
- REDIS_URL=redis://redis:6379
|
|
31
|
+
- MONGODB_HOST=mongo
|
|
32
|
+
- MEMCACHED_URL=memcached:11211
|
|
33
|
+
bundle_cache:
|
|
34
|
+
container_name: flipper_bundle_cache
|
|
35
|
+
image: busybox
|
|
36
|
+
volumes:
|
|
37
|
+
- /bundle_cache
|
data/docs/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
See [flippercloud.io](https://flippercloud.io/docs) for extensive docs.
|
data/docs/images/banner.jpg
CHANGED
|
Binary file
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Quick example of how to keep track of when a feature was last checked.
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
require 'active_support/notifications'
|
|
5
|
+
require 'flipper'
|
|
6
|
+
|
|
7
|
+
class FlipperSubscriber
|
|
8
|
+
def self.stats
|
|
9
|
+
@stats ||= {}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call(name, start, finish, id, payload)
|
|
13
|
+
if payload[:operation] == :enabled?
|
|
14
|
+
feature_name = payload.fetch(:feature_name)
|
|
15
|
+
self.class.stats[feature_name] = Time.now
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
ActiveSupport::Notifications.subscribe(/feature_operation.flipper/, new)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
Flipper.configure do |config|
|
|
23
|
+
config.default {
|
|
24
|
+
Flipper.new(config.adapter, instrumenter: ActiveSupport::Notifications)
|
|
25
|
+
}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
Flipper.enabled?(:search)
|
|
29
|
+
Flipper.enabled?(:booyeah)
|
|
30
|
+
Flipper.enabled?(:hooray)
|
|
31
|
+
sleep 1
|
|
32
|
+
Flipper.enabled?(:booyeah)
|
|
33
|
+
Flipper.enabled?(:hooray)
|
|
34
|
+
sleep 1
|
|
35
|
+
Flipper.enabled?(:hooray)
|
|
36
|
+
|
|
37
|
+
pp FlipperSubscriber.stats
|
|
@@ -34,33 +34,27 @@ module Flipper
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def add(feature)
|
|
37
|
-
|
|
38
|
-
@local.add(feature)
|
|
39
|
-
result
|
|
37
|
+
@remote.add(feature).tap { @local.add(feature) }
|
|
40
38
|
end
|
|
41
39
|
|
|
42
40
|
def remove(feature)
|
|
43
|
-
|
|
44
|
-
@local.remove(feature)
|
|
45
|
-
result
|
|
41
|
+
@remote.remove(feature).tap { @local.remove(feature) }
|
|
46
42
|
end
|
|
47
43
|
|
|
48
44
|
def clear(feature)
|
|
49
|
-
|
|
50
|
-
@local.clear(feature)
|
|
51
|
-
result
|
|
45
|
+
@remote.clear(feature).tap { @local.clear(feature) }
|
|
52
46
|
end
|
|
53
47
|
|
|
54
48
|
def enable(feature, gate, thing)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
@remote.enable(feature, gate, thing).tap do
|
|
50
|
+
@local.enable(feature, gate, thing)
|
|
51
|
+
end
|
|
58
52
|
end
|
|
59
53
|
|
|
60
54
|
def disable(feature, gate, thing)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
@remote.disable(feature, gate, thing).tap do
|
|
56
|
+
@local.disable(feature, gate, thing)
|
|
57
|
+
end
|
|
64
58
|
end
|
|
65
59
|
end
|
|
66
60
|
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module Flipper
|
|
2
|
+
module Adapters
|
|
3
|
+
class Failover
|
|
4
|
+
include ::Flipper::Adapter
|
|
5
|
+
|
|
6
|
+
# Public: The name of the adapter.
|
|
7
|
+
attr_reader :name
|
|
8
|
+
|
|
9
|
+
# Public: Build a new failover instance.
|
|
10
|
+
#
|
|
11
|
+
# primary - The primary flipper adapter.
|
|
12
|
+
# secondary - The secondary flipper adapter which services reads when
|
|
13
|
+
# the primary adapter is unavailable.
|
|
14
|
+
# options - Hash of options:
|
|
15
|
+
# :dual_write - Boolean, whether to update secondary when
|
|
16
|
+
# primary is updated
|
|
17
|
+
# :errors - Array of exception types for which to failover
|
|
18
|
+
|
|
19
|
+
def initialize(primary, secondary, options = {})
|
|
20
|
+
@name = :failover
|
|
21
|
+
@primary = primary
|
|
22
|
+
@secondary = secondary
|
|
23
|
+
|
|
24
|
+
@dual_write = options.fetch(:dual_write, false)
|
|
25
|
+
@errors = options.fetch(:errors, [ StandardError ])
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def features
|
|
29
|
+
@primary.features
|
|
30
|
+
rescue *@errors
|
|
31
|
+
@secondary.features
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def get(feature)
|
|
35
|
+
@primary.get(feature)
|
|
36
|
+
rescue *@errors
|
|
37
|
+
@secondary.get(feature)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def get_multi(features)
|
|
41
|
+
@primary.get_multi(features)
|
|
42
|
+
rescue *@errors
|
|
43
|
+
@secondary.get_multi(features)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def get_all
|
|
47
|
+
@primary.get_all
|
|
48
|
+
rescue *@errors
|
|
49
|
+
@secondary.get_all
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def add(feature)
|
|
53
|
+
@primary.add(feature).tap do
|
|
54
|
+
@secondary.add(feature) if @dual_write
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def remove(feature)
|
|
59
|
+
@primary.remove(feature).tap do
|
|
60
|
+
@secondary.remove(feature) if @dual_write
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def clear(feature)
|
|
65
|
+
@primary.clear(feature).tap do
|
|
66
|
+
@secondary.clear(feature) if @dual_write
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def enable(feature, gate, thing)
|
|
71
|
+
@primary.enable(feature, gate, thing).tap do
|
|
72
|
+
@secondary.enable(feature, gate, thing) if @dual_write
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def disable(feature, gate, thing)
|
|
77
|
+
@primary.disable(feature, gate, thing).tap do
|
|
78
|
+
@secondary.disable(feature, gate, thing) if @dual_write
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -70,9 +70,19 @@ module Flipper
|
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
def build_request(http_method, uri, headers, options)
|
|
73
|
+
request_headers = {
|
|
74
|
+
"Client-Language" => "ruby",
|
|
75
|
+
"Client-Language-Version" => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})",
|
|
76
|
+
"Client-Platform" => RUBY_PLATFORM,
|
|
77
|
+
"Client-Engine" => defined?(RUBY_ENGINE) ? RUBY_ENGINE : "",
|
|
78
|
+
"Client-Pid" => Process.pid.to_s,
|
|
79
|
+
"Client-Thread" => Thread.current.object_id.to_s,
|
|
80
|
+
"Client-Hostname" => Socket.gethostname,
|
|
81
|
+
}.merge(headers)
|
|
82
|
+
|
|
73
83
|
body = options[:body]
|
|
74
84
|
request = http_method.new(uri.request_uri)
|
|
75
|
-
request.initialize_http_header(
|
|
85
|
+
request.initialize_http_header(request_headers)
|
|
76
86
|
request.body = body if body
|
|
77
87
|
|
|
78
88
|
if @basic_auth_username && @basic_auth_password
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
1
3
|
module Flipper
|
|
2
4
|
module Adapters
|
|
3
5
|
class Http
|
|
@@ -6,7 +8,23 @@ module Flipper
|
|
|
6
8
|
|
|
7
9
|
def initialize(response)
|
|
8
10
|
@response = response
|
|
9
|
-
|
|
11
|
+
message = "Failed with status: #{response.code}"
|
|
12
|
+
|
|
13
|
+
begin
|
|
14
|
+
data = JSON.parse(response.body)
|
|
15
|
+
|
|
16
|
+
if error_message = data["message"]
|
|
17
|
+
message << "\n\n#{data["message"]}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
if more_info = data["more_info"]
|
|
21
|
+
message << "\n#{data["more_info"]}"
|
|
22
|
+
end
|
|
23
|
+
rescue => exception
|
|
24
|
+
# welp we tried
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
super(message)
|
|
10
28
|
end
|
|
11
29
|
end
|
|
12
30
|
end
|