flipper 0.28.3 → 1.4.2

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.
Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/ci.yml +56 -10
  4. data/.github/workflows/examples.yml +54 -11
  5. data/.github/workflows/release.yml +54 -0
  6. data/.superset/config.json +4 -0
  7. data/CLAUDE.md +93 -0
  8. data/Changelog.md +1 -559
  9. data/Gemfile +17 -8
  10. data/README.md +34 -29
  11. data/Rakefile +2 -2
  12. data/benchmark/typecast_ips.rb +8 -0
  13. data/docs/images/banner.jpg +0 -0
  14. data/docs/images/flipper_cloud.png +0 -0
  15. data/examples/cloud/app.ru +12 -0
  16. data/examples/cloud/backoff_policy.rb +13 -0
  17. data/examples/cloud/basic.rb +22 -0
  18. data/examples/cloud/cloud_setup.rb +20 -0
  19. data/examples/cloud/forked.rb +36 -0
  20. data/examples/cloud/import.rb +17 -0
  21. data/examples/cloud/poll_interval/README.md +111 -0
  22. data/examples/cloud/poll_interval/client.rb +108 -0
  23. data/examples/cloud/poll_interval/server.rb +98 -0
  24. data/examples/cloud/threaded.rb +33 -0
  25. data/examples/dsl.rb +0 -14
  26. data/examples/expressions.rb +237 -0
  27. data/examples/strict.rb +18 -0
  28. data/exe/flipper +5 -0
  29. data/flipper-cloud.gemspec +19 -0
  30. data/flipper.gemspec +8 -4
  31. data/lib/flipper/actor.rb +6 -3
  32. data/lib/flipper/adapter.rb +27 -1
  33. data/lib/flipper/adapter_builder.rb +44 -0
  34. data/lib/flipper/adapters/actor_limit.rb +54 -0
  35. data/lib/flipper/adapters/cache_base.rb +161 -0
  36. data/lib/flipper/adapters/dual_write.rb +7 -5
  37. data/lib/flipper/adapters/failover.rb +9 -7
  38. data/lib/flipper/adapters/failsafe.rb +2 -6
  39. data/lib/flipper/adapters/http/client.rb +53 -14
  40. data/lib/flipper/adapters/http/error.rb +2 -2
  41. data/lib/flipper/adapters/http.rb +56 -16
  42. data/lib/flipper/adapters/instrumented.rb +2 -6
  43. data/lib/flipper/adapters/memoizable.rb +17 -22
  44. data/lib/flipper/adapters/memory.rb +5 -7
  45. data/lib/flipper/adapters/operation_logger.rb +18 -92
  46. data/lib/flipper/adapters/poll.rb +16 -3
  47. data/lib/flipper/adapters/pstore.rb +18 -12
  48. data/lib/flipper/adapters/read_only.rb +8 -41
  49. data/lib/flipper/adapters/strict.rb +75 -0
  50. data/lib/flipper/adapters/sync/feature_synchronizer.rb +14 -1
  51. data/lib/flipper/adapters/sync/synchronizer.rb +13 -5
  52. data/lib/flipper/adapters/sync.rb +7 -7
  53. data/lib/flipper/adapters/wrapper.rb +54 -0
  54. data/lib/flipper/cli.rb +314 -0
  55. data/lib/flipper/cloud/configuration.rb +267 -0
  56. data/lib/flipper/cloud/dsl.rb +27 -0
  57. data/lib/flipper/cloud/message_verifier.rb +95 -0
  58. data/lib/flipper/cloud/middleware.rb +63 -0
  59. data/lib/flipper/cloud/migrate.rb +71 -0
  60. data/lib/flipper/cloud/routes.rb +14 -0
  61. data/lib/flipper/cloud/telemetry/backoff_policy.rb +96 -0
  62. data/lib/flipper/cloud/telemetry/instrumenter.rb +22 -0
  63. data/lib/flipper/cloud/telemetry/metric.rb +39 -0
  64. data/lib/flipper/cloud/telemetry/metric_storage.rb +30 -0
  65. data/lib/flipper/cloud/telemetry/submitter.rb +100 -0
  66. data/lib/flipper/cloud/telemetry.rb +191 -0
  67. data/lib/flipper/cloud.rb +54 -0
  68. data/lib/flipper/configuration.rb +25 -4
  69. data/lib/flipper/dsl.rb +48 -43
  70. data/lib/flipper/engine.rb +102 -0
  71. data/lib/flipper/export.rb +0 -2
  72. data/lib/flipper/exporters/json/export.rb +1 -1
  73. data/lib/flipper/exporters/json/v1.rb +1 -1
  74. data/lib/flipper/expression/builder.rb +73 -0
  75. data/lib/flipper/expression/constant.rb +25 -0
  76. data/lib/flipper/expression.rb +71 -0
  77. data/lib/flipper/expressions/all.rb +9 -0
  78. data/lib/flipper/expressions/any.rb +9 -0
  79. data/lib/flipper/expressions/boolean.rb +9 -0
  80. data/lib/flipper/expressions/comparable.rb +13 -0
  81. data/lib/flipper/expressions/equal.rb +9 -0
  82. data/lib/flipper/expressions/feature_enabled.rb +34 -0
  83. data/lib/flipper/expressions/greater_than.rb +9 -0
  84. data/lib/flipper/expressions/greater_than_or_equal_to.rb +9 -0
  85. data/lib/flipper/expressions/less_than.rb +9 -0
  86. data/lib/flipper/expressions/less_than_or_equal_to.rb +9 -0
  87. data/lib/flipper/expressions/not_equal.rb +9 -0
  88. data/lib/flipper/expressions/now.rb +9 -0
  89. data/lib/flipper/expressions/number.rb +9 -0
  90. data/lib/flipper/expressions/percentage.rb +9 -0
  91. data/lib/flipper/expressions/percentage_of_actors.rb +12 -0
  92. data/lib/flipper/expressions/property.rb +9 -0
  93. data/lib/flipper/expressions/random.rb +9 -0
  94. data/lib/flipper/expressions/string.rb +9 -0
  95. data/lib/flipper/expressions/time.rb +16 -0
  96. data/lib/flipper/feature.rb +63 -1
  97. data/lib/flipper/gate.rb +2 -1
  98. data/lib/flipper/gate_values.rb +5 -2
  99. data/lib/flipper/gates/expression.rb +75 -0
  100. data/lib/flipper/instrumentation/log_subscriber.rb +13 -5
  101. data/lib/flipper/instrumentation/statsd.rb +4 -2
  102. data/lib/flipper/instrumentation/statsd_subscriber.rb +2 -4
  103. data/lib/flipper/instrumentation/subscriber.rb +0 -4
  104. data/lib/flipper/metadata.rb +8 -1
  105. data/lib/flipper/middleware/memoizer.rb +30 -14
  106. data/lib/flipper/model/active_record.rb +23 -0
  107. data/lib/flipper/poller.rb +54 -12
  108. data/lib/flipper/serializers/gzip.rb +22 -0
  109. data/lib/flipper/serializers/json.rb +17 -0
  110. data/lib/flipper/spec/shared_adapter_specs.rb +82 -63
  111. data/lib/flipper/test/shared_adapter_test.rb +77 -58
  112. data/lib/flipper/test_help.rb +43 -0
  113. data/lib/flipper/typecast.rb +37 -9
  114. data/lib/flipper/types/percentage.rb +1 -1
  115. data/lib/flipper/version.rb +11 -1
  116. data/lib/flipper.rb +61 -8
  117. data/lib/generators/flipper/setup_generator.rb +68 -0
  118. data/lib/generators/flipper/templates/initializer.rb +45 -0
  119. data/lib/generators/flipper/templates/update/migrations/01_create_flipper_tables.rb.erb +22 -0
  120. data/lib/generators/flipper/templates/update/migrations/02_change_flipper_gates_value_to_text.rb.erb +18 -0
  121. data/lib/generators/flipper/update_generator.rb +35 -0
  122. data/package-lock.json +41 -0
  123. data/package.json +10 -0
  124. data/spec/fixtures/environment.rb +1 -0
  125. data/spec/flipper/adapter_builder_spec.rb +72 -0
  126. data/spec/flipper/adapter_spec.rb +21 -0
  127. data/spec/flipper/adapters/actor_limit_spec.rb +75 -0
  128. data/spec/flipper/adapters/dual_write_spec.rb +15 -2
  129. data/spec/flipper/adapters/failover_spec.rb +12 -0
  130. data/spec/flipper/adapters/http/client_spec.rb +61 -0
  131. data/spec/flipper/adapters/http_spec.rb +375 -74
  132. data/spec/flipper/adapters/instrumented_spec.rb +1 -1
  133. data/spec/flipper/adapters/memoizable_spec.rb +21 -21
  134. data/spec/flipper/adapters/operation_logger_spec.rb +2 -2
  135. data/spec/flipper/adapters/poll_spec.rb +41 -0
  136. data/spec/flipper/adapters/read_only_spec.rb +32 -17
  137. data/spec/flipper/adapters/strict_spec.rb +122 -0
  138. data/spec/flipper/adapters/sync/feature_synchronizer_spec.rb +39 -0
  139. data/spec/flipper/adapters/sync/synchronizer_spec.rb +87 -0
  140. data/spec/flipper/adapters/sync_spec.rb +13 -0
  141. data/spec/flipper/cli_spec.rb +217 -0
  142. data/spec/flipper/cloud/configuration_spec.rb +251 -0
  143. data/spec/flipper/cloud/dsl_spec.rb +82 -0
  144. data/spec/flipper/cloud/message_verifier_spec.rb +104 -0
  145. data/spec/flipper/cloud/middleware_spec.rb +289 -0
  146. data/spec/flipper/cloud/migrate_spec.rb +160 -0
  147. data/spec/flipper/cloud/telemetry/backoff_policy_spec.rb +107 -0
  148. data/spec/flipper/cloud/telemetry/metric_spec.rb +87 -0
  149. data/spec/flipper/cloud/telemetry/metric_storage_spec.rb +58 -0
  150. data/spec/flipper/cloud/telemetry/submitter_spec.rb +145 -0
  151. data/spec/flipper/cloud/telemetry_spec.rb +208 -0
  152. data/spec/flipper/cloud_spec.rb +186 -0
  153. data/spec/flipper/configuration_spec.rb +17 -0
  154. data/spec/flipper/dsl_spec.rb +34 -73
  155. data/spec/flipper/engine_spec.rb +374 -0
  156. data/spec/flipper/exporters/json/v1_spec.rb +3 -3
  157. data/spec/flipper/expression/builder_spec.rb +248 -0
  158. data/spec/flipper/expression_spec.rb +188 -0
  159. data/spec/flipper/expressions/all_spec.rb +15 -0
  160. data/spec/flipper/expressions/any_spec.rb +15 -0
  161. data/spec/flipper/expressions/boolean_spec.rb +15 -0
  162. data/spec/flipper/expressions/equal_spec.rb +24 -0
  163. data/spec/flipper/expressions/greater_than_or_equal_to_spec.rb +28 -0
  164. data/spec/flipper/expressions/greater_than_spec.rb +28 -0
  165. data/spec/flipper/expressions/less_than_or_equal_to_spec.rb +28 -0
  166. data/spec/flipper/expressions/less_than_spec.rb +32 -0
  167. data/spec/flipper/expressions/not_equal_spec.rb +15 -0
  168. data/spec/flipper/expressions/now_spec.rb +11 -0
  169. data/spec/flipper/expressions/number_spec.rb +21 -0
  170. data/spec/flipper/expressions/percentage_of_actors_spec.rb +20 -0
  171. data/spec/flipper/expressions/percentage_spec.rb +15 -0
  172. data/spec/flipper/expressions/property_spec.rb +13 -0
  173. data/spec/flipper/expressions/random_spec.rb +9 -0
  174. data/spec/flipper/expressions/string_spec.rb +11 -0
  175. data/spec/flipper/expressions/time_spec.rb +29 -0
  176. data/spec/flipper/feature_spec.rb +380 -10
  177. data/spec/flipper/gate_values_spec.rb +2 -2
  178. data/spec/flipper/gates/expression_spec.rb +190 -0
  179. data/spec/flipper/identifier_spec.rb +4 -5
  180. data/spec/flipper/instrumentation/log_subscriber_spec.rb +10 -2
  181. data/spec/flipper/instrumentation/statsd_subscriber_spec.rb +16 -2
  182. data/spec/flipper/middleware/memoizer_spec.rb +107 -7
  183. data/spec/flipper/model/active_record_spec.rb +72 -0
  184. data/spec/flipper/poller_spec.rb +347 -4
  185. data/spec/flipper/serializers/gzip_spec.rb +13 -0
  186. data/spec/flipper/serializers/json_spec.rb +13 -0
  187. data/spec/flipper/typecast_spec.rb +43 -7
  188. data/spec/flipper/types/actor_spec.rb +18 -1
  189. data/spec/flipper_integration_spec.rb +247 -16
  190. data/spec/flipper_spec.rb +92 -29
  191. data/spec/spec_helper.rb +24 -17
  192. data/spec/support/actor_names.yml +1 -0
  193. data/spec/support/fail_on_output.rb +8 -0
  194. data/spec/support/fake_backoff_policy.rb +15 -0
  195. data/spec/support/spec_helpers.rb +34 -8
  196. data/test/adapters/actor_limit_test.rb +20 -0
  197. data/test_rails/generators/flipper/setup_generator_test.rb +69 -0
  198. data/test_rails/generators/flipper/update_generator_test.rb +96 -0
  199. data/test_rails/helper.rb +22 -2
  200. data/test_rails/system/test_help_test.rb +52 -0
  201. metadata +139 -75
  202. data/.tool-versions +0 -1
  203. data/lib/flipper/railtie.rb +0 -47
  204. data/spec/flipper/railtie_spec.rb +0 -109
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32360e70231522c5c5b41e5e9e889fd0d4df13c59ba223dd5416433d904954e5
4
- data.tar.gz: 5ec60d72b7b00d4d4bb5458d5746a4df4b89f3656fa9d4c7bfeddb27caae9c81
3
+ metadata.gz: c886665703939f49361ef42fb82e951383cb53bd99f2b1d902add786f6793da0
4
+ data.tar.gz: b7af2d5972cc409f075390871dc96b225e495133917e0c5024db297760252e73
5
5
  SHA512:
6
- metadata.gz: 12e61dc74aa548fe5b266c1d909e650190416d8350adfd12c608a84b16b5ede9cce4b753d74c5fed472506bfb0dd9a3e0e768bcb193f6f751408f9550513774e
7
- data.tar.gz: a2c0dc70d0fd50848fe9aedc2ed9f8f396dd51f5b604badc1477efd0249104e9fa7276d5161ac95e25992d8b1765eadd491e9a1a1d79640c6644e9fdd69442f2
6
+ metadata.gz: 338ccb2e6d9ddeaa6f6a1f20755e7799dcda40341c22831f8eda1f25df5f08bf4c61d67333e9bdebf94172107842b07e7ddb3ec7a54a2d057663f109e78f5a5d
7
+ data.tar.gz: bbfdb72c366e7fa334d8c3903b799366bed22d755cf6771c532d1335cccf7e9480c8a752c700a449f1ae837ae273be5b9c06ef58bc38b56570d96ef417edbded
@@ -0,0 +1 @@
1
+ github: flippercloud
@@ -1,53 +1,99 @@
1
1
  name: CI
2
- on: [push, pull_request]
2
+ on: [push]
3
+
3
4
  jobs:
4
5
  test:
5
6
  name: Test on ruby ${{ matrix.ruby }} and rails ${{ matrix.rails }}
6
7
  runs-on: ubuntu-latest
8
+ timeout-minutes: 20
7
9
  services:
8
10
  redis:
9
11
  image: redis
10
- ports: ['6379:6379']
12
+ ports: ["6379:6379"]
11
13
  options: >-
12
14
  --health-cmd "redis-cli ping"
13
15
  --health-interval 10s
14
16
  --health-timeout 5s
15
17
  --health-retries 5
18
+ memcached:
19
+ image: memcached
20
+ ports: ["11211:11211"]
21
+ postgres:
22
+ image: postgres:13
23
+ ports:
24
+ - 5432:5432
25
+ env:
26
+ POSTGRES_USER: postgres
27
+ POSTGRES_PASSWORD: postgres
28
+ options: >-
29
+ --health-cmd pg_isready
30
+ --health-interval 10s
31
+ --health-timeout 5s
32
+ --health-retries 5
16
33
  strategy:
34
+ fail-fast: false
17
35
  matrix:
18
- ruby: ['2.6', '2.7', '3.0', '3.1', '3.2']
19
- rails: ['5.2', '6.0.0', '6.1.0', '7.0.0']
36
+ ruby: ["2.6", "2.7", "3.0", "3.1", "3.2", "3.3"]
37
+ rails: ["5.2", "6.0.0", "6.1.0", "7.0.0", "7.1.0", "7.2.0", "8.0.0"]
20
38
  exclude:
39
+ - ruby: "2.6"
40
+ rails: "7.1.0"
21
41
  - ruby: "2.6"
22
42
  rails: "7.0.0"
43
+ - ruby: "2.6"
44
+ rails: "7.2.0"
45
+ - ruby: "2.6"
46
+ rails: "8.0.0"
47
+ - ruby: "2.7"
48
+ rails: "7.1.0"
49
+ - ruby: "2.7"
50
+ rails: "7.2.0"
51
+ - ruby: "2.7"
52
+ rails: "8.0.0"
23
53
  - ruby: "3.0"
24
54
  rails: "5.2"
55
+ - ruby: "3.0"
56
+ rails: "7.2.0"
57
+ - ruby: "3.0"
58
+ rails: "8.0.0"
25
59
  - ruby: "3.1"
26
60
  rails: "5.2"
27
61
  - ruby: "3.1"
28
62
  rails: "6.0.0"
63
+ - ruby: "3.1"
64
+ rails: "8.0.0"
29
65
  - ruby: "3.2"
30
66
  rails: "5.2"
31
67
  - ruby: "3.2"
32
68
  rails: "6.0.0"
33
69
  - ruby: "3.2"
34
70
  rails: "6.1.0"
71
+ - ruby: "3.3"
72
+ rails: "5.2"
73
+ - ruby: "3.3"
74
+ rails: "6.0.0"
75
+ - ruby: "3.3"
76
+ rails: "6.1.0"
35
77
  env:
36
- SQLITE3_VERSION: 1.4.1
78
+ SQLITE3_VERSION: ${{ matrix.rails == '8.0.0' && '2.1.0' || '1.4.1' }}
37
79
  REDIS_URL: redis://localhost:6379/0
38
80
  CI: true
39
81
  RAILS_VERSION: ${{ matrix.rails }}
82
+ MYSQL_USER: root
83
+ MYSQL_PASSWORD: root
84
+ POSTGRES_USER: postgres
85
+ POSTGRES_PASSWORD: postgres
40
86
  steps:
41
- - name: Setup memcached
42
- uses: KeisukeYamashita/memcached-actions@v1
87
+ - name: Set up MySQL
88
+ run: sudo /etc/init.d/mysql start
43
89
  - name: Start MongoDB
44
- uses: supercharge/mongodb-github-action@1.9.0
90
+ uses: supercharge/mongodb-github-action@1.12.1
45
91
  with:
46
92
  mongodb-version: 4.0
47
93
  - name: Check out repository code
48
- uses: actions/checkout@v3
94
+ uses: actions/checkout@v6
49
95
  - name: Do some action caching
50
- uses: actions/cache@v3
96
+ uses: actions/cache@v5
51
97
  with:
52
98
  path: vendor/bundle
53
99
  key: ${{ runner.os }}-gems-${{ matrix.ruby }}-${{ matrix.rails }}-${{ hashFiles('**/Gemfile.lock') }}
@@ -1,14 +1,15 @@
1
1
  name: Examples
2
- on: [push, pull_request]
2
+ on: [push]
3
3
  jobs:
4
4
  test:
5
- if: github.repository_owner == 'jnunemaker'
6
- name: Test on ruby ${{ matrix.ruby }} and rails ${{ matrix.rails }}
5
+ if: github.repository_owner == 'flippercloud'
6
+ name: Example on ruby ${{ matrix.ruby }} and rails ${{ matrix.rails }}
7
7
  runs-on: ubuntu-latest
8
+ timeout-minutes: 20
8
9
  services:
9
10
  redis:
10
11
  image: redis
11
- ports: ['6379:6379']
12
+ ports: ["6379:6379"]
12
13
  options: >-
13
14
  --health-cmd "redis-cli ping"
14
15
  --health-interval 10s
@@ -16,20 +17,49 @@ jobs:
16
17
  --health-retries 5
17
18
  strategy:
18
19
  matrix:
19
- ruby: ['2.6', '2.7', '3.0', '3.1']
20
- rails: ['5.2', '6.0.0', '6.1.0', '7.0.0']
20
+ ruby: ["2.6", "2.7", "3.0", "3.1", "3.2", "3.3"]
21
+ rails: ["5.2", "6.0.0", "6.1.0", "7.0.0", "7.1.0", "7.2.0", "8.0.0"]
21
22
  exclude:
23
+ - ruby: "2.6"
24
+ rails: "7.1.0"
22
25
  - ruby: "2.6"
23
26
  rails: "7.0.0"
27
+ - ruby: "2.6"
28
+ rails: "7.2.0"
29
+ - ruby: "2.6"
30
+ rails: "8.0.0"
31
+ - ruby: "2.7"
32
+ rails: "7.1.0"
33
+ - ruby: "2.7"
34
+ rails: "7.2.0"
35
+ - ruby: "2.7"
36
+ rails: "8.0.0"
24
37
  - ruby: "3.0"
25
38
  rails: "5.2"
39
+ - ruby: "3.0"
40
+ rails: "7.2.0"
41
+ - ruby: "3.0"
42
+ rails: "8.0.0"
26
43
  - ruby: "3.1"
27
44
  rails: "5.2"
28
45
  - ruby: "3.1"
29
46
  rails: "6.0.0"
30
-
47
+ - ruby: "3.1"
48
+ rails: "8.0.0"
49
+ - ruby: "3.2"
50
+ rails: "5.2"
51
+ - ruby: "3.2"
52
+ rails: "6.0.0"
53
+ - ruby: "3.2"
54
+ rails: "6.1.0"
55
+ - ruby: "3.3"
56
+ rails: "5.2"
57
+ - ruby: "3.3"
58
+ rails: "6.0.0"
59
+ - ruby: "3.3"
60
+ rails: "6.1.0"
31
61
  env:
32
- SQLITE3_VERSION: 1.4.1
62
+ SQLITE3_VERSION: ${{ matrix.rails == '8.0.0' && '2.1.0' || '1.4.1' }}
33
63
  REDIS_URL: redis://localhost:6379/0
34
64
  CI: true
35
65
  RAILS_VERSION: ${{ matrix.rails }}
@@ -37,13 +67,13 @@ jobs:
37
67
  - name: Setup memcached
38
68
  uses: KeisukeYamashita/memcached-actions@v1
39
69
  - name: Start MongoDB
40
- uses: supercharge/mongodb-github-action@1.9.0
70
+ uses: supercharge/mongodb-github-action@1.12.1
41
71
  with:
42
72
  mongodb-version: 4.0
43
73
  - name: Check out repository code
44
- uses: actions/checkout@v3
74
+ uses: actions/checkout@v6
45
75
  - name: Do some action caching
46
- uses: actions/cache@v3
76
+ uses: actions/cache@v5
47
77
  with:
48
78
  path: vendor/bundle
49
79
  key: ${{ runner.os }}-gems-${{ matrix.ruby }}-${{ matrix.rails }}-${{ hashFiles('**/Gemfile.lock') }}
@@ -59,4 +89,17 @@ jobs:
59
89
  - name: Run Examples with Rails ${{ matrix.rails }}
60
90
  env:
61
91
  FLIPPER_CLOUD_TOKEN: ${{ secrets.FLIPPER_CLOUD_TOKEN }}
92
+ FLIPPER_CLOUD_TOKEN_26_52: ${{ secrets.FLIPPER_CLOUD_TOKEN_26_52 }}
93
+ FLIPPER_CLOUD_TOKEN_26_60: ${{ secrets.FLIPPER_CLOUD_TOKEN_26_60 }}
94
+ FLIPPER_CLOUD_TOKEN_26_61: ${{ secrets.FLIPPER_CLOUD_TOKEN_26_61 }}
95
+ FLIPPER_CLOUD_TOKEN_27_52: ${{ secrets.FLIPPER_CLOUD_TOKEN_27_52 }}
96
+ FLIPPER_CLOUD_TOKEN_27_60: ${{ secrets.FLIPPER_CLOUD_TOKEN_27_60 }}
97
+ FLIPPER_CLOUD_TOKEN_27_61: ${{ secrets.FLIPPER_CLOUD_TOKEN_27_61 }}
98
+ FLIPPER_CLOUD_TOKEN_27_70: ${{ secrets.FLIPPER_CLOUD_TOKEN_27_70 }}
99
+ FLIPPER_CLOUD_TOKEN_30_60: ${{ secrets.FLIPPER_CLOUD_TOKEN_30_60 }}
100
+ FLIPPER_CLOUD_TOKEN_30_61: ${{ secrets.FLIPPER_CLOUD_TOKEN_30_61 }}
101
+ FLIPPER_CLOUD_TOKEN_30_70: ${{ secrets.FLIPPER_CLOUD_TOKEN_30_70 }}
102
+ FLIPPER_CLOUD_TOKEN_31_61: ${{ secrets.FLIPPER_CLOUD_TOKEN_31_61 }}
103
+ FLIPPER_CLOUD_TOKEN_31_70: ${{ secrets.FLIPPER_CLOUD_TOKEN_31_70 }}
104
+ RAILS_VERSION: ${{ matrix.rails }}
62
105
  run: script/examples
@@ -0,0 +1,54 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ jobs:
9
+ release:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ id-token: write # RubyGems trusted publishing (OIDC)
13
+ contents: write # Create GitHub Releases
14
+ steps:
15
+ - uses: actions/checkout@v6
16
+
17
+ - uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: '3.3'
20
+
21
+ - name: Build all gems
22
+ run: |
23
+ for gemspec in *.gemspec; do
24
+ gem build "$gemspec"
25
+ done
26
+ mkdir -p pkg
27
+ mv *.gem pkg/
28
+ echo "Built gems:"
29
+ ls -la pkg/
30
+
31
+ - name: Configure RubyGems credentials
32
+ uses: rubygems/configure-rubygems-credentials@v1.0.0
33
+
34
+ - name: Publish all gems
35
+ run: |
36
+ # Push core gem first since other gems depend on it
37
+ echo "Pushing flipper core gem..."
38
+ gem push pkg/flipper-[0-9]*.gem || echo "Core gem already pushed, continuing..."
39
+
40
+ for gem_file in pkg/flipper-*.gem; do
41
+ basename="$(basename "$gem_file")"
42
+ if [[ "$basename" =~ ^flipper-[0-9] ]]; then
43
+ continue
44
+ fi
45
+ echo "Pushing $basename..."
46
+ gem push "$gem_file" || echo "Failed to push $basename, continuing..."
47
+ done
48
+
49
+ - name: Create draft GitHub Release
50
+ uses: softprops/action-gh-release@v2
51
+ with:
52
+ draft: true
53
+ generate_release_notes: true
54
+ files: pkg/*.gem
@@ -0,0 +1,4 @@
1
+ {
2
+ "setup": ["script/conductor-setup"],
3
+ "teardown": []
4
+ }
data/CLAUDE.md ADDED
@@ -0,0 +1,93 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Development Commands
6
+
7
+ ### Testing
8
+ - `bundle exec rake` - Run all tests (RSpec, Minitest, and Rails tests)
9
+ - `bundle exec rspec` - Run RSpec tests only
10
+ - `bundle exec rake spec:ui` - Run UI-specific specs
11
+ - `bundle exec rake test` - Run Minitest tests only
12
+ - `bundle exec rake test_rails` - Run Rails generator tests
13
+ - `script/test` - Bootstrap and run tests across multiple Rails versions (5.0-8.0)
14
+
15
+ ### Development Setup
16
+ - `script/bootstrap` - Bundle install dependencies and setup binstubs
17
+ - `script/console` - Start interactive console with Flipper loaded (uses Pry)
18
+ - `script/server` - Start local UI server on port 9999 for testing web interface
19
+
20
+ ### Releasing
21
+ 1. Bump version in `lib/flipper/version.rb`, commit, and push to main
22
+ 2. Tag and push: `git tag v1.x.x && git push origin v1.x.x`
23
+ 3. GitHub Actions (`.github/workflows/release.yml`) builds and publishes all 12 gems via RubyGems trusted publishing, then creates a draft GitHub Release
24
+ 4. Edit and publish the draft release at https://github.com/flippercloud/flipper/releases
25
+
26
+ - `bundle exec rake build` - Build all gems locally into pkg/ directory
27
+ - `script/release` - Manual fallback for local releases (prompts for OTP)
28
+
29
+ **After releasing**, purge the cached release URLs on flippercloud.io:
30
+ - `/release`
31
+ - `/release.json`
32
+
33
+ ## Architecture Overview
34
+
35
+ Flipper is a feature flag library for Ruby with a modular adapter-based architecture:
36
+
37
+ ### Core Components
38
+
39
+ **DSL Layer** (`lib/flipper/dsl.rb`):
40
+ - Main interface for feature flag operations
41
+ - Delegates to Feature instances
42
+ - Handles memoization and instrumentation
43
+ - Thread-safe instance management
44
+
45
+ **Feature** (`lib/flipper/feature.rb`):
46
+ - Represents individual feature flags
47
+ - Manages enable/disable operations through gates
48
+ - Handles instrumentation events
49
+ - Works with adapters for persistence
50
+
51
+ **Adapters** (`lib/flipper/adapters/`):
52
+ - Pluggable storage backends (Redis, ActiveRecord, Memory, etc.)
53
+ - Common interface for all storage implementations
54
+ - Support for caching, failover, and synchronization patterns
55
+
56
+ **Gates** (`lib/flipper/gates/`):
57
+ - Different targeting mechanisms:
58
+ - Boolean (on/off for everyone)
59
+ - Actor (specific users/entities)
60
+ - Group (predefined user groups)
61
+ - Percentage of Actors (rollout to X% of users)
62
+ - Percentage of Time (probabilistic enabling)
63
+ - Expression (complex conditional logic)
64
+
65
+ ### Multi-Gem Structure
66
+
67
+ The project is structured as multiple gems:
68
+ - `flipper` - Core library
69
+ - `flipper-ui` - Web interface
70
+ - `flipper-api` - REST API
71
+ - `flipper-cloud` - Cloud service integration
72
+ - `flipper-*` - Various adapter gems (redis, active_record, mongo, etc.)
73
+
74
+ ### Key Patterns
75
+
76
+ **Configuration**: Global configuration through `Flipper.configure` with per-thread instances
77
+ **Instrumentation**: Built-in event system for monitoring and debugging
78
+ **Memoization**: Automatic caching of feature checks within request/thread scope
79
+ **Type Safety**: Strong typing system for actors, percentages, and other values
80
+
81
+ ### Serialization and HTTP
82
+
83
+ Use `Flipper::Typecast` for JSON and gzip serialization instead of calling `JSON.generate`/`JSON.parse` or `Zlib` directly:
84
+ - `Typecast.to_json(hash)` / `Typecast.from_json(string)` for JSON serialization
85
+ - `Typecast.to_gzip(string)` / `Typecast.from_gzip(string)` for gzip compression
86
+
87
+ For outbound HTTP requests, use `Flipper::Adapters::Http::Client` instead of raw `Net::HTTP`. It provides timeouts, retries (`max_retries`), SSL verification, and diagnostic headers (user-agent, client-language, client-platform, etc.). See `lib/flipper/cloud/migrate.rb` for an example.
88
+
89
+ ### Testing
90
+
91
+ Uses both RSpec (currently preferred for new tests) and Minitest. Shared adapter specs ensure consistency across all storage backends. Extensive testing across multiple Rails versions (5.0-8.0).
92
+
93
+ `Flipper.configuration` is reset to nil before each spec (in `spec/spec_helper.rb`), but `Flipper::UI.configuration` is **not** globally reset. When modifying UI config in tests, set the value in `before` and reset it in `after` to match the existing pattern throughout the spec suite.