rox-rollout 4.1.0 → 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f4ad60820f71ef8569f15f07fcb1ced8b05e99be
4
- data.tar.gz: 327115ab21d5889e4783fcef71d33e1cbc72e7ab
2
+ SHA256:
3
+ metadata.gz: 6250ca231936b4d88356da80de6b2aadd4f88dbb799322a48024bfe6b8313984
4
+ data.tar.gz: 2b29111b2c899ab7e320610db0b43f8fddb36029e58e3740eb47e98753d355d1
5
5
  SHA512:
6
- metadata.gz: '0368035eb4d7f508749be64e32e89001af56475e57a9018d45654e854c3ac9e9bae322f800525b70ea606240efc35cb1b7c9d140537114e145d92390416b706b'
7
- data.tar.gz: 75afe906a4eb22195d5020fdb546952bea785a80f49df4eb6cb85bd8cdd9cec7c47e25f702d013525a8e4474b4ef8bd24f4e6acfb33553fde4a48a859dbcd6da
6
+ metadata.gz: 45e156d7b9452b07f75305d4cf0d729764ce086b677aa33ced194b0ce080efd7229ae9889059b6ddfa43d53d1eefe0075abaf3c0ac29f2ec748dbc75457c8111
7
+ data.tar.gz: 94e8e1841ff73cb085e53d38315620cfff72383099ec5191079a157e8ac44e93e1e4b62f736fc5dbf15953fc007d5c8ac753f68035966c68ae718ba2ddda11f3
data/.circleci/config.yml CHANGED
@@ -3,43 +3,50 @@ workflows:
3
3
  version: 2
4
4
  test:
5
5
  jobs:
6
+ - test-2.6
6
7
  - test-2.5
7
8
  - test-2.4
8
9
  - test-2.3
9
10
  jobs:
10
- test-2.5: &test-template
11
+ test-2.6: &test-template
11
12
  docker:
12
- - image: circleci/ruby:2.5.1
13
+ - image: circleci/ruby:2.6.4
13
14
 
14
15
  working_directory: ~/repo
15
16
 
16
17
  steps:
17
18
  - checkout
18
19
 
19
- - restore_cache:
20
- keys:
21
- - v1-dependencies-{{ checksum "Gemfile.lock" }}
22
- - v1-dependencies-
20
+ - run:
21
+ name: install ssh
22
+ command: |
23
+ sudo apt-get update
24
+ sudo apt-get install libssl-dev
23
25
 
24
26
  - run:
25
27
  name: install dependencies
26
28
  command: |
27
29
  bundle install --jobs=4 --retry=3 --path vendor/bundle
28
30
 
29
- - save_cache:
30
- paths:
31
- - ./vendor/bundle
32
- key: v1-dependencies-{{ checksum "Gemfile.lock" }}
33
-
34
31
  - run:
35
32
  name: run tests
36
33
  command: |
37
34
  bundle exec rake test
35
+
36
+ - run:
37
+ name: run tests
38
+ command: |
39
+ bundle exec rake e2e
40
+
41
+ test-2.5:
42
+ <<: *test-template
43
+ docker:
44
+ - image: circleci/ruby:2.5.6
38
45
  test-2.4:
39
46
  <<: *test-template
40
47
  docker:
41
- - image: circleci/ruby:2.4.4
48
+ - image: circleci/ruby:2.4.7
42
49
  test-2.3:
43
50
  <<: *test-template
44
51
  docker:
45
- - image: circleci/ruby:2.3.7
52
+ - image: circleci/ruby:2.3.8
data/.gitignore CHANGED
@@ -6,3 +6,5 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ Gemfile.lock
10
+ .ruby-version
data/README_DEVELOP.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Developer Guide
2
2
 
3
+ Ruby versions supported: 2.3.x, 2.4.x, 2.5.x, 2.6.x
4
+
3
5
  ## Run tests on current Ruby version
4
6
 
5
7
  ```
data/e2e/rox_e2e_test.rb CHANGED
@@ -156,4 +156,4 @@ module E2E
156
156
  assert_equal 'Yellow', @@container.flag_color_dependent_with_context.value(some_positive_context)
157
157
  end
158
158
  end
159
- end
159
+ end
@@ -9,17 +9,12 @@ module Rox
9
9
  PropertyType::PLATFORM,
10
10
  PropertyType::APP_KEY,
11
11
  PropertyType::LIB_VERSION,
12
- PropertyType::API_VERSION,
13
- PropertyType::CUSTOM_PROPERTIES,
14
- PropertyType::FEATURE_FLAGS,
15
- PropertyType::REMOTE_VARIABLES
12
+ PropertyType::API_VERSION
16
13
  ].freeze
17
14
 
18
15
  def initialize(sdk_settings, device_properties, flag_repository, custom_property_repository)
19
16
  @sdk_settings = sdk_settings
20
17
  @device_properties = device_properties
21
- @flag_repository = flag_repository
22
- @custom_property_repository = custom_property_repository
23
18
  @buid = nil
24
19
  end
25
20
 
@@ -30,9 +25,6 @@ module Rox
30
25
  values << properties[pt.name] if properties.include?(pt.name)
31
26
  end
32
27
 
33
- values << serialize_feature_flags
34
- values << serialize_custom_properties
35
-
36
28
  hash = Digest::MD5.hexdigest(values.join('|'))
37
29
 
38
30
  @buid = hash.upcase
@@ -44,39 +36,12 @@ module Rox
44
36
  {
45
37
  PropertyType::BUID.name => value,
46
38
  PropertyType::BUID_GENERATORS_LIST.name => generators.join(','),
47
- PropertyType::FEATURE_FLAGS.name => serialize_feature_flags,
48
- PropertyType::REMOTE_VARIABLES.name => '[]',
49
- PropertyType::CUSTOM_PROPERTIES.name => serialize_custom_properties,
50
39
  }
51
40
  end
52
41
 
53
- def serialize_feature_flags
54
- flags = []
55
- @flag_repository.all_flags.each do |f|
56
- flags << {
57
- name: f.name,
58
- defaultValue: f.default_value,
59
- options: f.options
60
- }
61
- end
62
- JSON.dump(flags)
63
- end
64
-
65
- def serialize_custom_properties
66
- properties = []
67
- @custom_property_repository.all_custom_properties.each do |p|
68
- properties << {
69
- name: p.name,
70
- type: p.type.type,
71
- externalType: p.type.external_type
72
- }
73
- end
74
- JSON.dump(properties)
75
- end
76
-
77
42
  def to_s
78
43
  @buid
79
44
  end
80
45
  end
81
46
  end
82
- end
47
+ end
@@ -42,4 +42,4 @@ module Rox
42
42
  end
43
43
  end
44
44
  end
45
- end
45
+ end
@@ -82,4 +82,4 @@ module Rox
82
82
  end
83
83
  end
84
84
  end
85
- end
85
+ end
@@ -2,7 +2,7 @@ module Rox
2
2
  module Core
3
3
  module Build
4
4
  PLATFORM = 'Ruby'
5
- API_VERSION = '1.7.0'
5
+ API_VERSION = '1.8.0'
6
6
  end
7
7
  end
8
- end
8
+ end
@@ -8,22 +8,44 @@ module Rox
8
8
  def self.cdn_path
9
9
  case ENV['ROLLOUT_MODE']
10
10
  when 'QA'
11
- 'https://s3.amazonaws.com/qa-rox-conf.rollout.io/v1/qa'
11
+ 'https://qa-conf.rollout.io'
12
12
  when 'LOCAL'
13
- 'https://s3.amazonaws.com/qa-rox-conf.rollout.io/v1/development'
13
+ 'https://development-conf.rollout.io'
14
14
  else
15
- 'https://s3.amazonaws.com/rox-conf.rollout.io/v1/production'
15
+ 'https://conf.rollout.io'
16
16
  end
17
17
  end
18
18
 
19
19
  def self.api_path
20
20
  case ENV['ROLLOUT_MODE']
21
21
  when 'QA'
22
- 'https://qax.rollout.io/device/request_configuration'
22
+ 'https://qax.rollout.io/device/get_configuration'
23
23
  when 'LOCAL'
24
- 'http://127.0.0.1:8557/device/request_configuration'
24
+ 'http://127.0.0.1:8557/device/get_configuration'
25
25
  else
26
- 'https://x-api.rollout.io/device/request_configuration'
26
+ 'https://x-api.rollout.io/device/get_configuration'
27
+ end
28
+ end
29
+
30
+ def self.state_cdn_path
31
+ case ENV['ROLLOUT_MODE']
32
+ when 'QA'
33
+ 'https://qa-statestore.rollout.io'
34
+ when 'LOCAL'
35
+ 'https://development-statestore.rollout.io'
36
+ else
37
+ 'https://statestore.rollout.io'
38
+ end
39
+ end
40
+
41
+ def self.state_api_path
42
+ case ENV['ROLLOUT_MODE']
43
+ when 'QA'
44
+ 'https://qax.rollout.io/device/update_state_store'
45
+ when 'LOCAL'
46
+ 'http://127.0.0.1:8557/device/update_state_store'
47
+ else
48
+ 'https://x-api.rollout.io/device/update_state_store'
27
49
  end
28
50
  end
29
51
 
@@ -50,4 +72,4 @@ module Rox
50
72
  end
51
73
  end
52
74
  end
53
- end
75
+ end
@@ -8,7 +8,7 @@ module Rox
8
8
  @name = name
9
9
  end
10
10
 
11
- CACHE_MISS_URL = PropertyType.new(1, 'cache_miss_url')
11
+ CACHE_MISS_RELATIVE_URL = PropertyType.new(1, 'cache_miss_relative_url')
12
12
  PACKAGE_NAME = PropertyType.new(2, "package_name")
13
13
  VERSION_NAME = PropertyType.new(3, "version_name")
14
14
  LIB_VERSION = PropertyType.new(4, "lib_version")
@@ -24,6 +24,8 @@ module Rox
24
24
  REMOTE_VARIABLES = PropertyType.new(14, "remote_variables")
25
25
  CUSTOM_PROPERTIES = PropertyType.new(15, "custom_properties")
26
26
  PLATFORM = PropertyType.new(16, "platform")
27
+ DEV_MODE_SECRET = PropertyType.new(17, "dev_mode_secret")
28
+ STATE_MD5 = PropertyType.new(18, "state_md5")
27
29
  end
28
30
  end
29
- end
31
+ end
data/lib/rox/core/core.rb CHANGED
@@ -11,6 +11,7 @@ require 'rox/core/network/request_configuration_builder'
11
11
  require 'rox/core/network/request'
12
12
  require 'rox/core/network/configuration_fetcher'
13
13
  require 'rox/core/network/configuration_fetcher_roxy'
14
+ require 'rox/core/network/state_sender'
14
15
  require 'rox/core/notifications/notification_listener'
15
16
  require 'rox/core/register/registerer'
16
17
  require 'rox/core/client/internal_flags'
@@ -55,6 +56,10 @@ module Rox
55
56
 
56
57
  roxy_path = rox_options.nil? || rox_options.roxy_url.nil? ? nil : rox_options.roxy_url
57
58
 
59
+ if roxy_path.nil?
60
+ validate_api_key(sdk_settings&.api_key)
61
+ end
62
+
58
63
  # TODO: Analytics.Analytics.Initialize(deviceProperties.RolloutKey, deviceProperties)
59
64
  @internal_flags = InternalFlags.new(@experiment_repository, @parser)
60
65
 
@@ -72,6 +77,9 @@ module Rox
72
77
 
73
78
  if roxy_path.nil?
74
79
  @configuration_fetcher = ConfigurationFetcher.new(request_config_builder, client_request, @configuration_fetched_invoker)
80
+ @state_sender = StateSender.new(@sdk_settings, device_properties, @flag_repository, @custom_property_repository)
81
+ @flag_repository.register_flag_added_handler { @state_sender.delayed_send }
82
+ @custom_property_repository.register_property_added_handler { @state_sender.delayed_send }
75
83
  else
76
84
  @configuration_fetcher = ConfigurationFetcherRoxy.new(request_config_builder, client_request, @configuration_fetched_invoker)
77
85
  end
@@ -161,6 +169,15 @@ module Rox
161
169
  def dynamic_api(entities_provider)
162
170
  Rox::Core::DynamicApi.new(@flag_repository, entities_provider)
163
171
  end
172
+
173
+ def validate_api_key(api_key)
174
+ valid_api_key_pattern = /^[a-f\d]{24}$/
175
+ if api_key&.strip&.empty?
176
+ raise ArgumentError.new('Blank Rollout api key - must be specified')
177
+ elsif !valid_api_key_pattern.match(api_key)
178
+ raise ArgumentError.new('Illegal Rollout api key')
179
+ end
180
+ end
164
181
  end
165
182
  end
166
- end
183
+ end
@@ -2,4 +2,4 @@ module Rox
2
2
  module Core
3
3
  ConfigurationFetchResult = Struct.new(:data, :source)
4
4
  end
5
- end
5
+ end
@@ -9,13 +9,13 @@ module Rox
9
9
  source = ConfigurationSource::CDN
10
10
  begin
11
11
  fetch_result = fetch_from_cdn
12
- return ConfigurationFetchResult.new(fetch_result.text, source) if fetch_result.success_status_code?
13
-
14
- if [403, 404].include?(fetch_result.status_code)
12
+ if fetch_result.success?
13
+ return ConfigurationFetchResult.new(fetch_result.text, source)
14
+ else
15
15
  write_fetch_error_to_log_and_invoke_fetch_handler(source, fetch_result, false, ConfigurationSource::API)
16
16
  source = ConfigurationSource::API
17
17
  fetch_result = fetch_from_api
18
- return ConfigurationFetchResult.new(fetch_result.text, source) if fetch_result.success_status_code?
18
+ return ConfigurationFetchResult.new(fetch_result.text, source) if fetch_result.success?
19
19
  end
20
20
 
21
21
  write_fetch_error_to_log_and_invoke_fetch_handler(source, fetch_result)
@@ -31,8 +31,9 @@ module Rox
31
31
  end
32
32
 
33
33
  def fetch_from_api
34
- @request.send_get(@request_configuration_builder.build_for_api)
34
+ api_request = @request_configuration_builder.build_for_api
35
+ @request.send_post(api_request.url, api_request.query_params)
35
36
  end
36
37
  end
37
38
  end
38
- end
39
+ end
@@ -22,4 +22,4 @@ module Rox
22
22
  end
23
23
  end
24
24
  end
25
- end
25
+ end
@@ -9,7 +9,7 @@ module Rox
9
9
  source = ConfigurationSource::ROXY
10
10
  begin
11
11
  fetch_roxy = fetch_from_roxy
12
- if fetch_roxy.success_status_code?
12
+ if fetch_roxy.success?
13
13
  return ConfigurationFetchResult.new(fetch_roxy.text, source)
14
14
  else
15
15
  write_fetch_error_to_log_and_invoke_fetch_handler(source, fetch_roxy)
@@ -26,4 +26,4 @@ module Rox
26
26
  end
27
27
  end
28
28
  end
29
- end
29
+ end
@@ -39,8 +39,8 @@ module Rox
39
39
  resp_body = gz.read
40
40
  end
41
41
 
42
- Response.new(resp.code.to_i, resp_body)
42
+ Response.new(resp.code.to_i, resp_body, resp['Content-Type'])
43
43
  end
44
44
  end
45
45
  end
46
- end
46
+ end
@@ -18,12 +18,16 @@ module Rox
18
18
  end
19
19
 
20
20
  def build_for_cdn
21
- RequestData.new("#{Rox::Core::Environment.cdn_path}/#{@buid.value}",
21
+ RequestData.new("#{Rox::Core::Environment.cdn_path}/#{relative_path}",
22
22
  Rox::Core::PropertyType::DISTINCT_ID.name => @device_properties.distinct_id)
23
23
  end
24
24
 
25
25
  def build_for_api
26
- build_request_with_full_params(Rox::Core::Environment.api_path)
26
+ build_request_with_full_params("#{Rox::Core::Environment.api_path}/#{relative_path}")
27
+ end
28
+
29
+ def relative_path
30
+ "#{@device_properties.rollout_key}/#{@buid.value}"
27
31
  end
28
32
 
29
33
  def build_request_with_full_params(url)
@@ -37,12 +41,11 @@ module Rox
37
41
  query_params[key] = value unless query_params.include?(key)
38
42
  end
39
43
 
40
- cdn_data = build_for_cdn
41
- query_params[Rox::Core::PropertyType::CACHE_MISS_URL.name] = cdn_data.url
44
+ query_params[Rox::Core::PropertyType::CACHE_MISS_RELATIVE_URL.name] = relative_path
42
45
  query_params['devModeSecret'] = @sdk_settings.dev_mode_secret
43
46
 
44
47
  RequestData.new(url, query_params)
45
48
  end
46
49
  end
47
50
  end
48
- end
51
+ end
@@ -1,16 +1,34 @@
1
+ require 'json'
2
+ require 'rox/core/logging/logging'
3
+
1
4
  module Rox
2
5
  module Core
3
6
  class Response
4
- attr_accessor :status_code, :text
7
+ attr_accessor :status_code, :text, :content_type
5
8
 
6
- def initialize(status_code, text)
9
+ def initialize(status_code, text, content_type='application/octet-stream')
7
10
  @status_code = status_code
8
11
  @text = text
12
+ @content_type = content_type
13
+ end
14
+
15
+ def success?
16
+ status_code_success? && !missing_via_response_body?
9
17
  end
10
18
 
11
- def success_status_code?
19
+ def status_code_success?
12
20
  @status_code >= 200 && @status_code < 300
13
21
  end
22
+
23
+ def missing_via_response_body?
24
+ begin
25
+ @status_code == 200 && @content_type == 'application/json' &&
26
+ [404, "404"].include?(JSON.parse(text)['result'])
27
+ rescue JSON::ParserError
28
+ Logging.logger.error("Failed to parse JSON response: #{text}")
29
+ false
30
+ end
31
+ end
14
32
  end
15
33
  end
16
- end
34
+ end
@@ -0,0 +1,104 @@
1
+ require 'digest'
2
+ require 'json'
3
+
4
+ require 'rox/core/consts/environment'
5
+ require 'rox/core/consts/property_type'
6
+ require 'rox/core/logging/logging'
7
+ require 'rox/core/network/request'
8
+ require 'rox/core/network/request_data'
9
+ require 'rox/core/network/response'
10
+ require 'rox/core/utils/debouncer'
11
+
12
+ module Rox
13
+ module Core
14
+ class StateSender
15
+ def initialize(sdk_settings, device_properties, flag_repository, custom_property_repository)
16
+ @sdk_settings = sdk_settings
17
+ @device_properties = device_properties
18
+ @flag_repository = flag_repository
19
+ @custom_property_repository = custom_property_repository
20
+ @request = Request.new
21
+ @debouncer = Debouncer.new(1, Proc.new { self.send })
22
+ end
23
+
24
+ def delayed_send
25
+ @debouncer.call
26
+ end
27
+
28
+ def send
29
+ rollout_key = @device_properties.rollout_key
30
+ serialized_feature_flags = StateSender.seralize_flag_repository(@flag_repository)
31
+ serialized_custom_properties = StateSender.serialize_custom_properties_repository(@custom_property_repository)
32
+
33
+ state_payload = StateSender.current_state_payload(serialized_feature_flags, serialized_custom_properties)
34
+ md5_signature = StateSender.generate_md5_signature(serialized_feature_flags, serialized_custom_properties, @device_properties, @sdk_settings.dev_mode_secret)
35
+
36
+ response = get_state_from_CDN(rollout_key, md5_signature)
37
+ if !response.success?
38
+ Rox::Core::Logging.logger.debug("Failed to fetch state from CDN. Sending state to API...")
39
+ response = send_state_to_API(rollout_key, md5_signature, state_payload)
40
+ if response.success?
41
+ Rox::Core::Logging.logger.debug("Successfully sent state to API.")
42
+ else
43
+ Rox::Core::Logging.logger.debug("Failed to send state to API.")
44
+ end
45
+ else
46
+ Rox::Core::Logging.logger.debug("Successfully fetched state from CDN")
47
+ end
48
+ end
49
+
50
+ def get_state_from_CDN(rollout_key, md5_signature)
51
+ url_for_state_cdn =
52
+ RequestData.new("#{Rox::Core::Environment.state_cdn_path}/#{rollout_key}/#{md5_signature}", {})
53
+ @request.send_get(url_for_state_cdn)
54
+ end
55
+
56
+ def send_state_to_API(rollout_key, md5_signature, state_payload)
57
+ @request.send_post("#{Rox::Core::Environment.state_api_path}/#{rollout_key}/#{md5_signature}", state_payload)
58
+ end
59
+
60
+ def self.generate_md5_signature(serialized_feature_flags, serialized_custom_properties, device_properties, dev_mode_secret)
61
+ values = []
62
+ values << device_properties.all_properties[PropertyType::APP_KEY.name]
63
+ values << device_properties.all_properties[PropertyType::PLATFORM.name]
64
+ values << serialized_feature_flags
65
+ values << serialized_custom_properties
66
+ values << dev_mode_secret
67
+
68
+ hash = Digest::MD5.hexdigest(values.join('|'))
69
+ hash.upcase
70
+ end
71
+
72
+ def self.current_state_payload(seralized_flag_repository, serialized_custom_property_repository)
73
+ values = []
74
+ values << seralized_flag_repository
75
+ values << serialized_custom_property_repository
76
+ values
77
+ end
78
+
79
+ def self.seralize_flag_repository(flag_repository)
80
+ flags = []
81
+ flag_repository.all_flags.sort_by{|flag| flag.name }.each do |f|
82
+ flags << {
83
+ name: f.name,
84
+ defaultValue: f.default_value,
85
+ options: f.options
86
+ }
87
+ end
88
+ JSON.dump(flags)
89
+ end
90
+
91
+ def self.serialize_custom_properties_repository(custom_property_repository)
92
+ properties = []
93
+ custom_property_repository.all_custom_properties.sort_by{|prop| prop.name }.each do |p|
94
+ properties << {
95
+ name: p.name,
96
+ type: p.type.type,
97
+ externalType: p.type.external_type
98
+ }
99
+ end
100
+ JSON.dump(properties)
101
+ end
102
+ end
103
+ end
104
+ end
@@ -58,4 +58,4 @@ module Rox
58
58
  end
59
59
  end
60
60
  end
61
- end
61
+ end
@@ -46,4 +46,4 @@ module Rox
46
46
  end
47
47
  end
48
48
  end
49
- end
49
+ end
@@ -1,4 +1,5 @@
1
1
  require 'digest'
2
+ require 'base64'
2
3
  require 'rox/core/roxx/core_stack'
3
4
  require 'rox/core/roxx/evaluation_result'
4
5
  require 'rox/core/roxx/value_compare_extensions'
@@ -143,6 +144,17 @@ module Rox
143
144
  stack.push(TokenType::UNDEFINED)
144
145
  end
145
146
  end
147
+
148
+ add_operator('b64d') do |parser, stack, context|
149
+ op1 = stack.pop
150
+ if op1.is_a?(String)
151
+ decoded = Base64.decode64(op1)
152
+ decoded = decoded.force_encoding('UTF-8')
153
+ stack.push(decoded)
154
+ else
155
+ stack.push(TokenType::UNDEFINED)
156
+ end
157
+ end
146
158
  end
147
159
  end
148
160
  end
@@ -0,0 +1,18 @@
1
+ class Debouncer
2
+ def initialize(delay_in_seconds, block)
3
+ @delay_in_seconds = delay_in_seconds
4
+ @block = block
5
+ @delay_until = Time.now
6
+ end
7
+
8
+ def call
9
+ now = Time.now
10
+ if now > @delay_until
11
+ @delay_until = now + @delay_in_seconds
12
+ Thread.new do
13
+ sleep(@delay_in_seconds)
14
+ @block.call
15
+ end
16
+ end
17
+ end
18
+ end
@@ -2,4 +2,4 @@ module Rox
2
2
  module Server
3
3
  SdkSettings = Struct.new(:api_key, :dev_mode_secret)
4
4
  end
5
- end
5
+ end
@@ -86,4 +86,4 @@ module Rox
86
86
  end
87
87
  end
88
88
  end
89
- end
89
+ end
data/lib/rox/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rox
2
- VERSION = "4.1.0"
2
+ VERSION = "4.7.0"
3
3
  end
data/rox.gemspec CHANGED
@@ -26,6 +26,8 @@ Gem::Specification.new do |spec|
26
26
  spec.add_runtime_dependency 'em-eventsource', '~> 0.3.0'
27
27
 
28
28
  spec.add_development_dependency 'bundler', '~> 1.16'
29
- spec.add_development_dependency 'minitest', '~> 5.0'
29
+ spec.add_development_dependency 'minitest', '~> 5.11'
30
30
  spec.add_development_dependency 'rake', '~> 12.3'
31
+ spec.add_development_dependency 'pry-byebug', '~> 3.7.0'
32
+ spec.add_development_dependency 'webmock', '~> 3.7.5'
31
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rox-rollout
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0
4
+ version: 4.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rollout.io
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-05-14 00:00:00.000000000 Z
11
+ date: 2019-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: em-eventsource
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '5.0'
47
+ version: '5.11'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '5.0'
54
+ version: '5.11'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,34 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '12.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.7.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 3.7.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: webmock
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 3.7.5
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 3.7.5
69
97
  description:
70
98
  email:
71
99
  - support@rollout.io
@@ -139,6 +167,7 @@ files:
139
167
  - lib/rox/core/network/request_configuration_builder.rb
140
168
  - lib/rox/core/network/request_data.rb
141
169
  - lib/rox/core/network/response.rb
170
+ - lib/rox/core/network/state_sender.rb
142
171
  - lib/rox/core/notifications/notification_listener.rb
143
172
  - lib/rox/core/properties/custom_property.rb
144
173
  - lib/rox/core/properties/custom_property_type.rb
@@ -162,6 +191,7 @@ files:
162
191
  - lib/rox/core/roxx/tokenized_expression.rb
163
192
  - lib/rox/core/roxx/value_compare_extensions.rb
164
193
  - lib/rox/core/security/signature_verifier.rb
194
+ - lib/rox/core/utils/debouncer.rb
165
195
  - lib/rox/core/utils/periodic_task.rb
166
196
  - lib/rox/core/utils/type_utils.rb
167
197
  - lib/rox/server/client/sdk_settings.rb
@@ -193,8 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
193
223
  - !ruby/object:Gem::Version
194
224
  version: '0'
195
225
  requirements: []
196
- rubyforge_project:
197
- rubygems_version: 2.6.14
226
+ rubygems_version: 3.0.3
198
227
  signing_key:
199
228
  specification_version: 4
200
229
  summary: Rollout.io ROX Ruby SDK