flipper 0.16.0 → 0.18.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Changelog.md +65 -3
- data/Dockerfile +1 -1
- data/Gemfile +10 -17
- data/README.md +1 -1
- data/Rakefile +10 -2
- data/docs/Adapters.md +1 -1
- data/docs/Caveats.md +1 -1
- data/docs/DockerCompose.md +0 -1
- data/docs/Gates.md +66 -66
- data/docs/api/README.md +36 -1
- data/flipper.gemspec +0 -1
- data/lib/flipper.rb +1 -1
- data/lib/flipper/adapters/http/client.rb +12 -0
- data/lib/flipper/adapters/instrumented.rb +20 -18
- data/lib/flipper/adapters/memory.rb +5 -2
- data/lib/flipper/adapters/pstore.rb +4 -1
- data/lib/flipper/feature.rb +0 -1
- data/lib/flipper/middleware/memoizer.rb +1 -3
- data/lib/flipper/spec/shared_adapter_specs.rb +25 -1
- data/lib/flipper/test/shared_adapter_test.rb +27 -2
- data/lib/flipper/types/group.rb +1 -1
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/adapter_spec.rb +2 -2
- data/spec/flipper/adapters/http_spec.rb +1 -0
- data/spec/flipper/adapters/instrumented_spec.rb +2 -0
- data/spec/flipper/feature_check_context_spec.rb +2 -2
- data/spec/flipper/feature_spec.rb +3 -3
- data/spec/flipper/types/group_spec.rb +22 -0
- data/spec/{integration_spec.rb → flipper_integration_spec.rb} +0 -0
- data/spec/helper.rb +1 -1
- data/spec/support/descriptions.yml +1 -0
- data/test/test_helper.rb +1 -1
- data/{test → test_rails}/helper.rb +1 -1
- metadata +9 -13
- data/.rubocop.yml +0 -54
- data/.rubocop_todo.yml +0 -199
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 60a4f0efac1116f4a9c4f0aeb899cd9104dcccf6578691ba639e047a23b77fe0
|
4
|
+
data.tar.gz: 270782a3c6d8021e8efa4b926fd0dfbe49613f1b47793d4783e15667cddb58e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10f4d755b8f3f9137cdf3868ddc3277177e4dea8d27e1125449c3bfc25afe3350dc4a4a6c97f71f26db8cc180357221686fcc737a1e60ce29edb6adbb60a5cc5
|
7
|
+
data.tar.gz: cd5b0bf940e4ff2dbede6c82c7ea2d30ab44fb9ec4917032df3b36b6c7c390c587494a6c334c36fa0498cf83162562afcecb44a12e2373ec8ebf0a3e941d525d
|
data/Changelog.md
CHANGED
@@ -1,3 +1,65 @@
|
|
1
|
+
## 0.18.0
|
2
|
+
|
3
|
+
## Additions/Changes
|
4
|
+
|
5
|
+
* Add support for feature descriptions to flipper-ui (https://github.com/jnunemaker/flipper/pull/461).
|
6
|
+
* Remove rubocop (https://github.com/jnunemaker/flipper/pull/469).
|
7
|
+
* flipper-ui redesign (https://github.com/jnunemaker/flipper/pull/470).
|
8
|
+
* Removed support for ruby 2.4.
|
9
|
+
* Added support for ruby 2.7.
|
10
|
+
* Removed support for Rails 4.x.x.
|
11
|
+
* Removed support for customizing actors, groups, % of actors and % of time text in flipper-ui in favor of automatic and more descriptive text.
|
12
|
+
|
13
|
+
## 0.17.2
|
14
|
+
|
15
|
+
### Additions/Changes
|
16
|
+
|
17
|
+
* Avoid errors on import when there are no features and shared specs/tests for get all with no features (https://github.com/jnunemaker/flipper/pull/441 and https://github.com/jnunemaker/flipper/pull/442)
|
18
|
+
* ::ActiveRecord::RecordNotUnique > ActiveRecord::RecordNotUnique (https://github.com/jnunemaker/flipper/pull/444)
|
19
|
+
* Clear gate values on enable (https://github.com/jnunemaker/flipper/pull/454)
|
20
|
+
* Remove use of multi from redis adapter (https://github.com/jnunemaker/flipper/pull/451)
|
21
|
+
|
22
|
+
## 0.17.1
|
23
|
+
|
24
|
+
* Fix require in flipper-active_record (https://github.com/jnunemaker/flipper/pull/437)
|
25
|
+
|
26
|
+
## 0.17.0
|
27
|
+
|
28
|
+
### Additions/Changes
|
29
|
+
|
30
|
+
* Allow shorthand block notation on group types (https://github.com/jnunemaker/flipper/pull/406)
|
31
|
+
* Relax active record/support constraints to support Rails 6 (https://github.com/jnunemaker/flipper/pull/409)
|
32
|
+
* Allow disabling fun (https://github.com/jnunemaker/flipper/pull/413)
|
33
|
+
* Include thing_value in payload of Instrumented#enable and #disable (https://github.com/jnunemaker/flipper/pull/417)
|
34
|
+
* Replace Erubis with Erubi (https://github.com/jnunemaker/flipper/pull/407)
|
35
|
+
* Allow customizing Rack::Protection middleware list (https://github.com/jnunemaker/flipper/pull/385)
|
36
|
+
* Allow setting write_timeout for ruby 2.6+ (https://github.com/jnunemaker/flipper/pull/433)
|
37
|
+
* Drop support for Ruby 2.1, 2.2, and 2.3 (https://github.com/jnunemaker/flipper/commit/cf58982e70de5e6963b018ceced4f36a275f5b5d)
|
38
|
+
* Add support for Ruby 2.6 (https://github.com/jnunemaker/flipper/commit/57888311449ec81184d3d47ba9ae5cb1ad4a2f45)
|
39
|
+
* Remove support for Rails 3.2 (https://github.com/jnunemaker/flipper/commit/177c48c4edf51d4e411e7c673e30e06d1c66fb40)
|
40
|
+
* Add write_timeout for flipper http adapter for ruby 2.6+ (https://github.com/jnunemaker/flipper/pull/433)
|
41
|
+
* Relax moneta version to allow for < 1.2 (https://github.com/jnunemaker/flipper/pull/434).
|
42
|
+
* Improve active record idempotency (https://github.com/jnunemaker/flipper/pull/436).
|
43
|
+
* Allow customizing add actor placeholder text (https://github.com/jnunemaker/flipper/commit/5faa1e9cf66b68f8227d2f8408fb448a14676c45)
|
44
|
+
|
45
|
+
## 0.16.2
|
46
|
+
|
47
|
+
### Additions/Changes
|
48
|
+
|
49
|
+
* Bump rollout redis dependency to < 5 (https://github.com/jnunemaker/flipper/pull/403)
|
50
|
+
* Bump redis dependency to < 5 (https://github.com/jnunemaker/flipper/pull/401)
|
51
|
+
* Bump sequel dependency to < 6 (https://github.com/jnunemaker/flipper/pull/399 and https://github.com/jnunemaker/flipper/commit/edc767e69b4ce8daead9801f38e0e8bf6b238765)
|
52
|
+
|
53
|
+
## 0.16.1
|
54
|
+
|
55
|
+
### Additions/Changes
|
56
|
+
|
57
|
+
* Add actors API endpoint (https://github.com/jnunemaker/flipper/pull/372).
|
58
|
+
* Fix rack body proxy require for those using flipper without rack (https://github.com/jnunemaker/flipper/pull/376).
|
59
|
+
* Unescapes feature_name in FeatureNameFromRoute (https://github.com/jnunemaker/flipper/pull/377).
|
60
|
+
* Replace delete_all with destroy_all in ActiveRecord adapter (https://github.com/jnunemaker/flipper/pull/395)
|
61
|
+
* Target correct bootstrap breakpoints in flipper UI (https://github.com/jnunemaker/flipper/pull/396)
|
62
|
+
|
1
63
|
## 0.16.0
|
2
64
|
|
3
65
|
### Bug Fixes
|
@@ -40,7 +102,7 @@
|
|
40
102
|
|
41
103
|
### Additions/Changes
|
42
104
|
|
43
|
-
* Added rollout adapter documentation (https://github.com/jnunemaker/flipper/pull/328).
|
105
|
+
* Added rollout adapter documentation (https://github.com/jnunemaker/flipper/pull/328).
|
44
106
|
|
45
107
|
### Bug Fixes
|
46
108
|
|
@@ -174,8 +236,8 @@
|
|
174
236
|
|
175
237
|
* Added Flipper.groups and Flipper.group_names
|
176
238
|
* Changed percentage_of_random to percentage_of_time
|
177
|
-
* Added enable/disable convenience methods for all gates (
|
178
|
-
* Added value convenience methods (
|
239
|
+
* Added enable/disable convenience methods for all gates (enable_group, enable_actor, enable_percentage_of_actors, enable_percentage_of_time)
|
240
|
+
* Added value convenience methods (boolean_value, groups_value, actors_value, etc.)
|
179
241
|
* Added Feature#gate_values for getting typecast adapter gate values
|
180
242
|
* Added Feature#enabled_gates and #disabled_gates for getting the gates that are enabled/disabled for the feature
|
181
243
|
* Remove Feature#description
|
data/Dockerfile
CHANGED
data/Gemfile
CHANGED
@@ -7,27 +7,20 @@ Dir['flipper-*.gemspec'].each do |gemspec|
|
|
7
7
|
end
|
8
8
|
|
9
9
|
gem 'pry'
|
10
|
-
gem 'rake', '~>
|
10
|
+
gem 'rake', '~> 12.3.3'
|
11
11
|
gem 'shotgun', '~> 0.9'
|
12
12
|
gem 'statsd-ruby', '~> 1.2.1'
|
13
13
|
gem 'rspec', '~> 3.0'
|
14
14
|
gem 'rack-test', '~> 0.6.3'
|
15
|
-
gem 'sqlite3',
|
16
|
-
gem 'rails', "~> #{ENV['RAILS_VERSION'] || '
|
17
|
-
gem 'minitest', '~> 5.8
|
18
|
-
gem '
|
19
|
-
gem '
|
20
|
-
gem 'webmock', '~> 2.0'
|
21
|
-
|
22
|
-
# for active support tests in test/ and only needed for ruby 2.2.x
|
23
|
-
gem 'test-unit', '~> 3.0'
|
15
|
+
gem 'sqlite3', "~> #{ENV['SQLITE3_VERSION'] || '1.4.1'}"
|
16
|
+
gem 'rails', "~> #{ENV['RAILS_VERSION'] || '6.0.0'}"
|
17
|
+
gem 'minitest', '~> 5.8'
|
18
|
+
gem 'minitest-documentation'
|
19
|
+
gem 'webmock', '~> 3.0'
|
24
20
|
|
25
21
|
group(:guard) do
|
26
|
-
gem 'guard', '~> 2.
|
27
|
-
gem 'guard-
|
28
|
-
gem 'guard-
|
29
|
-
gem '
|
30
|
-
gem 'guard-coffeescript', '~> 2.0.1'
|
31
|
-
gem 'guard-sass', '~> 1.6.0'
|
32
|
-
gem 'rb-fsevent', '~> 0.9.4'
|
22
|
+
gem 'guard', '~> 2.15'
|
23
|
+
gem 'guard-rspec', '~> 4.5'
|
24
|
+
gem 'guard-bundler', '~> 2.2'
|
25
|
+
gem 'rb-fsevent', '~> 0.9'
|
33
26
|
end
|
data/README.md
CHANGED
@@ -85,7 +85,7 @@ Of course there are more [examples for you to peruse](examples/). You could also
|
|
85
85
|
|
86
86
|
1. Fork it
|
87
87
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
88
|
-
3.
|
88
|
+
3. Run the tests (`bundle exec rake`)
|
89
89
|
4. Commit your changes (`git commit -am 'Added some feature'`)
|
90
90
|
5. Push to the branch (`git push origin my-new-feature`)
|
91
91
|
6. Create new Pull Request
|
data/Rakefile
CHANGED
@@ -25,7 +25,7 @@ end
|
|
25
25
|
|
26
26
|
require 'rspec/core/rake_task'
|
27
27
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
28
|
-
t.rspec_opts = %w(--color)
|
28
|
+
t.rspec_opts = %w(--color --format documentation)
|
29
29
|
end
|
30
30
|
|
31
31
|
namespace :spec do
|
@@ -39,6 +39,14 @@ end
|
|
39
39
|
Rake::TestTask.new do |t|
|
40
40
|
t.libs = %w(lib test)
|
41
41
|
t.pattern = 'test/**/*_test.rb'
|
42
|
+
t.options = '--documentation'
|
43
|
+
t.warning = false
|
42
44
|
end
|
43
45
|
|
44
|
-
|
46
|
+
Rake::TestTask.new(:test_rails) do |t|
|
47
|
+
t.libs = %w(lib test_rails)
|
48
|
+
t.pattern = 'test_rails/**/*_test.rb'
|
49
|
+
t.warning = false
|
50
|
+
end
|
51
|
+
|
52
|
+
task default: [:spec, :test, :test_rails]
|
data/docs/Adapters.md
CHANGED
@@ -4,7 +4,7 @@ I plan on supporting the adapters in the flipper repo. Other adapters are welcom
|
|
4
4
|
|
5
5
|
## Officially Supported
|
6
6
|
|
7
|
-
* [ActiveRecord adapter](https://github.com/jnunemaker/flipper/blob/master/docs/active_record) - Rails 3, 4, and
|
7
|
+
* [ActiveRecord adapter](https://github.com/jnunemaker/flipper/blob/master/docs/active_record) - Rails 3, 4, 5, and 6.
|
8
8
|
* [ActiveSupportCacheStore adapter](https://github.com/jnunemaker/flipper/blob/master/docs/active_support_cache_store) - ActiveSupport::Cache::Store
|
9
9
|
* [Cassanity adapter](https://github.com/jnunemaker/flipper-cassanity)
|
10
10
|
* [Http adapter](https://github.com/jnunemaker/flipper/blob/master/docs/http)
|
data/docs/Caveats.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
# Caveats
|
2
2
|
|
3
|
-
1. The [individual actor gate](https://github.com/jnunemaker/flipper/blob/master/docs/Gates.md#
|
3
|
+
1. The [individual actor gate](https://github.com/jnunemaker/flipper/blob/master/docs/Gates.md#2-individual-actor) is typically not designed for hundreds or thousands of actors to be enabled. This is an explicit choice to make it easier to batch load data from the adapters instead of performing individual checks for actors over and over. If you need to enable something for more than 20 individual people, I would recommend using a [group](https://github.com/jnunemaker/flipper/blob/master/docs/Gates.md#5-group).
|
4
4
|
2. The disable method exists only to clear something that is enabled. If the thing you are disabling is not enabled, the disable is pointless. This means that if you enable one group an actor is in and disable another group, the feature will be enabled for the actor. ([related issue](https://github.com/jnunemaker/flipper/issues/71))
|
data/docs/DockerCompose.md
CHANGED
@@ -11,7 +11,6 @@ new contributor could start working on code with a minumum efforts.
|
|
11
11
|
1. Install gems `docker-compose run --rm app bundle install`
|
12
12
|
1. Run specs `docker-compose run --rm app bundle exec rspec`
|
13
13
|
1. Run tests `docker-compose run --rm app bundle exec rake test`
|
14
|
-
1. Clear and check files with Rubocop `docker-compose run --rm app bundle exec rubocop -D`
|
15
14
|
1. Optional: log in to container an using a `bash` shell for running specs
|
16
15
|
```sh
|
17
16
|
docker-compose run --rm app bash
|
data/docs/Gates.md
CHANGED
@@ -13,69 +13,7 @@ flipper[:stats].disable # turn off
|
|
13
13
|
flipper[:stats].enabled? # check
|
14
14
|
```
|
15
15
|
|
16
|
-
## 2.
|
17
|
-
|
18
|
-
Turn on feature based on the return value of block. Super flexible way to turn on a feature for multiple things (users, people, accounts, etc.) as long as the thing returns true when passed to the block.
|
19
|
-
|
20
|
-
```ruby
|
21
|
-
# this registers a group
|
22
|
-
Flipper.register(:admins) do |actor|
|
23
|
-
actor.respond_to?(:admin?) && actor.admin?
|
24
|
-
end
|
25
|
-
|
26
|
-
flipper = Flipper.new(adapter)
|
27
|
-
|
28
|
-
flipper[:stats].enable flipper.group(:admins) # This registers a stats feature and turns it on for admins (which is anything that returns true from the registered block).
|
29
|
-
flipper[:stats].disable flipper.group(:admins) # turn off the stats feature for admins
|
30
|
-
|
31
|
-
person = Person.find(params[:id])
|
32
|
-
flipper[:stats].enabled? person # check if enabled, returns true if person.admin? is true
|
33
|
-
|
34
|
-
# you can also use shortcut methods. This also registers a stats feature and turns it on for admins.
|
35
|
-
flipper.enable_group :stats, :admins
|
36
|
-
person = Person.find(params[:id])
|
37
|
-
flipper[:stats].enabled? person # same as above. check if enabled, returns true if person.admin? is true
|
38
|
-
|
39
|
-
flipper.disable_group :stats, :admins
|
40
|
-
flipper[:stats].enable_group :admins
|
41
|
-
flipper[:stats].disable_group :admins
|
42
|
-
```
|
43
|
-
|
44
|
-
Here's a quick explanation of the above code block:
|
45
|
-
|
46
|
-
```
|
47
|
-
Flipper.register(:admins) do |actor|
|
48
|
-
actor.respond_to?(:admin?) && actor.admin?
|
49
|
-
end
|
50
|
-
```
|
51
|
-
- The above first registers a group called `admins` which essentially saves a [Proc](http://www.eriktrautman.com/posts/ruby-explained-blocks-procs-and-lambdas-aka-closures) to be called later.
|
52
|
-
|
53
|
-
```
|
54
|
-
flipper[:stats].enable flipper.group(:admins)
|
55
|
-
```
|
56
|
-
|
57
|
-
- The above enables the stats feature to any object that returns true from the `:admins` proc.
|
58
|
-
|
59
|
-
```
|
60
|
-
person = Person.find(params[:id])
|
61
|
-
flipper[:stats].enabled? person # check if person is enabled, returns true if person.admin? is true
|
62
|
-
```
|
63
|
-
|
64
|
-
When the `person` object is passed to the `enabled?` method, it is then passed into the proc. If the proc returns true, the entire statement returns true and so `flipper[:stats].enabled? person` returns true. Whatever logic follows this conditional check is then executed.
|
65
|
-
|
66
|
-
There is no requirement that the thing yielded to the block be a user model or whatever. It can be anything you want, therefore it is a good idea to check that the thing passed into the group block actually responds to what you are trying to do in the `register` proc.
|
67
|
-
|
68
|
-
In your application code, you can do something like this now:
|
69
|
-
|
70
|
-
```
|
71
|
-
if flipper[:stats].enabled?(some_admin)
|
72
|
-
# do thing...
|
73
|
-
else
|
74
|
-
# do not do thing
|
75
|
-
end
|
76
|
-
```
|
77
|
-
|
78
|
-
## 3. Individual Actor
|
16
|
+
## 2. Individual Actor
|
79
17
|
|
80
18
|
Turn feature on for individual thing. Think enable feature for someone to test or for a buddy. The only requirement for an individual actor is that it must respond to `flipper_id`.
|
81
19
|
|
@@ -117,7 +55,7 @@ class Group
|
|
117
55
|
end
|
118
56
|
```
|
119
57
|
|
120
|
-
##
|
58
|
+
## 3. Percentage of Actors
|
121
59
|
|
122
60
|
Turn this on for a percentage of actors (think user, member, account, group, whatever). Consistently on or off for this user as long as percentage increases. Think slow rollout of a new feature to a percentage of things.
|
123
61
|
|
@@ -141,7 +79,7 @@ flipper[:search].enable_percentage_of_actors 10
|
|
141
79
|
flipper[:search].disable_percentage_of_actors # sets to 0
|
142
80
|
```
|
143
81
|
|
144
|
-
##
|
82
|
+
## 4. Percentage of Time
|
145
83
|
|
146
84
|
Turn this on for a percentage of time. Think load testing new features behind the scenes and such.
|
147
85
|
|
@@ -158,10 +96,72 @@ flipper[:logging].enable percentage
|
|
158
96
|
flipper[:logging].enabled? # this will return true 5% of the time.
|
159
97
|
|
160
98
|
# you can also use shortcut methods
|
161
|
-
flipper.enable_percentage_of_time :search, 5 # registers a feature called "
|
99
|
+
flipper.enable_percentage_of_time :search, 5 # registers a feature called "search" and enables it 5% of the time
|
162
100
|
flipper.disable_percentage_of_time :search # sets to 0
|
163
101
|
flipper[:search].enable_percentage_of_time 5
|
164
102
|
flipper[:search].disable_percentage_of_time # sets to 0
|
165
103
|
```
|
166
104
|
|
167
105
|
Timeness is not a good idea for enabling new features in the UI. Most of the time you want a feature on or off for a user, but there are definitely times when I have found percentage of time to be very useful.
|
106
|
+
|
107
|
+
## 5. Group
|
108
|
+
|
109
|
+
Turn on feature based on the return value of block. Super flexible way to turn on a feature for multiple things (users, people, accounts, etc.) as long as the thing returns true when passed to the block.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
# this registers a group
|
113
|
+
Flipper.register(:admins) do |actor|
|
114
|
+
actor.respond_to?(:admin?) && actor.admin?
|
115
|
+
end
|
116
|
+
|
117
|
+
flipper = Flipper.new(adapter)
|
118
|
+
|
119
|
+
flipper[:stats].enable flipper.group(:admins) # This registers a stats feature and turns it on for admins (which is anything that returns true from the registered block).
|
120
|
+
flipper[:stats].disable flipper.group(:admins) # turn off the stats feature for admins
|
121
|
+
|
122
|
+
person = Person.find(params[:id])
|
123
|
+
flipper[:stats].enabled? person # check if enabled, returns true if person.admin? is true
|
124
|
+
|
125
|
+
# you can also use shortcut methods. This also registers a stats feature and turns it on for admins.
|
126
|
+
flipper.enable_group :stats, :admins
|
127
|
+
person = Person.find(params[:id])
|
128
|
+
flipper[:stats].enabled? person # same as above. check if enabled, returns true if person.admin? is true
|
129
|
+
|
130
|
+
flipper.disable_group :stats, :admins
|
131
|
+
flipper[:stats].enable_group :admins
|
132
|
+
flipper[:stats].disable_group :admins
|
133
|
+
```
|
134
|
+
|
135
|
+
Here's a quick explanation of the above code block:
|
136
|
+
|
137
|
+
```
|
138
|
+
Flipper.register(:admins) do |actor|
|
139
|
+
actor.respond_to?(:admin?) && actor.admin?
|
140
|
+
end
|
141
|
+
```
|
142
|
+
- The above first registers a group called `admins` which essentially saves a [Proc](http://www.eriktrautman.com/posts/ruby-explained-blocks-procs-and-lambdas-aka-closures) to be called later. The `actor` is an instance of the `Flipper::Types::Actor` that wraps the thing being checked against and `actor.thing` is the original object being checked.
|
143
|
+
|
144
|
+
```
|
145
|
+
flipper[:stats].enable flipper.group(:admins)
|
146
|
+
```
|
147
|
+
|
148
|
+
- The above enables the stats feature to any object that returns true from the `:admins` proc.
|
149
|
+
|
150
|
+
```
|
151
|
+
person = Person.find(params[:id])
|
152
|
+
flipper[:stats].enabled? person # check if person is enabled, returns true if person.admin? is true
|
153
|
+
```
|
154
|
+
|
155
|
+
When the `person` object is passed to the `enabled?` method, it is then passed into the proc. If the proc returns true, the entire statement returns true and so `flipper[:stats].enabled? person` returns true. Whatever logic follows this conditional check is then executed.
|
156
|
+
|
157
|
+
There is no requirement that the thing yielded to the block be a user model or whatever. It can be anything you want, therefore it is a good idea to check that the thing passed into the group block actually responds to what you are trying to do in the `register` proc.
|
158
|
+
|
159
|
+
In your application code, you can do something like this now:
|
160
|
+
|
161
|
+
```
|
162
|
+
if flipper[:stats].enabled?(some_admin)
|
163
|
+
# do thing...
|
164
|
+
else
|
165
|
+
# do not do thing
|
166
|
+
end
|
167
|
+
```
|
data/docs/api/README.md
CHANGED
@@ -527,7 +527,7 @@ Successful enabling of the actor will return a 200 HTTP status and the feature o
|
|
527
527
|
{
|
528
528
|
"key": "actors",
|
529
529
|
"name": "actor",
|
530
|
-
"value": ["User
|
530
|
+
"value": ["User;1"]
|
531
531
|
},
|
532
532
|
{
|
533
533
|
"key": "percentage_of_actors",
|
@@ -815,6 +815,41 @@ Successful disabling of a percentage of time will set the percentage to 0 and re
|
|
815
815
|
}
|
816
816
|
```
|
817
817
|
|
818
|
+
### Check if features are enabled for an actor
|
819
|
+
|
820
|
+
**URL**
|
821
|
+
|
822
|
+
`GET /actors/{flipper_id}`
|
823
|
+
|
824
|
+
**Parameters**
|
825
|
+
|
826
|
+
* `keys` - comma-separated list of features to check
|
827
|
+
|
828
|
+
**Request**
|
829
|
+
|
830
|
+
```
|
831
|
+
curl -X GET http://example.com/flipper/api/actors/User;1?keys=my_feature_1,my_feature_2
|
832
|
+
```
|
833
|
+
|
834
|
+
**Response**
|
835
|
+
|
836
|
+
Returns whether the actor with the provided flipper_id is enabled for the specififed feature keys.
|
837
|
+
If no keys are specified all features are returned.
|
838
|
+
|
839
|
+
```json
|
840
|
+
{
|
841
|
+
"flipper_id": "User;1",
|
842
|
+
"features": {
|
843
|
+
"my_feature_1": {
|
844
|
+
"enabled": true,
|
845
|
+
},
|
846
|
+
"my_feature_2": {
|
847
|
+
"enabled": false,
|
848
|
+
}
|
849
|
+
}
|
850
|
+
}
|
851
|
+
```
|
852
|
+
|
818
853
|
## Errors
|
819
854
|
In the event of an error the Flipper API will return an error object. The error object will contain a Flipper-specific error code, an error message, and a link to documentation providing more information about the error.
|
820
855
|
|
data/flipper.gemspec
CHANGED
@@ -25,7 +25,6 @@ Gem::Specification.new do |gem|
|
|
25
25
|
gem.authors = ['John Nunemaker']
|
26
26
|
gem.email = ['nunemaker@gmail.com']
|
27
27
|
gem.summary = 'Feature flipper for ANYTHING'
|
28
|
-
gem.description = 'Feature flipper is the act of enabling/disabling features in your application, ideally without re-deploying or changing anything in your code base. Flipper makes this extremely easy to do with any backend you would like to use.'
|
29
28
|
gem.homepage = 'https://github.com/jnunemaker/flipper'
|
30
29
|
gem.license = 'MIT'
|
31
30
|
|
data/lib/flipper.rb
CHANGED
@@ -21,6 +21,7 @@ module Flipper
|
|
21
21
|
@basic_auth_password = options[:basic_auth_password]
|
22
22
|
@read_timeout = options[:read_timeout]
|
23
23
|
@open_timeout = options[:open_timeout]
|
24
|
+
@write_timeout = options[:write_timeout]
|
24
25
|
@debug_output = options[:debug_output]
|
25
26
|
end
|
26
27
|
|
@@ -57,6 +58,7 @@ module Flipper
|
|
57
58
|
http = Net::HTTP.new(uri.host, uri.port)
|
58
59
|
http.read_timeout = @read_timeout if @read_timeout
|
59
60
|
http.open_timeout = @open_timeout if @open_timeout
|
61
|
+
apply_write_timeout(http)
|
60
62
|
http.set_debug_output(@debug_output) if @debug_output
|
61
63
|
|
62
64
|
if uri.scheme == HTTPS_SCHEME
|
@@ -79,6 +81,16 @@ module Flipper
|
|
79
81
|
|
80
82
|
request
|
81
83
|
end
|
84
|
+
|
85
|
+
def apply_write_timeout(http)
|
86
|
+
if @write_timeout
|
87
|
+
if RUBY_VERSION >= '2.6.0'
|
88
|
+
http.write_timeout = @write_timeout
|
89
|
+
else
|
90
|
+
Kernel.warn("Warning: option :write_timeout requires Ruby version 2.6.0 or later")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
82
94
|
end
|
83
95
|
end
|
84
96
|
end
|
@@ -32,115 +32,117 @@ module Flipper
|
|
32
32
|
|
33
33
|
# Public
|
34
34
|
def features
|
35
|
-
|
35
|
+
default_payload = {
|
36
36
|
operation: :features,
|
37
37
|
adapter_name: @adapter.name,
|
38
38
|
}
|
39
39
|
|
40
|
-
@instrumenter.instrument(InstrumentationName,
|
40
|
+
@instrumenter.instrument(InstrumentationName, default_payload) do |payload|
|
41
41
|
payload[:result] = @adapter.features
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
# Public
|
46
46
|
def add(feature)
|
47
|
-
|
47
|
+
default_payload = {
|
48
48
|
operation: :add,
|
49
49
|
adapter_name: @adapter.name,
|
50
50
|
feature_name: feature.name,
|
51
51
|
}
|
52
52
|
|
53
|
-
@instrumenter.instrument(InstrumentationName,
|
53
|
+
@instrumenter.instrument(InstrumentationName, default_payload) do |payload|
|
54
54
|
payload[:result] = @adapter.add(feature)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
# Public
|
59
59
|
def remove(feature)
|
60
|
-
|
60
|
+
default_payload = {
|
61
61
|
operation: :remove,
|
62
62
|
adapter_name: @adapter.name,
|
63
63
|
feature_name: feature.name,
|
64
64
|
}
|
65
65
|
|
66
|
-
@instrumenter.instrument(InstrumentationName,
|
66
|
+
@instrumenter.instrument(InstrumentationName, default_payload) do |payload|
|
67
67
|
payload[:result] = @adapter.remove(feature)
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
71
|
# Public
|
72
72
|
def clear(feature)
|
73
|
-
|
73
|
+
default_payload = {
|
74
74
|
operation: :clear,
|
75
75
|
adapter_name: @adapter.name,
|
76
76
|
feature_name: feature.name,
|
77
77
|
}
|
78
78
|
|
79
|
-
@instrumenter.instrument(InstrumentationName,
|
79
|
+
@instrumenter.instrument(InstrumentationName, default_payload) do |payload|
|
80
80
|
payload[:result] = @adapter.clear(feature)
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
84
|
# Public
|
85
85
|
def get(feature)
|
86
|
-
|
86
|
+
default_payload = {
|
87
87
|
operation: :get,
|
88
88
|
adapter_name: @adapter.name,
|
89
89
|
feature_name: feature.name,
|
90
90
|
}
|
91
91
|
|
92
|
-
@instrumenter.instrument(InstrumentationName,
|
92
|
+
@instrumenter.instrument(InstrumentationName, default_payload) do |payload|
|
93
93
|
payload[:result] = @adapter.get(feature)
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
97
|
def get_multi(features)
|
98
|
-
|
98
|
+
default_payload = {
|
99
99
|
operation: :get_multi,
|
100
100
|
adapter_name: @adapter.name,
|
101
101
|
feature_names: features.map(&:name),
|
102
102
|
}
|
103
103
|
|
104
|
-
@instrumenter.instrument(InstrumentationName,
|
104
|
+
@instrumenter.instrument(InstrumentationName, default_payload) do |payload|
|
105
105
|
payload[:result] = @adapter.get_multi(features)
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
109
|
def get_all
|
110
|
-
|
110
|
+
default_payload = {
|
111
111
|
operation: :get_all,
|
112
112
|
adapter_name: @adapter.name,
|
113
113
|
}
|
114
114
|
|
115
|
-
@instrumenter.instrument(InstrumentationName,
|
115
|
+
@instrumenter.instrument(InstrumentationName, default_payload) do |payload|
|
116
116
|
payload[:result] = @adapter.get_all
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
120
120
|
# Public
|
121
121
|
def enable(feature, gate, thing)
|
122
|
-
|
122
|
+
default_payload = {
|
123
123
|
operation: :enable,
|
124
124
|
adapter_name: @adapter.name,
|
125
125
|
feature_name: feature.name,
|
126
126
|
gate_name: gate.name,
|
127
|
+
thing_value: thing.value,
|
127
128
|
}
|
128
129
|
|
129
|
-
@instrumenter.instrument(InstrumentationName,
|
130
|
+
@instrumenter.instrument(InstrumentationName, default_payload) do |payload|
|
130
131
|
payload[:result] = @adapter.enable(feature, gate, thing)
|
131
132
|
end
|
132
133
|
end
|
133
134
|
|
134
135
|
# Public
|
135
136
|
def disable(feature, gate, thing)
|
136
|
-
|
137
|
+
default_payload = {
|
137
138
|
operation: :disable,
|
138
139
|
adapter_name: @adapter.name,
|
139
140
|
feature_name: feature.name,
|
140
141
|
gate_name: gate.name,
|
142
|
+
thing_value: thing.value,
|
141
143
|
}
|
142
144
|
|
143
|
-
@instrumenter.instrument(InstrumentationName,
|
145
|
+
@instrumenter.instrument(InstrumentationName, default_payload) do |payload|
|
144
146
|
payload[:result] = @adapter.disable(feature, gate, thing)
|
145
147
|
end
|
146
148
|
end
|
@@ -2,7 +2,7 @@ require 'set'
|
|
2
2
|
|
3
3
|
module Flipper
|
4
4
|
module Adapters
|
5
|
-
# Public: Adapter for storing everything in memory
|
5
|
+
# Public: Adapter for storing everything in memory.
|
6
6
|
# Useful for tests/specs.
|
7
7
|
class Memory
|
8
8
|
include ::Flipper::Adapter
|
@@ -65,7 +65,10 @@ module Flipper
|
|
65
65
|
# Public
|
66
66
|
def enable(feature, gate, thing)
|
67
67
|
case gate.data_type
|
68
|
-
when :boolean
|
68
|
+
when :boolean
|
69
|
+
clear(feature)
|
70
|
+
write key(feature, gate), thing.value.to_s
|
71
|
+
when :integer
|
69
72
|
write key(feature, gate), thing.value.to_s
|
70
73
|
when :set
|
71
74
|
set_add key(feature, gate), thing.value.to_s
|
@@ -84,7 +84,10 @@ module Flipper
|
|
84
84
|
def enable(feature, gate, thing)
|
85
85
|
@store.transaction do
|
86
86
|
case gate.data_type
|
87
|
-
when :boolean
|
87
|
+
when :boolean
|
88
|
+
clear_gates(feature)
|
89
|
+
write key(feature, gate), thing.value.to_s
|
90
|
+
when :integer
|
88
91
|
write key(feature, gate), thing.value.to_s
|
89
92
|
when :set
|
90
93
|
set_add key(feature, gate), thing.value.to_s
|
data/lib/flipper/feature.rb
CHANGED
@@ -5,7 +5,6 @@ require 'flipper/feature_check_context'
|
|
5
5
|
require 'flipper/gate_values'
|
6
6
|
|
7
7
|
module Flipper
|
8
|
-
# rubocop:disable Metrics/ClassLength
|
9
8
|
class Feature
|
10
9
|
# Private: The name of feature instrumentation events.
|
11
10
|
InstrumentationName = "feature_operation.#{InstrumentationNamespace}".freeze
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'rack/body_proxy'
|
2
|
-
|
3
1
|
module Flipper
|
4
2
|
module Middleware
|
5
3
|
class Memoizer
|
@@ -25,7 +23,7 @@ module Flipper
|
|
25
23
|
#
|
26
24
|
def initialize(app, opts = {})
|
27
25
|
if opts.is_a?(Flipper::DSL) || opts.is_a?(Proc)
|
28
|
-
raise 'Flipper::Middleware::Memoizer no longer initializes with a flipper instance or block. Read more at: https://git.io/vSo31.'
|
26
|
+
raise 'Flipper::Middleware::Memoizer no longer initializes with a flipper instance or block. Read more at: https://git.io/vSo31.'
|
29
27
|
end
|
30
28
|
|
31
29
|
@app = app
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# Requires the following methods:
|
2
2
|
# * subject - The instance of the adapter
|
3
|
-
# rubocop:disable Metrics/BlockLength
|
4
3
|
RSpec.shared_examples_for 'a flipper adapter' do
|
5
4
|
let(:flipper) { Flipper.new(subject) }
|
6
5
|
let(:feature) { flipper[:stats] }
|
@@ -280,4 +279,29 @@ RSpec.shared_examples_for 'a flipper adapter' do
|
|
280
279
|
expect(subject.enable(feature, group_gate, flipper.group(:admins))).to eq(true)
|
281
280
|
expect(subject.get(feature).fetch(:groups)).to eq(Set['admins'])
|
282
281
|
end
|
282
|
+
|
283
|
+
it 'can double enable percentage without error' do
|
284
|
+
expect(subject.enable(feature, actors_gate, flipper.actors(25))).to eq(true)
|
285
|
+
expect(subject.enable(feature, actors_gate, flipper.actors(25))).to eq(true)
|
286
|
+
end
|
287
|
+
|
288
|
+
it 'can double enable without error' do
|
289
|
+
expect(subject.enable(feature, boolean_gate, flipper.boolean)).to eq(true)
|
290
|
+
expect(subject.enable(feature, boolean_gate, flipper.boolean)).to eq(true)
|
291
|
+
end
|
292
|
+
|
293
|
+
it 'can get_all features when there are none' do
|
294
|
+
expect(subject.features).to eq(Set.new)
|
295
|
+
expect(subject.get_all).to eq({})
|
296
|
+
end
|
297
|
+
|
298
|
+
it 'clears other gate values on enable' do
|
299
|
+
actor = Flipper::Actor.new('Flipper::Actor;22')
|
300
|
+
subject.enable(feature, actors_gate, flipper.actors(25))
|
301
|
+
subject.enable(feature, time_gate, flipper.time(25))
|
302
|
+
subject.enable(feature, group_gate, flipper.group(:admins))
|
303
|
+
subject.enable(feature, actor_gate, flipper.actor(actor))
|
304
|
+
subject.enable(feature, boolean_gate, flipper.boolean(true))
|
305
|
+
expect(subject.get(feature)).to eq(subject.default_config.merge(boolean: "true"))
|
306
|
+
end
|
283
307
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# rubocop:disable Metrics/ModuleLength
|
2
1
|
module Flipper
|
3
2
|
module Test
|
4
3
|
module SharedAdapterTests
|
@@ -43,7 +42,7 @@ module Flipper
|
|
43
42
|
assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
|
44
43
|
assert_equal 'true', @adapter.get(@feature)[:boolean]
|
45
44
|
assert_equal true, @adapter.disable(@feature, @boolean_gate, @flipper.boolean(false))
|
46
|
-
|
45
|
+
assert_nil @adapter.get(@feature)[:boolean]
|
47
46
|
end
|
48
47
|
|
49
48
|
def test_fully_disables_all_enabled_things_when_boolean_gate_disabled
|
@@ -275,6 +274,32 @@ module Flipper
|
|
275
274
|
assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
|
276
275
|
assert_equal Set['admins'], @adapter.get(@feature).fetch(:groups)
|
277
276
|
end
|
277
|
+
|
278
|
+
def test_can_double_enable_percentage_without_error
|
279
|
+
assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(25))
|
280
|
+
assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(25))
|
281
|
+
end
|
282
|
+
|
283
|
+
def test_can_double_enable_without_error
|
284
|
+
assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
|
285
|
+
assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
|
286
|
+
end
|
287
|
+
|
288
|
+
def test_can_get_all_features_when_there_are_none
|
289
|
+
expected = {}
|
290
|
+
assert_equal Set.new, @adapter.features
|
291
|
+
assert_equal expected, @adapter.get_all
|
292
|
+
end
|
293
|
+
|
294
|
+
def test_clears_other_gate_values_on_enable
|
295
|
+
actor = Flipper::Actor.new('Flipper::Actor;22')
|
296
|
+
assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(25))
|
297
|
+
assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(25))
|
298
|
+
assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
|
299
|
+
assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor))
|
300
|
+
assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean(true))
|
301
|
+
assert_equal @adapter.default_config.merge(boolean: "true"), @adapter.get(@feature)
|
302
|
+
end
|
278
303
|
end
|
279
304
|
end
|
280
305
|
end
|
data/lib/flipper/types/group.rb
CHANGED
data/lib/flipper/version.rb
CHANGED
@@ -16,7 +16,7 @@ RSpec.describe Flipper::Adapter do
|
|
16
16
|
describe '.default_config' do
|
17
17
|
it 'returns default config' do
|
18
18
|
adapter_class = Class.new do
|
19
|
-
include Flipper::Adapter
|
19
|
+
include Flipper::Adapter
|
20
20
|
end
|
21
21
|
expect(adapter_class.default_config).to eq(default_config)
|
22
22
|
end
|
@@ -25,7 +25,7 @@ RSpec.describe Flipper::Adapter do
|
|
25
25
|
describe '#default_config' do
|
26
26
|
it 'returns default config' do
|
27
27
|
adapter_class = Class.new do
|
28
|
-
include Flipper::Adapter
|
28
|
+
include Flipper::Adapter
|
29
29
|
end
|
30
30
|
expect(adapter_class.new.default_config).to eq(default_config)
|
31
31
|
end
|
@@ -73,6 +73,7 @@ RSpec.describe Flipper::Adapters::Instrumented do
|
|
73
73
|
expect(event.payload[:adapter_name]).to eq(:memory)
|
74
74
|
expect(event.payload[:feature_name]).to eq(:stats)
|
75
75
|
expect(event.payload[:gate_name]).to eq(:percentage_of_actors)
|
76
|
+
expect(event.payload[:thing_value]).to eq(22)
|
76
77
|
expect(event.payload[:result]).to be(result)
|
77
78
|
end
|
78
79
|
end
|
@@ -88,6 +89,7 @@ RSpec.describe Flipper::Adapters::Instrumented do
|
|
88
89
|
expect(event.payload[:adapter_name]).to eq(:memory)
|
89
90
|
expect(event.payload[:feature_name]).to eq(:stats)
|
90
91
|
expect(event.payload[:gate_name]).to eq(:percentage_of_actors)
|
92
|
+
expect(event.payload[:thing_value]).to eq(22)
|
91
93
|
expect(event.payload[:result]).to be(result)
|
92
94
|
end
|
93
95
|
end
|
@@ -41,8 +41,8 @@ RSpec.describe Flipper::FeatureCheckContext do
|
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'knows actors_value' do
|
44
|
-
args = options.merge(values: Flipper::GateValues.new(actors: Set['User
|
45
|
-
expect(described_class.new(args).actors_value).to eq(Set['User
|
44
|
+
args = options.merge(values: Flipper::GateValues.new(actors: Set['User;1']))
|
45
|
+
expect(described_class.new(args).actors_value).to eq(Set['User;1'])
|
46
46
|
end
|
47
47
|
|
48
48
|
it 'knows groups_value' do
|
@@ -530,12 +530,12 @@ RSpec.describe Flipper::Feature do
|
|
530
530
|
|
531
531
|
context 'when one or more actors are enabled' do
|
532
532
|
before do
|
533
|
-
subject.enable Flipper::Types::Actor.new(Flipper::Actor.new('User
|
534
|
-
subject.enable Flipper::Types::Actor.new(Flipper::Actor.new('User
|
533
|
+
subject.enable Flipper::Types::Actor.new(Flipper::Actor.new('User;5'))
|
534
|
+
subject.enable Flipper::Types::Actor.new(Flipper::Actor.new('User;22'))
|
535
535
|
end
|
536
536
|
|
537
537
|
it 'returns set of actor ids' do
|
538
|
-
expect(subject.actors_value).to eq(Set.new(['User
|
538
|
+
expect(subject.actors_value).to eq(Set.new(['User;5', 'User;22']))
|
539
539
|
end
|
540
540
|
end
|
541
541
|
end
|
@@ -65,6 +65,28 @@ RSpec.describe Flipper::Types::Group do
|
|
65
65
|
expect(group.match?(double('Actor'), fake_context)).to be_falsey
|
66
66
|
end
|
67
67
|
|
68
|
+
it 'returns true for truthy shortand block results' do
|
69
|
+
actor = Class.new do
|
70
|
+
def admin?
|
71
|
+
true
|
72
|
+
end
|
73
|
+
end.new
|
74
|
+
|
75
|
+
group = described_class.new(:admin, &:admin?)
|
76
|
+
expect(group.match?(actor, fake_context)).to be_truthy
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'returns false for falsy shortand block results' do
|
80
|
+
actor = Class.new do
|
81
|
+
def admin?
|
82
|
+
false
|
83
|
+
end
|
84
|
+
end.new
|
85
|
+
|
86
|
+
group = described_class.new(:admin, &:admin?)
|
87
|
+
expect(group.match?(actor, fake_context)).to be_falsey
|
88
|
+
end
|
89
|
+
|
68
90
|
it 'can yield without context as block argument' do
|
69
91
|
context = Flipper::FeatureCheckContext.new(
|
70
92
|
feature_name: :my_feature,
|
File without changes
|
data/spec/helper.rb
CHANGED
@@ -17,7 +17,7 @@ require 'flipper'
|
|
17
17
|
require 'flipper-ui'
|
18
18
|
require 'flipper-api'
|
19
19
|
|
20
|
-
Dir[FlipperRoot.join('spec/support/**/*.rb')].each { |f| require f }
|
20
|
+
Dir[FlipperRoot.join('spec/support/**/*.rb')].sort.each { |f| require f }
|
21
21
|
|
22
22
|
RSpec.configure do |config|
|
23
23
|
config.before(:example) do
|
@@ -0,0 +1 @@
|
|
1
|
+
some_awesome_feature: 'Awesome feature description'
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,18 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flipper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.18.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Nunemaker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
14
|
-
ideally without re-deploying or changing anything in your code base. Flipper makes
|
15
|
-
this extremely easy to do with any backend you would like to use.
|
13
|
+
description:
|
16
14
|
email:
|
17
15
|
- nunemaker@gmail.com
|
18
16
|
executables: []
|
@@ -20,8 +18,6 @@ extensions: []
|
|
20
18
|
extra_rdoc_files: []
|
21
19
|
files:
|
22
20
|
- ".codeclimate.yml"
|
23
|
-
- ".rubocop.yml"
|
24
|
-
- ".rubocop_todo.yml"
|
25
21
|
- CODE_OF_CONDUCT.md
|
26
22
|
- Changelog.md
|
27
23
|
- Dockerfile
|
@@ -143,15 +139,16 @@ files:
|
|
143
139
|
- spec/flipper/types/percentage_of_actors_spec.rb
|
144
140
|
- spec/flipper/types/percentage_of_time_spec.rb
|
145
141
|
- spec/flipper/types/percentage_spec.rb
|
142
|
+
- spec/flipper_integration_spec.rb
|
146
143
|
- spec/flipper_spec.rb
|
147
144
|
- spec/helper.rb
|
148
|
-
- spec/
|
145
|
+
- spec/support/descriptions.yml
|
149
146
|
- spec/support/fake_udp_socket.rb
|
150
147
|
- spec/support/spec_helpers.rb
|
151
148
|
- test/adapters/memory_test.rb
|
152
149
|
- test/adapters/pstore_test.rb
|
153
|
-
- test/helper.rb
|
154
150
|
- test/test_helper.rb
|
151
|
+
- test_rails/helper.rb
|
155
152
|
homepage: https://github.com/jnunemaker/flipper
|
156
153
|
licenses:
|
157
154
|
- MIT
|
@@ -172,8 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
169
|
- !ruby/object:Gem::Version
|
173
170
|
version: '0'
|
174
171
|
requirements: []
|
175
|
-
|
176
|
-
rubygems_version: 2.4.5.4
|
172
|
+
rubygems_version: 3.0.3
|
177
173
|
signing_key:
|
178
174
|
specification_version: 4
|
179
175
|
summary: Feature flipper for ANYTHING
|
@@ -217,12 +213,12 @@ test_files:
|
|
217
213
|
- spec/flipper/types/percentage_of_actors_spec.rb
|
218
214
|
- spec/flipper/types/percentage_of_time_spec.rb
|
219
215
|
- spec/flipper/types/percentage_spec.rb
|
216
|
+
- spec/flipper_integration_spec.rb
|
220
217
|
- spec/flipper_spec.rb
|
221
218
|
- spec/helper.rb
|
222
|
-
- spec/
|
219
|
+
- spec/support/descriptions.yml
|
223
220
|
- spec/support/fake_udp_socket.rb
|
224
221
|
- spec/support/spec_helpers.rb
|
225
222
|
- test/adapters/memory_test.rb
|
226
223
|
- test/adapters/pstore_test.rb
|
227
|
-
- test/helper.rb
|
228
224
|
- test/test_helper.rb
|
data/.rubocop.yml
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
# This is the configuration used to check the rubocop source code.
|
2
|
-
|
3
|
-
require: rubocop-rspec
|
4
|
-
inherit_from:
|
5
|
-
- .rubocop_todo.yml
|
6
|
-
|
7
|
-
AllCops:
|
8
|
-
Exclude:
|
9
|
-
- 'docker-compose/**/*'
|
10
|
-
- 'examples/**/*'
|
11
|
-
- 'tmp/**/*'
|
12
|
-
- 'bin/**/*'
|
13
|
-
TargetRubyVersion: 2.0
|
14
|
-
# DefaultFormatter: fuubar
|
15
|
-
Style/Alias:
|
16
|
-
Enabled: false
|
17
|
-
|
18
|
-
Style/Documentation:
|
19
|
-
Enabled: false
|
20
|
-
|
21
|
-
Style/Encoding:
|
22
|
-
Enabled: false
|
23
|
-
|
24
|
-
Style/NumericLiterals:
|
25
|
-
Enabled: false
|
26
|
-
|
27
|
-
Style/StringLiterals:
|
28
|
-
Enabled: false
|
29
|
-
|
30
|
-
Style/GuardClause:
|
31
|
-
Enabled: false
|
32
|
-
|
33
|
-
Style/IfUnlessModifier:
|
34
|
-
Enabled: false
|
35
|
-
|
36
|
-
Metrics/LineLength:
|
37
|
-
Max: 100
|
38
|
-
Exclude:
|
39
|
-
- '*.gemspec'
|
40
|
-
|
41
|
-
Style/RegexpLiteral:
|
42
|
-
EnforcedStyle: mixed
|
43
|
-
|
44
|
-
Style/TrailingCommaInLiteral:
|
45
|
-
EnforcedStyleForMultiline: consistent_comma
|
46
|
-
|
47
|
-
RSpec/InstanceVariable:
|
48
|
-
Enabled: false
|
49
|
-
|
50
|
-
Style/AccessorMethodName:
|
51
|
-
Enabled: false
|
52
|
-
|
53
|
-
Lint/HandleExceptions:
|
54
|
-
Enabled: false
|
data/.rubocop_todo.yml
DELETED
@@ -1,199 +0,0 @@
|
|
1
|
-
# This configuration was generated by
|
2
|
-
# `rubocop --auto-gen-config`
|
3
|
-
# on 2016-11-20 15:49:33 +0000 using RuboCop version 0.45.0.
|
4
|
-
# The point is for the user to remove these configuration records
|
5
|
-
# one by one as the offenses are removed from the code base.
|
6
|
-
# Note that changes in the inspected code, or installation of new
|
7
|
-
# versions of RuboCop, may require this file to be generated again.
|
8
|
-
|
9
|
-
require: rubocop-rspec
|
10
|
-
|
11
|
-
# Offense count: 2
|
12
|
-
Lint/AmbiguousRegexpLiteral:
|
13
|
-
Exclude:
|
14
|
-
- 'lib/flipper/instrumentation/metriks.rb'
|
15
|
-
- 'lib/flipper/instrumentation/statsd.rb'
|
16
|
-
|
17
|
-
# Offense count: 6
|
18
|
-
# Configuration parameters: AllowSafeAssignment.
|
19
|
-
Lint/AssignmentInCondition:
|
20
|
-
Exclude:
|
21
|
-
- 'lib/flipper/adapters/active_record.rb'
|
22
|
-
- 'lib/flipper/adapters/sequel.rb'
|
23
|
-
- 'lib/flipper/feature.rb'
|
24
|
-
- 'lib/flipper/gate_values.rb'
|
25
|
-
|
26
|
-
# Offense count: 1
|
27
|
-
Lint/Eval:
|
28
|
-
Exclude:
|
29
|
-
- 'flipper.gemspec'
|
30
|
-
|
31
|
-
# Offense count: 3
|
32
|
-
Lint/HandleExceptions:
|
33
|
-
Exclude:
|
34
|
-
- 'spec/flipper/adapters/mongo_spec.rb'
|
35
|
-
- 'test/adapters/mongo_test.rb'
|
36
|
-
- 'test/helper.rb'
|
37
|
-
|
38
|
-
# Offense count: 24
|
39
|
-
Lint/ShadowingOuterLocalVariable:
|
40
|
-
Exclude:
|
41
|
-
- 'lib/flipper/adapters/active_record.rb'
|
42
|
-
- 'lib/flipper/adapters/instrumented.rb'
|
43
|
-
- 'lib/flipper/adapters/sequel.rb'
|
44
|
-
- 'spec/flipper/api/v1/actions/actors_gate_spec.rb'
|
45
|
-
- 'spec/flipper/api/v1/actions/percentage_of_actors_gate_spec.rb'
|
46
|
-
- 'spec/flipper/api/v1/actions/percentage_of_time_gate_spec.rb'
|
47
|
-
- 'spec/flipper/dsl_spec.rb'
|
48
|
-
- 'spec/flipper/feature_spec.rb'
|
49
|
-
- 'spec/flipper/types/group_spec.rb'
|
50
|
-
|
51
|
-
# Offense count: 26
|
52
|
-
Lint/UselessAssignment:
|
53
|
-
Exclude:
|
54
|
-
- 'lib/flipper/instrumentation/log_subscriber.rb'
|
55
|
-
- 'lib/flipper/instrumentation/subscriber.rb'
|
56
|
-
- 'lib/flipper/ui/actions/groups_gate.rb'
|
57
|
-
- 'spec/flipper/api/action_spec.rb'
|
58
|
-
- 'spec/flipper/dsl_spec.rb'
|
59
|
-
- 'spec/flipper/feature_spec.rb'
|
60
|
-
- 'spec/flipper/gates/group_spec.rb'
|
61
|
-
- 'spec/flipper/instrumentation/metriks_subscriber_spec.rb'
|
62
|
-
- 'spec/flipper/instrumentation/statsd_subscriber_spec.rb'
|
63
|
-
- 'spec/flipper_spec.rb'
|
64
|
-
- 'spec/flipper/middleware/memoizer_spec.rb'
|
65
|
-
- 'test/helper.rb'
|
66
|
-
|
67
|
-
# Offense count: 27
|
68
|
-
Metrics/AbcSize:
|
69
|
-
Max: 30
|
70
|
-
|
71
|
-
# Offense count: 1
|
72
|
-
# Configuration parameters: CountComments.
|
73
|
-
Metrics/BlockLength:
|
74
|
-
Max: 195
|
75
|
-
|
76
|
-
# Offense count: 4
|
77
|
-
# Configuration parameters: CountComments.
|
78
|
-
Metrics/ClassLength:
|
79
|
-
Max: 178
|
80
|
-
|
81
|
-
# Offense count: 39
|
82
|
-
# Configuration parameters: CountComments.
|
83
|
-
Metrics/MethodLength:
|
84
|
-
Max: 23
|
85
|
-
|
86
|
-
# Offense count: 65
|
87
|
-
# Configuration parameters: Max.
|
88
|
-
RSpec/ExampleLength:
|
89
|
-
Enabled: false
|
90
|
-
|
91
|
-
# Offense count: 2
|
92
|
-
# Configuration parameters: CustomTransform.
|
93
|
-
RSpec/FilePath:
|
94
|
-
Exclude:
|
95
|
-
- 'spec/flipper/adapters/pstore_spec.rb'
|
96
|
-
- 'spec/integration_spec.rb'
|
97
|
-
|
98
|
-
# Offense count: 91
|
99
|
-
RSpec/InstanceVariable:
|
100
|
-
Exclude:
|
101
|
-
- 'spec/flipper/adapters/operation_logger_spec.rb'
|
102
|
-
- 'spec/flipper/dsl_spec.rb'
|
103
|
-
- 'spec/flipper/feature_spec.rb'
|
104
|
-
- 'spec/flipper/instrumentation/log_subscriber_spec.rb'
|
105
|
-
- 'spec/flipper/ui/actions/add_feature_spec.rb'
|
106
|
-
- 'spec/flipper/ui/actions/features_spec.rb'
|
107
|
-
- 'spec/flipper/ui/decorators/feature_spec.rb'
|
108
|
-
- 'spec/flipper/ui/decorators/gate_spec.rb'
|
109
|
-
- 'spec/flipper/ui_spec.rb'
|
110
|
-
- 'spec/flipper_spec.rb'
|
111
|
-
- 'spec/integration_spec.rb'
|
112
|
-
|
113
|
-
# Offense count: 15
|
114
|
-
# Configuration parameters: IgnoreSymbolicNames.
|
115
|
-
RSpec/VerifiedDoubles:
|
116
|
-
Exclude:
|
117
|
-
- 'spec/flipper/api/v1/actions/features_spec.rb'
|
118
|
-
- 'spec/flipper/dsl_spec.rb'
|
119
|
-
- 'spec/flipper/feature_spec.rb'
|
120
|
-
- 'spec/flipper/types/group_spec.rb'
|
121
|
-
- 'spec/flipper_spec.rb'
|
122
|
-
- 'spec/integration_spec.rb'
|
123
|
-
|
124
|
-
# Offense count: 2
|
125
|
-
Style/AccessorMethodName:
|
126
|
-
Exclude:
|
127
|
-
- 'lib/flipper/adapters/memory.rb'
|
128
|
-
- 'lib/flipper/adapters/pstore.rb'
|
129
|
-
|
130
|
-
# Offense count: 7
|
131
|
-
Style/ConstantName:
|
132
|
-
Exclude:
|
133
|
-
- 'lib/flipper.rb'
|
134
|
-
- 'lib/flipper/adapters/dalli.rb'
|
135
|
-
- 'lib/flipper/adapters/memoizable.rb'
|
136
|
-
- 'lib/flipper/adapters/memory.rb'
|
137
|
-
- 'lib/flipper/adapters/mongo.rb'
|
138
|
-
- 'lib/flipper/adapters/pstore.rb'
|
139
|
-
- 'lib/flipper/adapters/redis.rb'
|
140
|
-
|
141
|
-
# Offense count: 3
|
142
|
-
Style/DoubleNegation:
|
143
|
-
Exclude:
|
144
|
-
- 'lib/flipper/adapters/memoizable.rb'
|
145
|
-
- 'lib/flipper/gates/boolean.rb'
|
146
|
-
- 'lib/flipper/typecast.rb'
|
147
|
-
|
148
|
-
# Offense count: 7
|
149
|
-
# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts.
|
150
|
-
Style/FileName:
|
151
|
-
Exclude:
|
152
|
-
- 'lib/flipper-active_record.rb'
|
153
|
-
- 'lib/flipper-api.rb'
|
154
|
-
- 'lib/flipper-active_support_cache_store.rb'
|
155
|
-
- 'lib/flipper-cloud.rb'
|
156
|
-
- 'lib/flipper-dalli.rb'
|
157
|
-
- 'lib/flipper-mongo.rb'
|
158
|
-
- 'lib/flipper-redis.rb'
|
159
|
-
- 'lib/flipper-sequel.rb'
|
160
|
-
- 'lib/flipper-ui.rb'
|
161
|
-
|
162
|
-
# Offense count: 2
|
163
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
164
|
-
# SupportedStyles: format, sprintf, percent
|
165
|
-
Style/FormatString:
|
166
|
-
Exclude:
|
167
|
-
- 'lib/flipper/instrumentation/log_subscriber.rb'
|
168
|
-
|
169
|
-
# Offense count: 10
|
170
|
-
# Configuration parameters: MinBodyLength.
|
171
|
-
Style/GuardClause:
|
172
|
-
Exclude:
|
173
|
-
- 'lib/flipper/api/v1/actions/percentage_of_actors_gate.rb'
|
174
|
-
- 'lib/flipper/api/v1/actions/percentage_of_time_gate.rb'
|
175
|
-
- 'lib/flipper/gate_values.rb'
|
176
|
-
- 'lib/flipper/instrumentation/statsd_subscriber.rb'
|
177
|
-
- 'lib/flipper/instrumentation/subscriber.rb'
|
178
|
-
- 'lib/flipper/registry.rb'
|
179
|
-
- 'lib/flipper/typecast.rb'
|
180
|
-
|
181
|
-
# Offense count: 1
|
182
|
-
Style/IfInsideElse:
|
183
|
-
Exclude:
|
184
|
-
- 'lib/flipper/gates/actor.rb'
|
185
|
-
|
186
|
-
# Offense count: 1
|
187
|
-
Style/MethodMissing:
|
188
|
-
Exclude:
|
189
|
-
- 'lib/flipper/types/actor.rb'
|
190
|
-
|
191
|
-
Style/AccessorMethodName:
|
192
|
-
Exclude:
|
193
|
-
- 'lib/flipper/adapter.rb'
|
194
|
-
- 'lib/flipper/adapters/http.rb'
|
195
|
-
- 'lib/flipper/adapters/instrumented.rb'
|
196
|
-
- 'lib/flipper/adapters/memoizable.rb'
|
197
|
-
- 'lib/flipper/adapters/operation_logger.rb'
|
198
|
-
- 'lib/flipper/adapters/memory.rb'
|
199
|
-
- 'lib/flipper/adapters/pstore.rb'
|