flipper 0.16.0 → 1.4.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 +5 -5
- data/.codeclimate.yml +1 -0
- data/.github/FUNDING.yml +1 -0
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ci.yml +110 -0
- data/.github/workflows/examples.yml +105 -0
- data/.github/workflows/release.yml +54 -0
- data/.rspec +1 -0
- data/CLAUDE.md +87 -0
- data/Changelog.md +2 -215
- data/Dockerfile +1 -1
- data/Gemfile +28 -20
- data/README.md +72 -62
- data/Rakefile +13 -3
- data/benchmark/enabled_ips.rb +10 -0
- data/benchmark/enabled_multiple_actors_ips.rb +20 -0
- data/benchmark/enabled_profile.rb +20 -0
- data/benchmark/instrumentation_ips.rb +21 -0
- data/benchmark/typecast_ips.rb +27 -0
- data/docker-compose.yml +37 -34
- data/docs/DockerCompose.md +0 -1
- data/docs/README.md +1 -0
- data/docs/images/banner.jpg +0 -0
- data/docs/images/flipper_cloud.png +0 -0
- data/examples/api/basic.ru +18 -0
- data/examples/api/custom_memoized.ru +36 -0
- data/examples/api/memoized.ru +42 -0
- data/examples/basic.rb +1 -12
- data/examples/cloud/app.ru +12 -0
- data/examples/cloud/backoff_policy.rb +13 -0
- data/examples/cloud/basic.rb +22 -0
- data/examples/cloud/cloud_setup.rb +20 -0
- data/examples/cloud/forked.rb +36 -0
- data/examples/cloud/import.rb +17 -0
- data/examples/cloud/poll_interval/README.md +111 -0
- data/examples/cloud/poll_interval/client.rb +108 -0
- data/examples/cloud/poll_interval/server.rb +98 -0
- data/examples/cloud/threaded.rb +33 -0
- data/examples/configuring_default.rb +2 -5
- data/examples/dsl.rb +10 -35
- data/examples/enabled_for_actor.rb +10 -15
- data/examples/expressions.rb +237 -0
- data/examples/group.rb +3 -6
- data/examples/group_dynamic_lookup.rb +5 -19
- data/examples/group_with_members.rb +4 -14
- data/examples/importing.rb +1 -1
- data/examples/individual_actor.rb +2 -5
- data/examples/instrumentation.rb +2 -2
- data/examples/instrumentation_last_accessed_at.rb +38 -0
- data/examples/memoizing.rb +35 -0
- data/examples/mirroring.rb +59 -0
- data/examples/percentage_of_actors.rb +6 -16
- data/examples/percentage_of_actors_enabled_check.rb +7 -10
- data/examples/percentage_of_actors_group.rb +5 -18
- data/examples/percentage_of_time.rb +3 -6
- data/examples/strict.rb +18 -0
- data/exe/flipper +5 -0
- data/flipper-cloud.gemspec +19 -0
- data/flipper.gemspec +10 -7
- data/lib/flipper/actor.rb +10 -3
- data/lib/flipper/adapter.rb +50 -8
- data/lib/flipper/adapter_builder.rb +44 -0
- data/lib/flipper/adapters/actor_limit.rb +54 -0
- data/lib/flipper/adapters/cache_base.rb +161 -0
- data/lib/flipper/adapters/dual_write.rb +63 -0
- data/lib/flipper/adapters/failover.rb +85 -0
- data/lib/flipper/adapters/failsafe.rb +72 -0
- data/lib/flipper/adapters/http/client.rb +64 -7
- data/lib/flipper/adapters/http/error.rb +19 -1
- data/lib/flipper/adapters/http.rb +97 -43
- data/lib/flipper/adapters/instrumented.rb +47 -26
- data/lib/flipper/adapters/memoizable.rb +44 -40
- data/lib/flipper/adapters/memory.rb +75 -111
- data/lib/flipper/adapters/operation_logger.rb +22 -78
- data/lib/flipper/adapters/poll/poller.rb +2 -0
- data/lib/flipper/adapters/poll.rb +52 -0
- data/lib/flipper/adapters/pstore.rb +27 -17
- data/lib/flipper/adapters/read_only.rb +8 -41
- data/lib/flipper/adapters/strict.rb +45 -0
- data/lib/flipper/adapters/sync/feature_synchronizer.rb +14 -1
- data/lib/flipper/adapters/sync/interval_synchronizer.rb +2 -7
- data/lib/flipper/adapters/sync/synchronizer.rb +13 -6
- data/lib/flipper/adapters/sync.rb +23 -29
- data/lib/flipper/adapters/wrapper.rb +54 -0
- data/lib/flipper/cli.rb +314 -0
- data/lib/flipper/cloud/configuration.rb +271 -0
- data/lib/flipper/cloud/dsl.rb +27 -0
- data/lib/flipper/cloud/message_verifier.rb +95 -0
- data/lib/flipper/cloud/middleware.rb +63 -0
- data/lib/flipper/cloud/migrate.rb +71 -0
- data/lib/flipper/cloud/routes.rb +14 -0
- data/lib/flipper/cloud/telemetry/backoff_policy.rb +96 -0
- data/lib/flipper/cloud/telemetry/instrumenter.rb +22 -0
- data/lib/flipper/cloud/telemetry/metric.rb +39 -0
- data/lib/flipper/cloud/telemetry/metric_storage.rb +30 -0
- data/lib/flipper/cloud/telemetry/submitter.rb +100 -0
- data/lib/flipper/cloud/telemetry.rb +191 -0
- data/lib/flipper/cloud.rb +54 -0
- data/lib/flipper/configuration.rb +54 -7
- data/lib/flipper/dsl.rb +58 -47
- data/lib/flipper/engine.rb +102 -0
- data/lib/flipper/errors.rb +3 -21
- data/lib/flipper/export.rb +24 -0
- data/lib/flipper/exporter.rb +17 -0
- data/lib/flipper/exporters/json/export.rb +32 -0
- data/lib/flipper/exporters/json/v1.rb +33 -0
- data/lib/flipper/expression/builder.rb +73 -0
- data/lib/flipper/expression/constant.rb +25 -0
- data/lib/flipper/expression.rb +71 -0
- data/lib/flipper/expressions/all.rb +9 -0
- data/lib/flipper/expressions/any.rb +9 -0
- data/lib/flipper/expressions/boolean.rb +9 -0
- data/lib/flipper/expressions/comparable.rb +13 -0
- data/lib/flipper/expressions/equal.rb +9 -0
- data/lib/flipper/expressions/feature_enabled.rb +34 -0
- data/lib/flipper/expressions/greater_than.rb +9 -0
- data/lib/flipper/expressions/greater_than_or_equal_to.rb +9 -0
- data/lib/flipper/expressions/less_than.rb +9 -0
- data/lib/flipper/expressions/less_than_or_equal_to.rb +9 -0
- data/lib/flipper/expressions/not_equal.rb +9 -0
- data/lib/flipper/expressions/now.rb +9 -0
- data/lib/flipper/expressions/number.rb +9 -0
- data/lib/flipper/expressions/percentage.rb +9 -0
- data/lib/flipper/expressions/percentage_of_actors.rb +12 -0
- data/lib/flipper/expressions/property.rb +9 -0
- data/lib/flipper/expressions/random.rb +9 -0
- data/lib/flipper/expressions/string.rb +9 -0
- data/lib/flipper/expressions/time.rb +16 -0
- data/lib/flipper/feature.rb +95 -28
- data/lib/flipper/feature_check_context.rb +10 -6
- data/lib/flipper/gate.rb +13 -11
- data/lib/flipper/gate_values.rb +5 -18
- data/lib/flipper/gates/actor.rb +10 -17
- data/lib/flipper/gates/boolean.rb +1 -1
- data/lib/flipper/gates/expression.rb +75 -0
- data/lib/flipper/gates/group.rb +5 -7
- data/lib/flipper/gates/percentage_of_actors.rb +10 -13
- data/lib/flipper/gates/percentage_of_time.rb +1 -2
- data/lib/flipper/identifier.rb +17 -0
- data/lib/flipper/instrumentation/log_subscriber.rb +35 -8
- data/lib/flipper/instrumentation/statsd.rb +4 -2
- data/lib/flipper/instrumentation/statsd_subscriber.rb +2 -4
- data/lib/flipper/instrumentation/subscriber.rb +8 -5
- data/lib/flipper/instrumenters/memory.rb +6 -2
- data/lib/flipper/metadata.rb +8 -1
- data/lib/flipper/middleware/memoizer.rb +46 -27
- data/lib/flipper/middleware/setup_env.rb +13 -3
- data/lib/flipper/model/active_record.rb +23 -0
- data/lib/flipper/poller.rb +157 -0
- data/lib/flipper/serializers/gzip.rb +22 -0
- data/lib/flipper/serializers/json.rb +17 -0
- data/lib/flipper/spec/shared_adapter_specs.rb +122 -56
- data/lib/flipper/test/shared_adapter_test.rb +120 -52
- data/lib/flipper/test_help.rb +43 -0
- data/lib/flipper/typecast.rb +59 -18
- data/lib/flipper/types/actor.rb +19 -13
- data/lib/flipper/types/group.rb +12 -5
- data/lib/flipper/types/percentage.rb +1 -1
- data/lib/flipper/version.rb +11 -1
- data/lib/flipper.rb +71 -12
- data/lib/generators/flipper/setup_generator.rb +68 -0
- data/lib/generators/flipper/templates/initializer.rb +45 -0
- data/lib/generators/flipper/templates/update/migrations/01_create_flipper_tables.rb.erb +22 -0
- data/lib/generators/flipper/templates/update/migrations/02_change_flipper_gates_value_to_text.rb.erb +18 -0
- data/lib/generators/flipper/update_generator.rb +35 -0
- data/package-lock.json +41 -0
- data/package.json +10 -0
- data/spec/fixtures/environment.rb +1 -0
- data/spec/fixtures/flipper_pstore_1679087600.json +46 -0
- data/spec/flipper/actor_spec.rb +10 -2
- data/spec/flipper/adapter_builder_spec.rb +72 -0
- data/spec/flipper/adapter_spec.rb +52 -6
- data/spec/flipper/adapters/actor_limit_spec.rb +75 -0
- data/spec/flipper/adapters/dual_write_spec.rb +82 -0
- data/spec/flipper/adapters/failover_spec.rb +141 -0
- data/spec/flipper/adapters/failsafe_spec.rb +58 -0
- data/spec/flipper/adapters/http/client_spec.rb +61 -0
- data/spec/flipper/adapters/http_spec.rb +402 -65
- data/spec/flipper/adapters/instrumented_spec.rb +31 -13
- data/spec/flipper/adapters/memoizable_spec.rb +51 -33
- data/spec/flipper/adapters/memory_spec.rb +33 -5
- data/spec/flipper/adapters/operation_logger_spec.rb +38 -12
- data/spec/flipper/adapters/poll_spec.rb +41 -0
- data/spec/flipper/adapters/pstore_spec.rb +0 -2
- data/spec/flipper/adapters/read_only_spec.rb +32 -18
- data/spec/flipper/adapters/strict_spec.rb +64 -0
- data/spec/flipper/adapters/sync/feature_synchronizer_spec.rb +39 -1
- data/spec/flipper/adapters/sync/interval_synchronizer_spec.rb +4 -5
- data/spec/flipper/adapters/sync/synchronizer_spec.rb +87 -1
- data/spec/flipper/adapters/sync_spec.rb +17 -6
- data/spec/flipper/cli_spec.rb +217 -0
- data/spec/flipper/cloud/configuration_spec.rb +257 -0
- data/spec/flipper/cloud/dsl_spec.rb +90 -0
- data/spec/flipper/cloud/message_verifier_spec.rb +104 -0
- data/spec/flipper/cloud/middleware_spec.rb +307 -0
- data/spec/flipper/cloud/migrate_spec.rb +160 -0
- data/spec/flipper/cloud/telemetry/backoff_policy_spec.rb +107 -0
- data/spec/flipper/cloud/telemetry/metric_spec.rb +87 -0
- data/spec/flipper/cloud/telemetry/metric_storage_spec.rb +58 -0
- data/spec/flipper/cloud/telemetry/submitter_spec.rb +145 -0
- data/spec/flipper/cloud/telemetry_spec.rb +208 -0
- data/spec/flipper/cloud_spec.rb +186 -0
- data/spec/flipper/configuration_spec.rb +37 -3
- data/spec/flipper/dsl_spec.rb +67 -80
- data/spec/flipper/engine_spec.rb +374 -0
- data/spec/flipper/export_spec.rb +13 -0
- data/spec/flipper/exporter_spec.rb +16 -0
- data/spec/flipper/exporters/json/export_spec.rb +60 -0
- data/spec/flipper/exporters/json/v1_spec.rb +33 -0
- data/spec/flipper/expression/builder_spec.rb +248 -0
- data/spec/flipper/expression_spec.rb +188 -0
- data/spec/flipper/expressions/all_spec.rb +15 -0
- data/spec/flipper/expressions/any_spec.rb +15 -0
- data/spec/flipper/expressions/boolean_spec.rb +15 -0
- data/spec/flipper/expressions/equal_spec.rb +24 -0
- data/spec/flipper/expressions/greater_than_or_equal_to_spec.rb +28 -0
- data/spec/flipper/expressions/greater_than_spec.rb +28 -0
- data/spec/flipper/expressions/less_than_or_equal_to_spec.rb +28 -0
- data/spec/flipper/expressions/less_than_spec.rb +32 -0
- data/spec/flipper/expressions/not_equal_spec.rb +15 -0
- data/spec/flipper/expressions/now_spec.rb +11 -0
- data/spec/flipper/expressions/number_spec.rb +21 -0
- data/spec/flipper/expressions/percentage_of_actors_spec.rb +20 -0
- data/spec/flipper/expressions/percentage_spec.rb +15 -0
- data/spec/flipper/expressions/property_spec.rb +13 -0
- data/spec/flipper/expressions/random_spec.rb +9 -0
- data/spec/flipper/expressions/string_spec.rb +11 -0
- data/spec/flipper/expressions/time_spec.rb +29 -0
- data/spec/flipper/feature_check_context_spec.rb +18 -20
- data/spec/flipper/feature_spec.rb +461 -48
- data/spec/flipper/gate_spec.rb +0 -2
- data/spec/flipper/gate_values_spec.rb +2 -34
- data/spec/flipper/gates/actor_spec.rb +0 -2
- data/spec/flipper/gates/boolean_spec.rb +1 -3
- data/spec/flipper/gates/expression_spec.rb +190 -0
- data/spec/flipper/gates/group_spec.rb +2 -5
- data/spec/flipper/gates/percentage_of_actors_spec.rb +61 -7
- data/spec/flipper/gates/percentage_of_time_spec.rb +2 -4
- data/spec/flipper/identifier_spec.rb +12 -0
- data/spec/flipper/instrumentation/log_subscriber_spec.rb +24 -7
- data/spec/flipper/instrumentation/statsd_subscriber_spec.rb +26 -3
- 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 +199 -62
- data/spec/flipper/middleware/setup_env_spec.rb +23 -5
- data/spec/flipper/model/active_record_spec.rb +72 -0
- data/spec/flipper/poller_spec.rb +390 -0
- data/spec/flipper/registry_spec.rb +0 -1
- data/spec/flipper/serializers/gzip_spec.rb +13 -0
- data/spec/flipper/serializers/json_spec.rb +13 -0
- data/spec/flipper/typecast_spec.rb +121 -7
- data/spec/flipper/types/actor_spec.rb +63 -47
- data/spec/flipper/types/boolean_spec.rb +0 -1
- data/spec/flipper/types/group_spec.rb +24 -3
- 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/{integration_spec.rb → flipper_integration_spec.rb} +301 -59
- data/spec/flipper_spec.rb +123 -29
- data/spec/{helper.rb → spec_helper.rb} +23 -21
- data/spec/support/actor_names.yml +1 -0
- data/spec/support/descriptions.yml +1 -0
- data/spec/support/fail_on_output.rb +8 -0
- data/spec/support/fake_backoff_policy.rb +15 -0
- data/spec/support/skippable.rb +18 -0
- data/spec/support/spec_helpers.rb +53 -6
- data/test/adapters/actor_limit_test.rb +20 -0
- data/test/test_helper.rb +2 -1
- data/test_rails/generators/flipper/setup_generator_test.rb +69 -0
- data/test_rails/generators/flipper/update_generator_test.rb +96 -0
- data/test_rails/helper.rb +31 -0
- data/test_rails/system/test_help_test.rb +52 -0
- metadata +200 -82
- data/.rubocop.yml +0 -54
- data/.rubocop_todo.yml +0 -199
- 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 -114
- data/docs/api/README.md +0 -849
- data/docs/http/README.md +0 -35
- data/docs/read-only/README.md +0 -21
- data/examples/example_setup.rb +0 -8
- data/test/helper.rb +0 -11
data/Gemfile
CHANGED
|
@@ -6,28 +6,36 @@ Dir['flipper-*.gemspec'].each do |gemspec|
|
|
|
6
6
|
gemspec(name: "flipper-#{plugin}", development_group: plugin)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
gem '
|
|
10
|
-
gem '
|
|
11
|
-
gem '
|
|
9
|
+
gem 'concurrent-ruby', '1.3.4'
|
|
10
|
+
gem 'connection_pool'
|
|
11
|
+
gem 'debug'
|
|
12
|
+
gem 'rake'
|
|
12
13
|
gem 'statsd-ruby', '~> 1.2.1'
|
|
13
14
|
gem 'rspec', '~> 3.0'
|
|
14
|
-
gem 'rack-test'
|
|
15
|
-
gem '
|
|
16
|
-
gem '
|
|
17
|
-
gem '
|
|
18
|
-
gem '
|
|
19
|
-
gem '
|
|
20
|
-
gem '
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
gem '
|
|
15
|
+
gem 'rack-test'
|
|
16
|
+
gem 'rackup', '= 1.0.0'
|
|
17
|
+
gem 'sqlite3', "~> #{ENV['SQLITE3_VERSION'] || '2.1.0'}"
|
|
18
|
+
gem 'rails', "~> #{ENV['RAILS_VERSION'] || '8.0'}"
|
|
19
|
+
gem 'minitest', '~> 5.18'
|
|
20
|
+
gem 'minitest-documentation'
|
|
21
|
+
gem 'pstore'
|
|
22
|
+
gem 'webmock'
|
|
23
|
+
gem 'ice_age'
|
|
24
|
+
gem 'redis-namespace'
|
|
25
|
+
gem 'webrick'
|
|
26
|
+
gem 'stackprof'
|
|
27
|
+
gem 'benchmark-ips'
|
|
28
|
+
gem 'stackprof-webnav'
|
|
29
|
+
gem 'flamegraph'
|
|
30
|
+
gem 'mysql2'
|
|
31
|
+
gem 'pg'
|
|
32
|
+
gem 'cuprite'
|
|
33
|
+
gem 'puma'
|
|
34
|
+
gem 'warning'
|
|
24
35
|
|
|
25
36
|
group(:guard) do
|
|
26
|
-
gem 'guard'
|
|
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'
|
|
37
|
+
gem 'guard'
|
|
38
|
+
gem 'guard-rspec'
|
|
39
|
+
gem 'guard-bundler'
|
|
40
|
+
gem 'rb-fsevent'
|
|
33
41
|
end
|
data/README.md
CHANGED
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
Feature flipping is the act of enabling or disabling features or parts of your application, ideally without re-deploying or changing anything in your code base.
|
|
19
|
-
|
|
20
|
-
The goal of this gem is to make turning features on or off so easy that everyone does it. Whatever your data store, throughput, or experience, feature flipping should be easy and have minimal impact on your application.
|
|
1
|
+
[](https://www.flippercloud.io)
|
|
2
|
+
|
|
3
|
+
[Website](https://flippercloud.io?utm_source=oss&utm_medium=readme&utm_campaign=website_link) | [Documentation](https://flippercloud.io/docs?utm_source=oss&utm_medium=readme&utm_campaign=docs_link) | [Examples](examples) | [Chat](https://chat.flippercloud.io/join/xjHq-aJsA-BeZH) | [Twitter](https://twitter.com/flipper_cloud) | [Ruby.social](https://ruby.social/@flipper)
|
|
4
|
+
|
|
5
|
+
# Flipper
|
|
6
|
+
|
|
7
|
+
> Beautiful, performant feature flags for Ruby and Rails.
|
|
8
|
+
|
|
9
|
+
Flipper gives you control over who has access to features in your app.
|
|
10
|
+
|
|
11
|
+
- Enable or disable features for everyone, specific actors, groups of actors, a percentage of actors, or a percentage of time.
|
|
12
|
+
- Configure your feature flags from the console or a web UI.
|
|
13
|
+
- Regardless of what data store you are using, Flipper can performantly store your feature flags.
|
|
14
|
+
- Use [Flipper Cloud](#flipper-cloud) to cascade features from multiple environments, share settings with your team, control permissions, keep an audit history, and rollback.
|
|
15
|
+
|
|
16
|
+
Control your software — don't let it control you.
|
|
21
17
|
|
|
22
18
|
## Installation
|
|
23
19
|
|
|
@@ -25,6 +21,10 @@ Add this line to your application's Gemfile:
|
|
|
25
21
|
|
|
26
22
|
gem 'flipper'
|
|
27
23
|
|
|
24
|
+
You'll also want to pick a storage [adapter](https://flippercloud.io/docs/adapters), for example:
|
|
25
|
+
|
|
26
|
+
gem 'flipper-active_record'
|
|
27
|
+
|
|
28
28
|
And then execute:
|
|
29
29
|
|
|
30
30
|
$ bundle
|
|
@@ -33,74 +33,84 @@ Or install it yourself with:
|
|
|
33
33
|
|
|
34
34
|
$ gem install flipper
|
|
35
35
|
|
|
36
|
-
##
|
|
37
|
-
|
|
38
|
-
The goal of the API for flipper was to have everything revolve around features and what ways they can be enabled. Start with top level and dig into a feature, then dig in further and enable that feature for a given type of access, as opposed to thinking about how the feature will be accessed first (ie: `stats.enable` vs `activate_group(:stats, ...)`).
|
|
36
|
+
## Subscribe & Ship
|
|
39
37
|
|
|
40
|
-
|
|
41
|
-
require 'flipper'
|
|
38
|
+
[💌 Subscribe](https://blog.flippercloud.io/#/portal/signup) - we'll send you short and sweet emails when we release new versions ([examples](https://blog.flippercloud.io/tag/releases/)).
|
|
42
39
|
|
|
43
|
-
|
|
44
|
-
config.default do
|
|
45
|
-
# pick an adapter, this uses memory, any will do
|
|
46
|
-
adapter = Flipper::Adapters::Memory.new
|
|
40
|
+
## Getting Started
|
|
47
41
|
|
|
48
|
-
|
|
49
|
-
Flipper.new(adapter)
|
|
50
|
-
end
|
|
51
|
-
end
|
|
42
|
+
Use `Flipper#enabled?` in your app to check if a feature is enabled.
|
|
52
43
|
|
|
44
|
+
```ruby
|
|
53
45
|
# check if search is enabled
|
|
54
|
-
if Flipper.enabled?(:search)
|
|
46
|
+
if Flipper.enabled?(:search, current_user)
|
|
55
47
|
puts 'Search away!'
|
|
56
48
|
else
|
|
57
49
|
puts 'No search for you!'
|
|
58
50
|
end
|
|
51
|
+
```
|
|
59
52
|
|
|
60
|
-
|
|
61
|
-
Flipper.enable(:search)
|
|
53
|
+
All features are disabled by default, so you'll need to explicitly enable them.
|
|
62
54
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
55
|
+
```ruby
|
|
56
|
+
# Enable a feature for everyone
|
|
57
|
+
Flipper.enable :search
|
|
58
|
+
|
|
59
|
+
# Enable a feature for a specific actor
|
|
60
|
+
Flipper.enable_actor :search, current_user
|
|
61
|
+
|
|
62
|
+
# Enable a feature for a group of actors
|
|
63
|
+
Flipper.enable_group :search, :admin
|
|
64
|
+
|
|
65
|
+
# Enable a feature for a percentage of actors
|
|
66
|
+
Flipper.enable_percentage_of_actors :search, 2
|
|
69
67
|
```
|
|
70
68
|
|
|
71
|
-
|
|
69
|
+
Read more about [getting started with Flipper](https://flippercloud.io/docs?utm_source=oss&utm_medium=readme&utm_campaign=getting_started) and [enabling features](https://flippercloud.io/docs/features?utm_source=oss&utm_medium=readme&utm_campaign=enabling_features).
|
|
70
|
+
|
|
71
|
+
## Flipper Cloud
|
|
72
|
+
|
|
73
|
+
Like Flipper and want more? Check out [Flipper Cloud](https://www.flippercloud.io?utm_source=oss&utm_medium=readme&utm_campaign=check_out), which comes with:
|
|
74
|
+
|
|
75
|
+
- **multiple environments** — production, staging, per continent, whatever you need. Every environment inherits from production by default and every project comes with a [project overview page](https://blog.flippercloud.io/project-overview/) that shows each feature and its status in each environment.
|
|
76
|
+
- **personal environments** — everyone on your team gets a personal environment (that inherits from production) which they can modify however they want without stepping on anyone else's toes.
|
|
77
|
+
- **permissions** — grant access to everyone in your organization or lockdown each project to particular people. You can even limit access to a particular environment (like production) to specific people.
|
|
78
|
+
- **audit history** — every feature change and who made it.
|
|
79
|
+
- **rollbacks** — enable or disable a feature accidentally? No problem. You can roll back to any point in the audit history with a single click.
|
|
80
|
+
- **maintenance** — we'll keep the lights on for you. We also have handy webhooks and background polling for keeping your app in sync with Cloud, so **our availability won't affect yours**. All your feature flag reads are local to your app.
|
|
81
|
+
- **everything in one place** — no need to bounce around from different application UIs or IRB consoles.
|
|
82
|
+
|
|
83
|
+
[](https://www.flippercloud.io?utm_source=oss&utm_medium=readme&utm_campaign=screenshot)
|
|
72
84
|
|
|
73
|
-
|
|
85
|
+
Cloud is super simple to integrate with Rails ([demo app](https://github.com/fewerandfaster/flipper-rails-demo)), Sinatra or any other framework.
|
|
74
86
|
|
|
75
|
-
|
|
76
|
-
* [Adapters](docs/Adapters.md) - Mongo, Redis, Cassandra, Active Record...
|
|
77
|
-
* [Instrumentation](docs/Instrumentation.md) - ActiveSupport::Notifications and Statsd
|
|
78
|
-
* [Optimization](docs/Optimization.md) - Memoization middleware and Cache adapters
|
|
79
|
-
* [Web Interface](docs/ui/README.md) - Point and click...
|
|
80
|
-
* [API](docs/api/README.md) - HTTP API interface
|
|
81
|
-
* [Caveats](docs/Caveats.md) - Flipper beware! (see what I did there)
|
|
82
|
-
* [Docker-Compose](docs/DockerCompose.md) - Using docker-compose in contributing
|
|
87
|
+
We also have a [free plan](https://www.flippercloud.io?utm_source=oss&utm_medium=readme&utm_campaign=free_plan) that you can use forever.
|
|
83
88
|
|
|
84
89
|
## Contributing
|
|
85
90
|
|
|
86
91
|
1. Fork it
|
|
87
92
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
88
|
-
3.
|
|
93
|
+
3. Run the tests (`bundle exec rake`). Check out [Docker-Compose](docs/DockerCompose.md) if you need help getting all the adapters running.
|
|
89
94
|
4. Commit your changes (`git commit -am 'Added some feature'`)
|
|
90
95
|
5. Push to the branch (`git push origin my-new-feature`)
|
|
91
96
|
6. Create new Pull Request
|
|
92
97
|
|
|
93
98
|
## Releasing
|
|
94
99
|
|
|
95
|
-
1. Update the version
|
|
96
|
-
2. `
|
|
97
|
-
3.
|
|
100
|
+
1. Update the version in `lib/flipper/version.rb` and commit.
|
|
101
|
+
2. Tag and push: `git tag v1.x.x && git push origin v1.x.x`
|
|
102
|
+
3. GitHub Actions builds and publishes all gems to RubyGems automatically.
|
|
103
|
+
4. Edit and publish the draft [GitHub Release](https://github.com/flippercloud/flipper/releases).
|
|
98
104
|
|
|
99
105
|
## Brought To You By
|
|
100
106
|
|
|
101
|
-
| pic
|
|
102
|
-
|
|
103
|
-
| 
|
|
104
|
-
|  | [@jnunemaker](https://github.com/jnunemaker) | most things |
|
|
110
|
+
|  | [@bkeepers](https://github.com/bkeepers) | most things |
|
|
111
|
+
|  | [@dpep](https://github.com/dpep) | tbd |
|
|
112
|
+
|  | [@alexwheeler](https://github.com/alexwheeler) | api |
|
|
113
|
+
|  | [@thetimbanks](https://github.com/thetimbanks) | ui |
|
|
114
|
+
|  | [@lazebny](https://github.com/lazebny) | docker |
|
|
115
|
+
|  | [@pagertree](https://github.com/pagertree) | sponsor |
|
|
116
|
+
|  | [@kdaigle](https://github.com/kdaigle) | sponsor |
|
data/Rakefile
CHANGED
|
@@ -18,14 +18,17 @@ end
|
|
|
18
18
|
desc 'Tags version, pushes to remote, and pushes gem'
|
|
19
19
|
task release: :build do
|
|
20
20
|
sh 'git', 'tag', "v#{Flipper::VERSION}"
|
|
21
|
-
sh 'git push origin
|
|
21
|
+
sh 'git push origin main'
|
|
22
22
|
sh "git push origin v#{Flipper::VERSION}"
|
|
23
|
-
|
|
23
|
+
puts "\nWhat OTP code should be used?"
|
|
24
|
+
otp_code = STDIN.gets.chomp
|
|
25
|
+
sh "ls pkg/*.gem | xargs -n 1 gem push --otp #{otp_code}"
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
require 'rspec/core/rake_task'
|
|
27
29
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
|
28
30
|
t.rspec_opts = %w(--color)
|
|
31
|
+
t.verbose = false
|
|
29
32
|
end
|
|
30
33
|
|
|
31
34
|
namespace :spec do
|
|
@@ -39,6 +42,13 @@ end
|
|
|
39
42
|
Rake::TestTask.new do |t|
|
|
40
43
|
t.libs = %w(lib test)
|
|
41
44
|
t.pattern = 'test/**/*_test.rb'
|
|
45
|
+
t.warning = false
|
|
42
46
|
end
|
|
43
47
|
|
|
44
|
-
|
|
48
|
+
Rake::TestTask.new(:test_rails) do |t|
|
|
49
|
+
t.libs = %w(lib test_rails)
|
|
50
|
+
t.pattern = 'test_rails/**/*_test.rb'
|
|
51
|
+
t.warning = false
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
task default: [:spec, :test, :test_rails]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'bundler/setup'
|
|
2
|
+
require 'flipper'
|
|
3
|
+
require 'benchmark/ips'
|
|
4
|
+
|
|
5
|
+
actor1 = Flipper::Actor.new("User;1")
|
|
6
|
+
actor2 = Flipper::Actor.new("User;2")
|
|
7
|
+
actor3 = Flipper::Actor.new("User;3")
|
|
8
|
+
actor4 = Flipper::Actor.new("User;4")
|
|
9
|
+
actor5 = Flipper::Actor.new("User;5")
|
|
10
|
+
actor6 = Flipper::Actor.new("User;6")
|
|
11
|
+
actor7 = Flipper::Actor.new("User;7")
|
|
12
|
+
actor8 = Flipper::Actor.new("User;8")
|
|
13
|
+
|
|
14
|
+
actors = [actor1, actor2, actor3, actor4, actor5, actor6, actor7, actor8]
|
|
15
|
+
|
|
16
|
+
Benchmark.ips do |x|
|
|
17
|
+
x.report("with array of actors") { Flipper.enabled?(:foo, actors) }
|
|
18
|
+
x.report("with multiple enabled? checks") { actors.each { |actor| Flipper.enabled?(:foo, actor) } }
|
|
19
|
+
x.compare!
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'bundler/setup'
|
|
2
|
+
require 'flipper'
|
|
3
|
+
require 'stackprof'
|
|
4
|
+
require 'benchmark/ips'
|
|
5
|
+
|
|
6
|
+
flipper = Flipper.new(Flipper::Adapters::Memory.new)
|
|
7
|
+
feature = flipper.feature(:foo)
|
|
8
|
+
actor = Flipper::Actor.new("User;1")
|
|
9
|
+
|
|
10
|
+
profile = StackProf.run(mode: :wall, interval: 1_000) do
|
|
11
|
+
2_000_000.times do
|
|
12
|
+
feature.enabled?(actor)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
result = StackProf::Report.new(profile)
|
|
17
|
+
puts
|
|
18
|
+
result.print_text
|
|
19
|
+
puts "\n\n\n"
|
|
20
|
+
result.print_method(/Flipper::Feature#enabled?/)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'bundler/setup'
|
|
2
|
+
require 'flipper'
|
|
3
|
+
require 'active_support/notifications'
|
|
4
|
+
require 'active_support/isolated_execution_state'
|
|
5
|
+
require 'benchmark/ips'
|
|
6
|
+
|
|
7
|
+
class FlipperSubscriber
|
|
8
|
+
def call(name, start, finish, id, payload)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
ActiveSupport::Notifications.subscribe(/flipper/, new)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
actor = Flipper::Actor.new("User;1")
|
|
15
|
+
bare = Flipper.new(Flipper::Adapters::Memory.new)
|
|
16
|
+
instrumented = Flipper.new(Flipper::Adapters::Memory.new, instrumenter: ActiveSupport::Notifications)
|
|
17
|
+
|
|
18
|
+
Benchmark.ips do |x|
|
|
19
|
+
x.report("with instrumentation") { instrumented.enabled?(:foo, actor) }
|
|
20
|
+
x.report("without instrumentation") { bare.enabled?(:foo, actor) }
|
|
21
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'bundler/setup'
|
|
2
|
+
require 'flipper'
|
|
3
|
+
require 'benchmark/ips'
|
|
4
|
+
|
|
5
|
+
Benchmark.ips do |x|
|
|
6
|
+
x.report("Typecast.to_boolean true") { Flipper::Typecast.to_boolean(true) }
|
|
7
|
+
x.report("Typecast.to_boolean 1") { Flipper::Typecast.to_boolean(1) }
|
|
8
|
+
x.report("Typecast.to_boolean 'true'") { Flipper::Typecast.to_boolean('true'.freeze) }
|
|
9
|
+
x.report("Typecast.to_boolean '1'") { Flipper::Typecast.to_boolean('1'.freeze) }
|
|
10
|
+
x.report("Typecast.to_boolean false") { Flipper::Typecast.to_boolean(false) }
|
|
11
|
+
|
|
12
|
+
x.report("Typecast.to_integer 1") { Flipper::Typecast.to_integer(1) }
|
|
13
|
+
x.report("Typecast.to_integer '1'") { Flipper::Typecast.to_integer('1') }
|
|
14
|
+
|
|
15
|
+
x.report("Typecast.to_float 1") { Flipper::Typecast.to_float(1) }
|
|
16
|
+
x.report("Typecast.to_float '1'") { Flipper::Typecast.to_float('1'.freeze) }
|
|
17
|
+
x.report("Typecast.to_float 1.01") { Flipper::Typecast.to_float(1) }
|
|
18
|
+
x.report("Typecast.to_float '1.01'") { Flipper::Typecast.to_float('1'.freeze) }
|
|
19
|
+
|
|
20
|
+
x.report("Typecast.to_number 1") { Flipper::Typecast.to_number(1) }
|
|
21
|
+
x.report("Typecast.to_number 1.1") { Flipper::Typecast.to_number(1.1) }
|
|
22
|
+
x.report("Typecast.to_number '1'") { Flipper::Typecast.to_number('1'.freeze) }
|
|
23
|
+
x.report("Typecast.to_number '1.1'") { Flipper::Typecast.to_number('1.1'.freeze) }
|
|
24
|
+
x.report("Typecast.to_number nil") { Flipper::Typecast.to_number(nil) }
|
|
25
|
+
time = Time.now
|
|
26
|
+
x.report("Typecast.to_number Time.now") { Flipper::Typecast.to_number(time) }
|
|
27
|
+
end
|
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/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/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
See [flippercloud.io](https://flippercloud.io/docs) for extensive docs.
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Usage:
|
|
3
|
+
# bin/rackup examples/api/basic.ru -p 9999
|
|
4
|
+
#
|
|
5
|
+
# http://localhost:9999/
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
require 'bundler/setup'
|
|
9
|
+
require 'rack/reloader'
|
|
10
|
+
require "flipper/api"
|
|
11
|
+
require "flipper/adapters/pstore"
|
|
12
|
+
|
|
13
|
+
# You can uncomment this to get some default data:
|
|
14
|
+
# Flipper.enable :logging
|
|
15
|
+
|
|
16
|
+
use Rack::Reloader
|
|
17
|
+
|
|
18
|
+
run Flipper::Api.app
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Usage:
|
|
3
|
+
# bin/rackup examples/api/custom_memoized.ru -p 9999
|
|
4
|
+
#
|
|
5
|
+
# http://localhost:9999/
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
require 'bundler/setup'
|
|
9
|
+
require 'rack/reloader'
|
|
10
|
+
require "active_support/notifications"
|
|
11
|
+
require "flipper/api"
|
|
12
|
+
require "flipper/adapters/pstore"
|
|
13
|
+
|
|
14
|
+
adapter = Flipper::Adapters::Instrumented.new(
|
|
15
|
+
Flipper::Adapters::PStore.new,
|
|
16
|
+
instrumenter: ActiveSupport::Notifications,
|
|
17
|
+
)
|
|
18
|
+
flipper = Flipper.new(adapter)
|
|
19
|
+
|
|
20
|
+
ActiveSupport::Notifications.subscribe(/.*/, ->(*args) {
|
|
21
|
+
name, start, finish, id, data = args
|
|
22
|
+
case name
|
|
23
|
+
when "adapter_operation.flipper"
|
|
24
|
+
p data[:adapter_name] => data[:operation]
|
|
25
|
+
end
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
# You can uncomment this to get some default data:
|
|
29
|
+
# flipper[:logging].enable_percentage_of_time 5
|
|
30
|
+
|
|
31
|
+
use Rack::Reloader
|
|
32
|
+
|
|
33
|
+
run Flipper::Api.app(flipper) { |builder|
|
|
34
|
+
builder.use Flipper::Middleware::SetupEnv, flipper
|
|
35
|
+
builder.use Flipper::Middleware::Memoizer, preload: true
|
|
36
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Usage:
|
|
3
|
+
# bin/rackup examples/api/memoized.ru -p 9999
|
|
4
|
+
#
|
|
5
|
+
# http://localhost:9999/
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
require 'bundler/setup'
|
|
9
|
+
require 'rack/reloader'
|
|
10
|
+
require "active_support/notifications"
|
|
11
|
+
require "flipper/api"
|
|
12
|
+
require "flipper/adapters/pstore"
|
|
13
|
+
|
|
14
|
+
Flipper.configure do |config|
|
|
15
|
+
config.adapter {
|
|
16
|
+
Flipper::Adapters::Instrumented.new(
|
|
17
|
+
Flipper::Adapters::PStore.new,
|
|
18
|
+
instrumenter: ActiveSupport::Notifications,
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
ActiveSupport::Notifications.subscribe(/.*/, ->(*args) {
|
|
24
|
+
name, start, finish, id, data = args
|
|
25
|
+
case name
|
|
26
|
+
when "adapter_operation.flipper"
|
|
27
|
+
p data[:adapter_name] => data[:operation]
|
|
28
|
+
end
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
Flipper.register(:admins) { |actor|
|
|
32
|
+
actor.respond_to?(:admin?) && actor.admin?
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# You can uncomment this to get some default data:
|
|
36
|
+
# Flipper.enable :logging
|
|
37
|
+
|
|
38
|
+
use Rack::Reloader
|
|
39
|
+
|
|
40
|
+
run Flipper::Api.app { |builder|
|
|
41
|
+
builder.use Flipper::Middleware::Memoizer, preload: true
|
|
42
|
+
}
|
data/examples/basic.rb
CHANGED
|
@@ -1,17 +1,6 @@
|
|
|
1
|
-
require
|
|
2
|
-
|
|
1
|
+
require 'bundler/setup'
|
|
3
2
|
require 'flipper'
|
|
4
3
|
|
|
5
|
-
Flipper.configure do |config|
|
|
6
|
-
config.default do
|
|
7
|
-
# pick an adapter, this uses memory, any will do
|
|
8
|
-
adapter = Flipper::Adapters::Memory.new
|
|
9
|
-
|
|
10
|
-
# pass adapter to handy DSL instance
|
|
11
|
-
Flipper.new(adapter)
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
4
|
# check if search is enabled
|
|
16
5
|
if Flipper.enabled?(:search)
|
|
17
6
|
puts 'Search away!'
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Usage (from the repo root):
|
|
2
|
+
# env FLIPPER_CLOUD_TOKEN=<token> FLIPPER_CLOUD_SYNC_SECRET=<secret> bundle exec rackup examples/cloud/app.ru -p 9999
|
|
3
|
+
# http://localhost:9999/
|
|
4
|
+
|
|
5
|
+
require 'bundler/setup'
|
|
6
|
+
require 'flipper/cloud'
|
|
7
|
+
|
|
8
|
+
Flipper.configure do |config|
|
|
9
|
+
config.default { Flipper::Cloud.new }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
run Flipper::Cloud.app
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Just a simple example that shows how the backoff policy works.
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
require 'flipper/cloud/telemetry/backoff_policy'
|
|
4
|
+
|
|
5
|
+
intervals = []
|
|
6
|
+
policy = Flipper::Cloud::Telemetry::BackoffPolicy.new
|
|
7
|
+
|
|
8
|
+
5.times do |n|
|
|
9
|
+
intervals << policy.next_interval
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
pp intervals.map { |i| i.round(2) }
|
|
13
|
+
puts "Total: #{intervals.sum.round(2)}ms (#{(intervals.sum/1_000.0).round(2)} sec)"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Usage (from the repo root):
|
|
2
|
+
# env FLIPPER_CLOUD_TOKEN=<token> bundle exec ruby examples/cloud/basic.rb
|
|
3
|
+
|
|
4
|
+
require_relative "./cloud_setup"
|
|
5
|
+
require 'bundler/setup'
|
|
6
|
+
require 'flipper/cloud'
|
|
7
|
+
|
|
8
|
+
Flipper[:stats].enable
|
|
9
|
+
|
|
10
|
+
if Flipper[:stats].enabled?
|
|
11
|
+
puts 'Enabled!'
|
|
12
|
+
else
|
|
13
|
+
puts 'Disabled!'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
Flipper[:stats].disable
|
|
17
|
+
|
|
18
|
+
if Flipper[:stats].enabled?
|
|
19
|
+
puts 'Enabled!'
|
|
20
|
+
else
|
|
21
|
+
puts 'Disabled!'
|
|
22
|
+
end
|