rox-rollout 4.7.1 → 5.0.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 (116) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +34 -13
  3. data/.editorconfig +12 -0
  4. data/.github/workflows/ruby.yml +20 -0
  5. data/.rubocop.yml +17 -0
  6. data/Gemfile +2 -2
  7. data/README.md +32 -0
  8. data/Rakefile +12 -9
  9. data/bin/console +3 -4
  10. data/e2e/container.rb +11 -14
  11. data/e2e/custom_props.rb +9 -9
  12. data/e2e/rox_e2e_test.rb +17 -19
  13. data/e2e/test_vars.rb +3 -6
  14. data/e2e-server/run_server.sh +12 -0
  15. data/e2e-server/server.rb +158 -0
  16. data/example/local.rb +40 -0
  17. data/lib/rox/core/analytics.rb +18 -0
  18. data/lib/rox/core/client/buid.rb +8 -8
  19. data/lib/rox/core/client/device_properties.rb +7 -1
  20. data/lib/rox/core/client/dynamic_api.rb +53 -15
  21. data/lib/rox/core/client/internal_flags.rb +14 -2
  22. data/lib/rox/core/client/sdk_settings.rb +1 -1
  23. data/lib/rox/core/configuration/configuration.rb +1 -1
  24. data/lib/rox/core/configuration/configuration_fetched_args.rb +2 -2
  25. data/lib/rox/core/configuration/configuration_fetched_invoker.rb +8 -3
  26. data/lib/rox/core/configuration/configuration_parser.rb +38 -37
  27. data/lib/rox/core/configuration/fetcher_error.rb +1 -1
  28. data/lib/rox/core/configuration/fetcher_status.rb +1 -1
  29. data/lib/rox/core/configuration/models/experiment_model.rb +1 -1
  30. data/lib/rox/core/configuration/models/target_group_model.rb +1 -1
  31. data/lib/rox/core/consts/build.rb +2 -2
  32. data/lib/rox/core/consts/environment.rb +10 -8
  33. data/lib/rox/core/consts/property_type.rb +16 -17
  34. data/lib/rox/core/context/merged_context.rb +2 -1
  35. data/lib/rox/core/core.rb +89 -38
  36. data/lib/rox/core/entities/default_flag_values.rb +10 -0
  37. data/lib/rox/core/entities/flag.rb +22 -7
  38. data/lib/rox/core/entities/flag_setter.rb +6 -6
  39. data/lib/rox/core/entities/rox_double.rb +11 -0
  40. data/lib/rox/core/entities/rox_int.rb +11 -0
  41. data/lib/rox/core/entities/{variant.rb → rox_string.rb} +20 -13
  42. data/lib/rox/core/error_handling/exception_trigger.rb +10 -0
  43. data/lib/rox/core/error_handling/userspace_handler_exception.rb +12 -0
  44. data/lib/rox/core/error_handling/userspace_unhandled_error_invoker.rb +41 -0
  45. data/lib/rox/core/impression/impression_args.rb +2 -2
  46. data/lib/rox/core/impression/impression_invoker.rb +41 -7
  47. data/lib/rox/core/impression/models/experiment.rb +1 -1
  48. data/lib/rox/core/impression/models/reporting_value.rb +10 -2
  49. data/lib/rox/core/logging/logging.rb +3 -3
  50. data/lib/rox/core/logging/no_op_logger.rb +1 -1
  51. data/lib/rox/core/network/configuration_fetcher.rb +2 -2
  52. data/lib/rox/core/network/configuration_fetcher_roxy.rb +2 -2
  53. data/lib/rox/core/network/configuration_fetcher_self_managed.rb +30 -0
  54. data/lib/rox/core/network/configuration_source.rb +1 -1
  55. data/lib/rox/core/network/request.rb +1 -1
  56. data/lib/rox/core/network/request_configuration_builder.rb +5 -5
  57. data/lib/rox/core/network/request_data.rb +1 -1
  58. data/lib/rox/core/network/response.rb +6 -8
  59. data/lib/rox/core/network/state_sender.rb +63 -19
  60. data/lib/rox/core/notifications/notification_listener.rb +4 -4
  61. data/lib/rox/core/properties/custom_property.rb +1 -1
  62. data/lib/rox/core/properties/custom_property_type.rb +1 -1
  63. data/lib/rox/core/properties/device_property.rb +2 -2
  64. data/lib/rox/core/properties/property_factory.rb +132 -0
  65. data/lib/rox/core/register/registerer.rb +13 -12
  66. data/lib/rox/core/reporting/error_reporter.rb +14 -13
  67. data/lib/rox/core/repositories/experiment_repository.rb +2 -4
  68. data/lib/rox/core/repositories/flag_repository.rb +7 -7
  69. data/lib/rox/core/repositories/roxx/experiments_extensions.rb +8 -8
  70. data/lib/rox/core/repositories/roxx/properties_extensions.rb +32 -7
  71. data/lib/rox/core/repositories/target_group_repository.rb +2 -4
  72. data/lib/rox/core/roxx/evaluation_result.rb +2 -0
  73. data/lib/rox/core/roxx/node.rb +1 -1
  74. data/lib/rox/core/roxx/parser.rb +35 -21
  75. data/lib/rox/core/roxx/regular_expression_extensions.rb +6 -3
  76. data/lib/rox/core/roxx/string_tokenizer.rb +3 -1
  77. data/lib/rox/core/roxx/symbols.rb +1 -1
  78. data/lib/rox/core/roxx/token_type.rb +1 -1
  79. data/lib/rox/core/roxx/tokenized_expression.rb +16 -12
  80. data/lib/rox/core/roxx/value_compare_extensions.rb +49 -29
  81. data/lib/rox/core/security/signature_verifier.rb +3 -3
  82. data/lib/rox/core/security/signature_verifier_mock.rb +12 -0
  83. data/lib/rox/core/utils/type_utils.rb +1 -1
  84. data/lib/rox/server/client/server_properties.rb +1 -1
  85. data/lib/rox/server/flags/normalize_flag_type.rb +25 -0
  86. data/lib/rox/server/flags/rox_double.rb +8 -0
  87. data/lib/rox/server/flags/rox_flag.rb +1 -1
  88. data/lib/rox/server/flags/rox_int.rb +8 -0
  89. data/lib/rox/server/flags/rox_string.rb +8 -0
  90. data/lib/rox/server/flags/server_entities_provider.rb +14 -4
  91. data/lib/rox/server/logging/server_logger.rb +2 -2
  92. data/lib/rox/server/rox_options.rb +39 -8
  93. data/lib/rox/server/rox_server.rb +84 -59
  94. data/lib/rox/version.rb +1 -1
  95. data/rox.gemspec +11 -9
  96. metadata +62 -33
  97. data/CODEOWNERS +0 -1
  98. data/README_DEVELOP.md +0 -25
  99. data/_archive/.document +0 -5
  100. data/_archive/.rspec +0 -1
  101. data/_archive/Gemfile +0 -15
  102. data/_archive/Gemfile.lock +0 -87
  103. data/_archive/README.md +0 -32
  104. data/_archive/README.rdoc +0 -19
  105. data/_archive/Rakefile +0 -50
  106. data/_archive/lib/expr_function_definition.rb +0 -52
  107. data/_archive/lib/function_definition.rb +0 -48
  108. data/_archive/lib/function_token.rb +0 -12
  109. data/_archive/lib/object_extends.rb +0 -12
  110. data/_archive/lib/ruby_interpreter.rb +0 -292
  111. data/_archive/lib/stack.rb +0 -48
  112. data/_archive/lib/string_extends.rb +0 -14
  113. data/_archive/spec/ruby_interpreter_spec.rb +0 -203
  114. data/_archive/spec/spec_helper.rb +0 -30
  115. data/_archive/spec/stack_spec.rb +0 -77
  116. data/lib/rox/server/flags/rox_variant.rb +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f469e98c7755e93dd933348040c9427b948dfc74b291909edf2f95f29782dc04
4
- data.tar.gz: 33fb5b1fbba476ed8c8c3782bdd37df0ca8c9e162b86c68b50e158cace43681e
3
+ metadata.gz: acfdbd9f2a75d947284c96ac406567af69f9eb61623d079664c0de6b0d26d338
4
+ data.tar.gz: db992ff6df1b786b96ba6fdd2625e4037e32e75b272fc7ad8ddf8ef9c170dacf
5
5
  SHA512:
6
- metadata.gz: 1e6586963cd6fad7a99c83a547ace73534779d4fa40a325a9dfd2027b11a1f5b807665f9058130282a79a3a0aec36bcbc165f3d41f9e33301405d74083a9aac5
7
- data.tar.gz: 7383631322c0186f6567196975d28688afb4b0b8b4c911e9f79a25ef4b2ee82bcc7bc007ccf9c612e3d441158bcf3c62189506bda667e970780113790a738790
6
+ metadata.gz: 0aba475fed416f669ba8286b7c1144e04e9171471c1bcf35022a3451d4f6869648a85d80f831f1e363d23a09971d045ada0e3c6579a0aab30169000299f35cba
7
+ data.tar.gz: 6366f4efca140a0f5695accd0918ac1ece1d94ba7fea64ff28d45de870f93d7141ba3009eb1379c5986067840e0af1a282a56c6b9274a5b34468a4cd040395d5
data/.circleci/config.yml CHANGED
@@ -1,14 +1,6 @@
1
- version: 2
2
- workflows:
3
- version: 2
4
- test:
5
- jobs:
6
- - test-2.6
7
- - test-2.5
8
- - test-2.4
9
- - test-2.3
1
+ version: 2.1
10
2
  jobs:
11
- test-2.6: &test-template
3
+ test_2-6: &test-template
12
4
  docker:
13
5
  - image: circleci/ruby:2.6.4
14
6
 
@@ -38,15 +30,44 @@ jobs:
38
30
  command: |
39
31
  bundle exec rake e2e
40
32
 
41
- test-2.5:
33
+ test_2-5:
42
34
  <<: *test-template
43
35
  docker:
44
36
  - image: circleci/ruby:2.5.6
45
- test-2.4:
37
+ test_2-4:
46
38
  <<: *test-template
47
39
  docker:
48
40
  - image: circleci/ruby:2.4.7
49
- test-2.3:
41
+ test_2-3:
50
42
  <<: *test-template
51
43
  docker:
52
44
  - image: circleci/ruby:2.3.8
45
+
46
+ sdk-integration-test:
47
+ <<: *test-template
48
+ steps:
49
+ - run:
50
+ name: trigger sdk integration test workflow
51
+ command: >-
52
+ curl -X POST https://circleci.com/api/v2/project/gh/rollout/sdk-integration-tests/pipeline
53
+ --header 'Content-Type: application/json'
54
+ --header 'Accept: application/json'
55
+ --header 'x-attribution-login: rox-ruby'
56
+ --header 'x-attribution-actor-id: rox-ruby'
57
+ --header 'Circle-Token: '$CircleApiToken
58
+ --data '{"parameters": {"sdk_triggered_run": true, "repo_name": "'$CIRCLE_PROJECT_REPONAME'", "repo_owner": "'$CIRCLE_PROJECT_USERNAME'", "sha": "'$CIRCLE_SHA1'" }}'
59
+
60
+ workflows:
61
+ version: 2
62
+ test:
63
+ jobs:
64
+ - test_2-6
65
+ - test_2-5
66
+ - test_2-4
67
+ - test_2-3
68
+ - sdk-integration-test:
69
+ requires:
70
+ - test_2-6
71
+ - test_2-5
72
+ - test_2-4
73
+ - test_2-3
data/.editorconfig ADDED
@@ -0,0 +1,12 @@
1
+ # EditorConfig is awesome: https://EditorConfig.org
2
+
3
+ # top-most EditorConfig file
4
+ root = true
5
+
6
+ [*]
7
+ indent_style = space
8
+ indent_size = 2
9
+ end_of_line = lf
10
+ charset = utf-8
11
+ trim_trailing_whitespace = true
12
+ insert_final_newline = true
@@ -0,0 +1,20 @@
1
+ name: Ruby
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ test:
7
+ strategy:
8
+ fail-fast: false
9
+ matrix:
10
+ os: [ubuntu-latest]
11
+ ruby: [2.4, 2.5, 2.6, 2.7, 3.0]
12
+ runs-on: ${{ matrix.os }}
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: ${{ matrix.ruby }}
18
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
19
+ - run: bundle exec rake test
20
+ - run: bundle exec rake e2e
data/.rubocop.yml ADDED
@@ -0,0 +1,17 @@
1
+ AllCops:
2
+ NewCops: enable
3
+
4
+ Metrics/BlockLength:
5
+ Exclude:
6
+ - test/**/*.rb
7
+ - e2e/**/*.rb
8
+ - e2e-server/**/*.rb
9
+
10
+ Metrics/ClassLength:
11
+ Exclude:
12
+ - test/**/*.rb
13
+
14
+ Style/FrozenStringLiteralComment:
15
+ Enabled: false
16
+ Style/IfUnlessModifier:
17
+ Enabled: false
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in rox.gemspec
6
6
  gemspec
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # ROX SDK for Ruby
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/rox-rollout.svg)](https://badge.fury.io/rb/rox-rollout)
4
+
5
+ Ruby supported versions: 2.3.x, 2.4.x, 2.5.x, 2.6.x
6
+
7
+ ## Run tests
8
+
9
+ Unit tests (folder tests)
10
+ ```bash
11
+ bundle exec rake test
12
+ ```
13
+
14
+ E2E tests (folder e2e)
15
+ ```bash
16
+ bundle exec rake e2e
17
+ ```
18
+
19
+ ## Run linter (rubocop)
20
+
21
+ ```bash
22
+ bundle exec rake lint
23
+ ```
24
+
25
+ ## Publish new version
26
+
27
+ 1. Increment version in ```lib/rox/version.rb```, open a PR and wait for CI to complete workflows
28
+ 2. Merge to master, wait for CI to complete workflows
29
+ 2. Generate the gem package: ```gem build rox.gemspec```
30
+ 3. Install gem locally, and test with a sample project
31
+ 4. Upload to RubyGems: ```gem push rox-rollout-VERSION.gem```
32
+ 5. Celebrate! 🎉
data/Rakefile CHANGED
@@ -1,16 +1,19 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+ require 'rubocop/rake_task'
3
4
 
4
5
  Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
6
+ t.libs << 'test'
7
+ t.libs << 'lib'
8
+ t.test_files = FileList['test/**/*_test.rb']
8
9
  end
9
10
 
10
11
  Rake::TestTask.new(:e2e) do |t|
11
- t.libs << "lib"
12
- t.libs << "e2e"
13
- t.test_files = FileList["e2e/**/*_test.rb"]
12
+ t.libs << 'lib'
13
+ t.libs << 'e2e'
14
+ t.test_files = FileList['e2e/**/*_test.rb']
14
15
  end
15
16
 
16
- task :default => :test
17
+ RuboCop::RakeTask.new(:lint)
18
+
19
+ task default: :test
data/bin/console CHANGED
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "rox"
2
+ require 'bundler/setup'
3
+ require 'rox'
5
4
 
6
5
  # You can add fixtures and/or initialization code here to make experimenting
7
6
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +9,5 @@ require "rox"
10
9
  # require "pry"
11
10
  # Pry.start
12
11
 
13
- require "irb"
12
+ require 'irb'
14
13
  IRB.start(__FILE__)
data/e2e/container.rb CHANGED
@@ -1,15 +1,13 @@
1
1
  require 'rox/server/flags/rox_flag'
2
- require 'rox/server/flags/rox_variant'
2
+ require 'rox/server/flags/rox_string'
3
3
 
4
4
  module E2E
5
5
  class Container
6
- attr_accessor :simple_flag, :simple_flag_overwritten
7
- attr_accessor :flag_for_impression, :flag_for_impression_with_experiment_and_context
8
- attr_accessor :flag_custom_properties
9
- attr_accessor :flag_target_groups_all, :flag_target_groups_any, :flag_target_groups_none
10
- attr_accessor :variant_with_context
11
- attr_accessor :variant, :variant_overwritten
12
- attr_accessor :flag_for_dependency, :flag_colors_for_dependency, :flag_dependent, :flag_color_dependent_with_context
6
+ attr_accessor :simple_flag, :simple_flag_overwritten, :flag_for_impression,
7
+ :flag_for_impression_with_experiment_and_context, :flag_custom_properties,
8
+ :flag_target_groups_all, :flag_target_groups_any, :flag_target_groups_none,
9
+ :variant_with_context, :variant, :variant_overwritten, :flag_for_dependency,
10
+ :flag_dependent, :flag_color_dependent_with_context
13
11
 
14
12
  def initialize
15
13
  @simple_flag = Rox::Server::RoxFlag.new(true)
@@ -24,15 +22,14 @@ module E2E
24
22
  @flag_target_groups_any = Rox::Server::RoxFlag.new
25
23
  @flag_target_groups_none = Rox::Server::RoxFlag.new
26
24
 
27
- @variant_with_context = Rox::Server::RoxVariant.new('red', ['red', 'blue', 'green'])
25
+ @variant_with_context = Rox::Server::RoxString.new('red', %w[red blue green])
28
26
 
29
- @variant = Rox::Server::RoxVariant.new('red', ['red', 'blue', 'green'])
30
- @variant_overwritten = Rox::Server::RoxVariant.new('red', ['red', 'blue', 'green'])
27
+ @variant = Rox::Server::RoxString.new('red', %w[red blue green])
28
+ @variant_overwritten = Rox::Server::RoxString.new('red', %w[red blue green])
31
29
 
32
30
  @flag_for_dependency = Rox::Server::RoxFlag.new(false)
33
- @flag_colors_for_dependency = Rox::Server::RoxVariant.new('White', ['White', 'Blue', 'Green', 'Yellow'])
34
31
  @flag_dependent = Rox::Server::RoxFlag.new(false)
35
- @flag_color_dependent_with_context = Rox::Server::RoxVariant.new('White', ['White', 'Blue', 'Green', 'Yellow'])
32
+ @flag_color_dependent_with_context = Rox::Server::RoxString.new('White', %w[White Blue Green Yellow])
36
33
  end
37
34
  end
38
- end
35
+ end
data/e2e/custom_props.rb CHANGED
@@ -2,31 +2,31 @@ module E2E
2
2
  class CustomProps
3
3
  def self.create_custom_props
4
4
  Rox::Server::RoxServer.set_custom_string_property('string_prop1', 'Hello')
5
- Rox::Server::RoxServer.set_custom_string_property('string_prop2') do |context|
5
+ Rox::Server::RoxServer.set_custom_string_property('string_prop2') do |_context|
6
6
  TestVars.is_computed_string_prop_called = true
7
7
  'World'
8
8
  end
9
9
 
10
10
  Rox::Server::RoxServer.set_custom_boolean_property('bool_prop1', true)
11
- Rox::Server::RoxServer.set_custom_boolean_property('bool_prop2') do |context|
11
+ Rox::Server::RoxServer.set_custom_boolean_property('bool_prop2') do |_context|
12
12
  TestVars.is_computed_boolean_prop_called = true
13
13
  false
14
14
  end
15
15
 
16
16
  Rox::Server::RoxServer.set_custom_int_property('int_prop1', 6)
17
- Rox::Server::RoxServer.set_custom_int_property('int_prop2') do |context|
17
+ Rox::Server::RoxServer.set_custom_int_property('int_prop2') do |_context|
18
18
  TestVars.is_computed_int_prop_called = true
19
19
  28
20
20
  end
21
21
 
22
22
  Rox::Server::RoxServer.set_custom_float_property('float_prop1', 3.14)
23
- Rox::Server::RoxServer.set_custom_float_property('float_prop2') do |context|
23
+ Rox::Server::RoxServer.set_custom_float_property('float_prop2') do |_context|
24
24
  TestVars.is_computed_float_prop_called = true
25
25
  1.618
26
26
  end
27
27
 
28
28
  Rox::Server::RoxServer.set_custom_semver_property('smvr_prop1', '9.11.2001')
29
- Rox::Server::RoxServer.set_custom_semver_property('smvr_prop2') do |context|
29
+ Rox::Server::RoxServer.set_custom_semver_property('smvr_prop2') do |_context|
30
30
  TestVars.is_computed_semver_prop_called = true
31
31
  '20.7.1969'
32
32
  end
@@ -35,15 +35,15 @@ module E2E
35
35
  context['isDuckAndCover']
36
36
  end
37
37
 
38
- Rox::Server::RoxServer.set_custom_boolean_property('bool_prop_target_group_operand1') do |context|
38
+ Rox::Server::RoxServer.set_custom_boolean_property('bool_prop_target_group_operand1') do |_context|
39
39
  TestVars.target_group1
40
40
  end
41
41
 
42
- Rox::Server::RoxServer.set_custom_boolean_property('bool_prop_target_group_operand2') do |context|
42
+ Rox::Server::RoxServer.set_custom_boolean_property('bool_prop_target_group_operand2') do |_context|
43
43
  TestVars.target_group2
44
44
  end
45
45
 
46
- Rox::Server::RoxServer.set_custom_boolean_property('bool_prop_target_group_for_dependency') do |context|
46
+ Rox::Server::RoxServer.set_custom_boolean_property('bool_prop_target_group_for_dependency') do |_context|
47
47
  TestVars.is_prop_for_target_group_for_dependency
48
48
  end
49
49
 
@@ -52,4 +52,4 @@ module E2E
52
52
  end
53
53
  end
54
54
  end
55
- end
55
+ end
data/e2e/rox_e2e_test.rb CHANGED
@@ -1,4 +1,4 @@
1
- require "minitest/autorun"
1
+ require 'minitest/autorun'
2
2
  require 'rox/server/rox_options'
3
3
  require 'rox/server/rox_server'
4
4
  require_relative 'container'
@@ -7,7 +7,7 @@ require_relative 'test_vars'
7
7
 
8
8
  module E2E
9
9
  class Logger
10
- def debug(message, ex = nil)
10
+ def debug(message, _ex = nil)
11
11
  puts 'Before Rox.Setup', message
12
12
  end
13
13
 
@@ -15,7 +15,7 @@ module E2E
15
15
  puts 'Before Rox.Setup', message, ex
16
16
  end
17
17
 
18
- def warn(message, ex = nil)
18
+ def warn(message, _ex = nil)
19
19
  puts 'Before Rox.Setup', message
20
20
  end
21
21
  end
@@ -30,8 +30,8 @@ module E2E
30
30
  end
31
31
 
32
32
  impression_handler = proc do |e|
33
- if !e.nil? && !e.reporting_value.nil?
34
- TestVars.is_impression_raised = true if e.reporting_value.name == 'flag_for_impression'
33
+ if !e.nil? && !e.reporting_value.nil? && (e.reporting_value.name == 'flag_for_impression')
34
+ TestVars.is_impression_raised = true
35
35
  end
36
36
  TestVars.impression_returned_args = e
37
37
  end
@@ -44,7 +44,7 @@ module E2E
44
44
  )
45
45
 
46
46
  @@container = Container.new
47
- Rox::Server::RoxServer.register('', @@container)
47
+ Rox::Server::RoxServer.register(@@container)
48
48
  CustomProps.create_custom_props
49
49
  Rox::Server::RoxServer.setup('5b82864ebc3aec37aff1fdd5', option).join
50
50
 
@@ -56,7 +56,7 @@ module E2E
56
56
  assert_equal false, @@container.simple_flag_overwritten.enabled?
57
57
  end
58
58
 
59
- def test_variant
59
+ def test_string
60
60
  assert_equal 'red', @@container.variant.value
61
61
  end
62
62
 
@@ -87,9 +87,9 @@ module E2E
87
87
  end
88
88
  end
89
89
 
90
- def test_variant_with_context
91
- some_positive_context = {'isDuckAndCover' => true}
92
- some_negative_context = {'isDuckAndCover' => false}
90
+ def test_string_with_context
91
+ some_positive_context = { 'isDuckAndCover' => true }
92
+ some_negative_context = { 'isDuckAndCover' => false }
93
93
 
94
94
  assert_equal 'red', @@container.variant_with_context.value
95
95
 
@@ -121,18 +121,16 @@ module E2E
121
121
  assert_equal true, TestVars.is_impression_raised
122
122
  TestVars.is_impression_raised = false
123
123
 
124
- context = {'var' => 'val'}
124
+ context = { 'var' => 'val' }
125
125
  flag_impression_value = @@container.flag_for_impression_with_experiment_and_context.enabled?(context)
126
126
  refute_nil TestVars.impression_returned_args
127
127
  refute_nil TestVars.impression_returned_args.reporting_value
128
- assert_equal 'true', TestVars.impression_returned_args.reporting_value.value
128
+ assert_equal true, TestVars.impression_returned_args.reporting_value.value
129
129
  assert_equal true, flag_impression_value
130
- assert_equal 'flag_for_impression_with_experiment_and_context', TestVars.impression_returned_args.reporting_value.name
130
+ assert_equal 'flag_for_impression_with_experiment_and_context',
131
+ TestVars.impression_returned_args.reporting_value.name
131
132
 
132
133
  refute_nil TestVars.impression_returned_args
133
- refute_nil TestVars.impression_returned_args.experiment
134
- assert_equal '5b8f85ecbc3aec37aff20841', TestVars.impression_returned_args.experiment.identifier
135
- assert_equal 'flag for impression with experiment and context', TestVars.impression_returned_args.experiment.name
136
134
 
137
135
  assert_equal 'val', TestVars.impression_returned_args.context['var']
138
136
  end
@@ -147,9 +145,9 @@ module E2E
147
145
  assert_equal false, @@container.flag_for_dependency.enabled?
148
146
  end
149
147
 
150
- def test_variant_dependency_with_context
151
- some_positive_context = {'isDuckAndCover' => true}
152
- some_negative_context = {'isDuckAndCover' => false}
148
+ def test_string_dependency_with_context
149
+ some_positive_context = { 'isDuckAndCover' => true }
150
+ some_negative_context = { 'isDuckAndCover' => false }
153
151
 
154
152
  assert_equal 'White', @@container.flag_color_dependent_with_context.value
155
153
  assert_equal 'White', @@container.flag_color_dependent_with_context.value(some_negative_context)
data/e2e/test_vars.rb CHANGED
@@ -1,11 +1,8 @@
1
1
  module E2E
2
2
  module TestVars
3
3
  class << self
4
- attr_accessor :is_computed_boolean_prop_called, :is_computed_string_prop_called, :is_computed_int_prop_called, :is_computed_float_prop_called, :is_computed_semver_prop_called
5
- attr_accessor :target_group1, :target_group2
6
- attr_accessor :is_impression_raised, :is_prop_for_target_group_for_dependency
7
-
8
- attr_accessor :configuration_fetched_count, :impression_returned_args
4
+ attr_accessor :is_computed_boolean_prop_called, :is_computed_string_prop_called, :is_computed_int_prop_called,
5
+ :is_computed_float_prop_called, :is_computed_semver_prop_called, :target_group1, :target_group2, :is_impression_raised, :is_prop_for_target_group_for_dependency, :configuration_fetched_count, :impression_returned_args
9
6
  end
10
7
 
11
8
  @is_computed_boolean_prop_called = false
@@ -21,4 +18,4 @@ module E2E
21
18
  @configuration_fetched_count = 0
22
19
  @impression_returned_args = nil
23
20
  end
24
- end
21
+ end
@@ -0,0 +1,12 @@
1
+ #!/bin/bash -x
2
+ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
3
+ cd -P "$DIR"
4
+ DIR=`pwd`
5
+ gem install sinatra
6
+ gem install sinatra-contrib
7
+ gem install json
8
+ nohup ruby ./server.rb $1 1>"$DIR"/log_"$1".out 2>&1 &
9
+ while true ; do
10
+ curl -p http://127.0.0.1:$1/status-check && exit
11
+ sleep 1
12
+ done
@@ -0,0 +1,158 @@
1
+ require 'sinatra'
2
+ require 'sinatra/namespace'
3
+ require 'json'
4
+ require 'rox/server/flags/rox_flag'
5
+ require 'rox/server/rox_server'
6
+ require 'rox/server/rox_options'
7
+
8
+ class Container
9
+ attr_accessor :first_flag
10
+ attr_reader :bool_default_false, :bool_default_true
11
+
12
+ def initialize
13
+ @bool_default_false = Rox::Server::RoxFlag.new(false)
14
+ @bool_default_true = Rox::Server::RoxFlag.new(true)
15
+ @first_flag = Rox::Server::RoxFlag.new(true)
16
+ end
17
+ end
18
+
19
+ class ServerLogger
20
+ def initialize
21
+ @logger = Logger.new($stdout)
22
+ end
23
+
24
+ def debug(message, exception = nil)
25
+ if exception.nil?
26
+ @logger.debug(message)
27
+ else
28
+ @logger.debug("#{message}. Exception: #{exception}")
29
+ end
30
+ end
31
+
32
+ def error(message, exception = nil)
33
+ if exception.nil?
34
+ @logger.error(message)
35
+ else
36
+ @logger.error("#{message}. Exception: #{exception}")
37
+ end
38
+ end
39
+
40
+ def warn(message, exception = nil)
41
+ if exception.nil?
42
+ @logger.warn(message)
43
+ else
44
+ @logger.warn("#{message}. Exception: #{exception}")
45
+ end
46
+ end
47
+ end
48
+
49
+ container = Container.new
50
+ set :port, ARGV[0]
51
+
52
+ namespace '/' do
53
+ before do
54
+ content_type 'application/json'
55
+ end
56
+
57
+ get 'status-check' do
58
+ [200, '']
59
+ end
60
+
61
+ get 'api/values/:id' do |id|
62
+ if container.first_flag.enabled?
63
+ [200, JSON.generate({ value: id })]
64
+ else
65
+ [200, 'Eladddddd']
66
+ end
67
+ end
68
+
69
+ put 'api/values/:id' do
70
+ [200, '']
71
+ end
72
+
73
+ delete 'api/values/:id' do
74
+ [200, '']
75
+ end
76
+
77
+ post '' do
78
+ data = JSON.parse(request.body.read)
79
+ action = data['action']
80
+ payload = data['payload']
81
+ puts data
82
+
83
+ case action
84
+ when 'staticFlagIsEnabled'
85
+ flag = payload['flag']
86
+ result = container.send(flag.to_sym).enabled?(payload['context'])
87
+ [200, JSON.generate({ result: result })]
88
+ when 'registerStaticContainers'
89
+ Rox::Server::RoxServer.register(container)
90
+ [200, JSON.generate({ result: 'done' })]
91
+ when 'setCustomPropertyToThrow'
92
+ def raise_(ex)
93
+ raise ex
94
+ end
95
+ Rox::Server::RoxServer.set_custom_string_property(payload['key'], raise_(Exception('error')))
96
+ [200, JSON.generate({ result: 'done' })]
97
+ when 'setCustomStringProperty'
98
+ Rox::Server::RoxServer.set_custom_string_property(payload['key'], payload['value'])
99
+ [200, JSON.generate({ result: 'done' })]
100
+ when 'dynamicFlagValue'
101
+ if payload['context']
102
+ puts "There is a payload[context] => #{payload['context']}"
103
+ payload['context'].each do |context|
104
+ key = context[0]
105
+ value = context[1]
106
+ Rox::Server::RoxServer.set_custom_string_property(key, value) if value.instance_of? String
107
+ if value.instance_of? TrueClass
108
+ Rox::Server::RoxServer.set_custom_boolean_property(key, value)
109
+ elsif value.instance_of? FalseClass
110
+ Rox::Server::RoxServer.set_custom_boolean_property(key, value)
111
+ end
112
+ Rox::Server::RoxServer.set_custom_int_property(key, value) if value.instance_of? Integer
113
+ Rox::Server::RoxServer.set_custom_float_property(key, value) if value.instance_of? Float
114
+ end
115
+ end
116
+ result = Rox::Server::RoxServer.dynamic_api.value(payload['flag'], payload['defaultValue'], payload['context'],
117
+ [])
118
+ [200, JSON.generate({ result: result })]
119
+ when 'dynamicFlagIsEnabled'
120
+ payload['context']&.each do |context|
121
+ key = context[0]
122
+ value = context[1]
123
+ Rox::Server::RoxServer.set_custom_string_property(key, value) if value.instance_of? String
124
+ if value.instance_of? TrueClass
125
+ Rox::Server::RoxServer.set_custom_boolean_property(key, value)
126
+ elsif value.instance_of? FalseClass
127
+ Rox::Server::RoxServer.set_custom_boolean_property(key, value)
128
+ end
129
+ Rox::Server::RoxServer.set_custom_int_property(key, value) if value.instance_of? Integer
130
+ Rox::Server::RoxServer.set_custom_float_property(key, value) if value.instance_of? Float
131
+ end
132
+ result = Rox::Server::RoxServer.dynamic_api.enabled?(payload['flag'], payload['defaultValue'], payload['context'])
133
+ [200, JSON.generate({ result: result })]
134
+ when 'setupAndAwait'
135
+ env = 'stam'
136
+ if payload['options']
137
+ options = payload['options']
138
+ if options['configuration']
139
+ configuration = options['configuration']
140
+ env = configuration['env']
141
+ end
142
+ end
143
+ case env
144
+ when 'qa'
145
+ ENV['ROLLOUT_MODE'] = 'QA'
146
+ when 'localhost'
147
+ ENV['ROLLOUT_MODE'] = 'LOCAL'
148
+ end
149
+ options = Rox::Server::RoxOptions.new(logger: ServerLogger.new)
150
+ puts "options => #{options}"
151
+ Rox::Server::RoxServer.setup(payload['key'], options).value
152
+ [200, JSON.generate({ result: 'done' })]
153
+ when 'stop'
154
+ Thread.new { sleep 1; Process.kill 'INT', Process.pid }
155
+ halt 200, JSON.generate({ result: 'done' })
156
+ end
157
+ end
158
+ end
data/example/local.rb ADDED
@@ -0,0 +1,40 @@
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
2
+
3
+ require 'rox/server/rox_server'
4
+ require 'rox/server/rox_options'
5
+
6
+ API_HOST = 'http://localhost:8557'.freeze
7
+ APP_KEY = '611e70975d05440313ccda68'.freeze
8
+ #DEV_MODE_SECRET = 'e56cda16749d8d0a9b91d34c'.freeze
9
+
10
+ class Flags
11
+ attr_accessor :boolean_flag, :string_flag, :int_flag, :double_flag
12
+
13
+ def initialize
14
+ # Define the feature flags
15
+ @boolean_flag = Rox::Server::RoxFlag.new(true)
16
+ @string_flag = Rox::Server::RoxString.new('option 1', ['option 1', 'option 2', 'option 3'])
17
+ @int_flag = Rox::Server::RoxInt.new(1, [1, 2, 3])
18
+ @double_flag = Rox::Server::RoxDouble.new(4.0, [5.0, 6.0])
19
+ end
20
+ end
21
+
22
+ flags = Flags.new
23
+ Rox::Server::RoxServer.register(flags)
24
+
25
+ options = Rox::Server::RoxOptions.new(
26
+ #self_managed_options: Rox::Server::SelfManagedOptions.new(
27
+ # server_url: API_HOST,
28
+ # analytics_url: 'http://127.0.0.1:8787'
29
+ #),
30
+ #dev_mode_key: DEV_MODE_SECRET
31
+ )
32
+
33
+ Rox::Server::RoxServer.setup(APP_KEY, options)
34
+
35
+ puts "boolean_flag is #{flags.boolean_flag.enabled?}"
36
+ puts "boolean_flag is #{Rox::Server::RoxServer.dynamic_api.enabled?('boolean_flag', true)} (dynamic api)"
37
+ puts "boolean_flag is #{Rox::Server::RoxServer.dynamic_api.enabled?('boolean_flag', true)} (dynamic api)"
38
+ puts "string_flag is #{flags.string_flag.value}"
39
+ puts "int_flag is #{flags.int_flag.value}"
40
+ puts "double_flag is #{flags.double_flag.value}"