configcat 1.0.1 → 1.2.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
2
  SHA256:
3
- metadata.gz: f268b80ad6cfa72c12ca3a438d6fc8a896be9dcd324d5f7743274ea1b93935b8
4
- data.tar.gz: e9889a6887f63823adacfa9be12f1ede457f0f94d17a2920d6800b6c816a4f23
3
+ metadata.gz: dada53197ffe2d00bf8f4349bd643312f65d72b970e4de9bb774a490bf2f12c4
4
+ data.tar.gz: 0e656c1c42d3def92aa47013f8c22a555f0268b2dff5b8df37b79a0ac3952425
5
5
  SHA512:
6
- metadata.gz: 248a015959119f3629c42df5b6bb9d1b5105a452ea5d3d8054d0110b73fff508f2e551cf7e3ed591330f0037748adf487b7c6678a0385c47e5869613ca8b6d66
7
- data.tar.gz: 055ac0dd698e4bd3173ba64c299c9856ad8e2821bd92fd5b0a6e2f25197054ba1ff15bb0c931b6a1bd78ed6eb6ea369d2b08e637db5743154fd73a243b6f3876
6
+ metadata.gz: ace75c4e4f36cfb62447beca19786287026fa8be4409506fa54b58a693f4b996a9526acad14b9552012377a6c5e75b5fcd0073118e7cd2af403b1585eecc6e07
7
+ data.tar.gz: bd98ab5c116d6a4daf2d1f07a214e585bcc630d9f81b268febe9b0fead8f4fdc1cb86e7af4042f5d568c46e8692d8599db2f4e9b83a74fbec80312612c091c46
@@ -5,7 +5,7 @@ require 'logger'
5
5
 
6
6
  module ConfigCat
7
7
 
8
- @logger = Logger.new(STDOUT, level: Logger::INFO)
8
+ @logger = Logger.new(STDOUT, level: Logger::WARN)
9
9
  class << self
10
10
  attr_accessor :logger
11
11
  end
@@ -19,7 +19,16 @@ module ConfigCat
19
19
  return create_client_with_auto_poll(api_key)
20
20
  end
21
21
 
22
- def ConfigCat.create_client_with_auto_poll(api_key, poll_interval_seconds: 60, max_init_wait_time_seconds: 5, on_configuration_changed_callback: nil, config_cache_class: nil, base_url: nil)
22
+ def ConfigCat.create_client_with_auto_poll(api_key,
23
+ poll_interval_seconds: 60,
24
+ max_init_wait_time_seconds: 5,
25
+ on_configuration_changed_callback: nil,
26
+ config_cache_class: nil,
27
+ base_url: nil,
28
+ proxy_address:nil,
29
+ proxy_port:nil,
30
+ proxy_user:nil,
31
+ proxy_pass:nil)
23
32
  #
24
33
  # Create an instance of ConfigCatClient and setup Auto Poll mode with custom options
25
34
  #
@@ -30,6 +39,10 @@ module ConfigCat
30
39
  # :param config_cache_class: If you want to use custom caching instead of the client's default InMemoryConfigCache,
31
40
  # You can provide an implementation of ConfigCache.
32
41
  # :param base_url: You can set a base_url if you want to use a proxy server between your application and ConfigCat
42
+ # :param proxy_address: Proxy address
43
+ # :param proxy_port: Proxy port
44
+ # :param proxy_user: username for proxy authentication
45
+ # :param proxy_pass: password for proxy authentication
33
46
  #
34
47
  if api_key === nil
35
48
  raise ConfigCatClientException, "API Key is required."
@@ -46,10 +59,21 @@ module ConfigCat
46
59
  on_configuration_changed_callback: on_configuration_changed_callback,
47
60
  cache_time_to_live_seconds: 0,
48
61
  config_cache_class: config_cache_class,
49
- base_url: base_url)
62
+ base_url: base_url,
63
+ proxy_address: proxy_address,
64
+ proxy_port: proxy_port,
65
+ proxy_user: proxy_user,
66
+ proxy_pass: proxy_pass)
50
67
  end
51
68
 
52
- def ConfigCat.create_client_with_lazy_load(api_key, cache_time_to_live_seconds: 60, config_cache_class: nil, base_url: nil)
69
+ def ConfigCat.create_client_with_lazy_load(api_key,
70
+ cache_time_to_live_seconds: 60,
71
+ config_cache_class: nil,
72
+ base_url: nil,
73
+ proxy_address:nil,
74
+ proxy_port:nil,
75
+ proxy_user:nil,
76
+ proxy_pass:nil)
53
77
  #
54
78
  # Create an instance of ConfigCatClient and setup Lazy Load mode with custom options
55
79
  #
@@ -58,6 +82,10 @@ module ConfigCat
58
82
  # :param config_cache_class: If you want to use custom caching instead of the client's default InMemoryConfigCache,
59
83
  # You can provide an implementation of ConfigCache.
60
84
  # :param base_url: You can set a base_url if you want to use a proxy server between your application and ConfigCat
85
+ # :param proxy_address: Proxy address
86
+ # :param proxy_port: Proxy port
87
+ # :param proxy_user: username for proxy authentication
88
+ # :param proxy_pass: password for proxy authentication
61
89
  #
62
90
  if api_key === nil
63
91
  raise ConfigCatClientException, "API Key is required."
@@ -71,10 +99,20 @@ module ConfigCat
71
99
  on_configuration_changed_callback: nil,
72
100
  cache_time_to_live_seconds: cache_time_to_live_seconds,
73
101
  config_cache_class: config_cache_class,
74
- base_url: base_url)
102
+ base_url: base_url,
103
+ proxy_address: proxy_address,
104
+ proxy_port: proxy_port,
105
+ proxy_user: proxy_user,
106
+ proxy_pass: proxy_pass)
75
107
  end
76
108
 
77
- def ConfigCat.create_client_with_manual_poll(api_key, config_cache_class: nil, base_url: nil)
109
+ def ConfigCat.create_client_with_manual_poll(api_key,
110
+ config_cache_class: nil,
111
+ base_url: nil,
112
+ proxy_address:nil,
113
+ proxy_port:nil,
114
+ proxy_user:nil,
115
+ proxy_pass:nil)
78
116
  #
79
117
  # Create an instance of ConfigCatClient and setup Manual Poll mode with custom options
80
118
  #
@@ -82,6 +120,10 @@ module ConfigCat
82
120
  # :param config_cache_class: If you want to use custom caching instead of the client's default InMemoryConfigCache,
83
121
  # You can provide an implementation of ConfigCache.
84
122
  # :param base_url: You can set a base_url if you want to use a proxy server between your application and ConfigCat
123
+ # :param proxy_address: Proxy address
124
+ # :param proxy_port: Proxy port
125
+ # :param proxy_user: username for proxy authentication
126
+ # :param proxy_pass: password for proxy authentication
85
127
  #
86
128
  if api_key === nil
87
129
  raise ConfigCatClientException, "API Key is required."
@@ -92,7 +134,11 @@ module ConfigCat
92
134
  on_configuration_changed_callback: nil,
93
135
  cache_time_to_live_seconds: 0,
94
136
  config_cache_class: config_cache_class,
95
- base_url: base_url)
137
+ base_url: base_url,
138
+ proxy_address: proxy_address,
139
+ proxy_port: proxy_port,
140
+ proxy_user: proxy_user,
141
+ proxy_pass: proxy_pass)
96
142
  end
97
143
 
98
144
  end
@@ -47,30 +47,38 @@ module ConfigCat
47
47
  end
48
48
 
49
49
  def force_refresh()
50
- begin
51
- @_lock.acquire_read_lock()
52
- old_configuration = @_config_cache.get()
53
- ensure
54
- @_lock.release_read_lock()
55
- end
56
50
  begin
57
51
  configuration = @_config_fetcher.get_configuration_json()
52
+
58
53
  begin
59
- @_lock.acquire_write_lock()
60
- @_config_cache.set(configuration)
61
- @_initialized = true
54
+ @_lock.acquire_read_lock()
55
+ old_configuration = @_config_cache.get()
62
56
  ensure
63
- @_lock.release_write_lock()
57
+ @_lock.release_read_lock()
64
58
  end
65
- begin
66
- if !@_on_configuration_changed_callback.equal?(nil) && configuration != old_configuration
67
- @_on_configuration_changed_callback.call()
59
+
60
+ if configuration != old_configuration
61
+ begin
62
+ @_lock.acquire_write_lock()
63
+ @_config_cache.set(configuration)
64
+ @_initialized = true
65
+ ensure
66
+ @_lock.release_write_lock()
67
+ end
68
+ begin
69
+ if !@_on_configuration_changed_callback.equal?(nil)
70
+ @_on_configuration_changed_callback.()
71
+ end
72
+ rescue Exception => e
73
+ ConfigCat.logger.error("Exception in on_configuration_changed_callback: #{e.class}:'#{e}'")
68
74
  end
69
- rescue Exception => e
70
- ConfigCat.logger.error "threw exception #{e.class}:'#{e}'"
71
- ConfigCat.logger.error "stacktrace: #{e.backtrace}"
72
75
  end
73
- rescue StandardError => e
76
+
77
+ if !@_initialized && !old_configuration.equal?(nil)
78
+ @_initialized = true
79
+ end
80
+ rescue Exception => e
81
+ ConfigCat.logger.error("Double-check your API KEY at https://app.configcat.com/apikey.")
74
82
  ConfigCat.logger.error "threw exception #{e.class}:'#{e}'"
75
83
  ConfigCat.logger.error "stacktrace: #{e.backtrace}"
76
84
  end
@@ -14,7 +14,11 @@ module ConfigCat
14
14
  on_configuration_changed_callback:nil,
15
15
  cache_time_to_live_seconds:60,
16
16
  config_cache_class:nil,
17
- base_url:nil)
17
+ base_url:nil,
18
+ proxy_address:nil,
19
+ proxy_port:nil,
20
+ proxy_user:nil,
21
+ proxy_pass:nil)
18
22
  if api_key === nil
19
23
  raise ConfigCatClientException, "API Key is required."
20
24
  end
@@ -27,14 +31,14 @@ module ConfigCat
27
31
  end
28
32
 
29
33
  if poll_interval_seconds > 0
30
- @_config_fetcher = CacheControlConfigFetcher.new(api_key, "p", base_url)
34
+ @_config_fetcher = CacheControlConfigFetcher.new(api_key, "p", base_url, proxy_address, proxy_port, proxy_user, proxy_pass)
31
35
  @_cache_policy = AutoPollingCachePolicy.new(@_config_fetcher, @_config_cache, poll_interval_seconds, max_init_wait_time_seconds, on_configuration_changed_callback)
32
36
  else
33
37
  if cache_time_to_live_seconds > 0
34
- @_config_fetcher = CacheControlConfigFetcher.new(api_key, "l", base_url)
38
+ @_config_fetcher = CacheControlConfigFetcher.new(api_key, "l", base_url, proxy_address, proxy_port, proxy_user, proxy_pass)
35
39
  @_cache_policy = LazyLoadingCachePolicy.new(@_config_fetcher, @_config_cache, cache_time_to_live_seconds)
36
40
  else
37
- @_config_fetcher = CacheControlConfigFetcher.new(api_key, "m", base_url)
41
+ @_config_fetcher = CacheControlConfigFetcher.new(api_key, "m", base_url, proxy_address, proxy_port, proxy_user, proxy_pass)
38
42
  @_cache_policy = ManualPollingCachePolicy.new(@_config_fetcher, @_config_cache)
39
43
  end
40
44
  end
@@ -7,10 +7,10 @@ require 'json'
7
7
  module ConfigCat
8
8
  BASE_URL = "https://cdn.configcat.com"
9
9
  BASE_PATH = "configuration-files/"
10
- BASE_EXTENSION = "/config_v2.json"
10
+ BASE_EXTENSION = "/config_v3.json"
11
11
 
12
12
  class CacheControlConfigFetcher < ConfigFetcher
13
- def initialize(api_key, mode, base_url=nil)
13
+ def initialize(api_key, mode, base_url=nil, proxy_address=nil, proxy_port=nil, proxy_user=nil, proxy_pass=nil)
14
14
  @_api_key = api_key
15
15
  @_etag = nil
16
16
  @_headers = {"User-Agent" => ((("ConfigCat-Ruby/") + mode) + ("-")) + VERSION, "X-ConfigCat-UserAgent" => ((("ConfigCat-Ruby/") + mode) + ("-")) + VERSION, "Content-Type" => "application/json"}
@@ -20,7 +20,7 @@ module ConfigCat
20
20
  @_base_url = BASE_URL
21
21
  end
22
22
  uri = URI.parse(@_base_url)
23
- @_http = Net::HTTP.new(uri.host, uri.port)
23
+ @_http = Net::HTTP.new(uri.host, uri.port, proxy_address, proxy_port, proxy_user, proxy_pass)
24
24
  @_http.use_ssl = true if uri.scheme == 'https'
25
25
  @_http.open_timeout = 10 # in seconds
26
26
  @_http.read_timeout = 30 # in seconds
@@ -49,6 +49,7 @@ module ConfigCat
49
49
  @_lock.release_write_lock()
50
50
  end
51
51
  rescue StandardError => e
52
+ ConfigCat.logger.error("Double-check your API KEY at https://app.configcat.com/apikey.")
52
53
  ConfigCat.logger.error "threw exception #{e.class}:'#{e}'"
53
54
  ConfigCat.logger.error "stacktrace: #{e.backtrace}"
54
55
  end
@@ -29,6 +29,7 @@ module ConfigCat
29
29
  @_lock.release_write_lock()
30
30
  end
31
31
  rescue StandardError => e
32
+ ConfigCat.logger.error("Double-check your API KEY at https://app.configcat.com/apikey.")
32
33
  ConfigCat.logger.error "threw exception #{e.class}:'#{e}'"
33
34
  ConfigCat.logger.error "stacktrace: #{e.backtrace}"
34
35
  end
@@ -1,71 +1,172 @@
1
1
  require 'configcat/user'
2
2
  require 'digest'
3
+ require 'semantic'
3
4
 
4
5
  module ConfigCat
5
6
  class RolloutEvaluator
7
+ COMPARATOR_TEXTS = ["IS ONE OF", "IS NOT ONE OF", "CONTAINS", "DOES NOT CONTAIN", "IS ONE OF (SemVer)", "IS NOT ONE OF (SemVer)", "< (SemVer)", "<= (SemVer)", "> (SemVer)", ">= (SemVer)", "= (Number)", "<> (Number)", "< (Number)", "<= (Number)", "> (Number)", ">= (Number)"]
8
+
9
+ VALUE = "v"
10
+ COMPARATOR = "t"
11
+ COMPARISON_ATTRIBUTE = "a"
12
+ COMPARISON_VALUE = "c"
13
+ ROLLOUT_PERCENTAGE_ITEMS = "p"
14
+ PERCENTAGE = "p"
15
+ ROLLOUT_RULES = "r"
6
16
 
7
17
  def self.evaluate(key, user, default_value, config)
8
- if !user.equal?(nil) && !user.class.equal?(User)
9
- ConfigCat.logger.warn "User parameter is not an instance of User type."
10
- user = nil
11
- end
18
+ ConfigCat.logger.info("Evaluating get_value('%s')." % key)
19
+
12
20
  setting_descriptor = config.fetch(key, nil)
13
21
  if setting_descriptor === nil
14
- ConfigCat.logger.warn "Could not find setting by key, returning default value. Key: #{key}"
22
+ ConfigCat.logger.error("Evaluating get_value('%s') failed. Value not found for key '%s' Returning default_value: [%s]. Here are the available keys: %s" % [key, key, default_value.to_s, config.to_a.join(", ")])
15
23
  return default_value
16
24
  end
25
+
26
+ rollout_rules = setting_descriptor.fetch(ROLLOUT_RULES, [])
27
+ rollout_percentage_items = setting_descriptor.fetch(ROLLOUT_PERCENTAGE_ITEMS, [])
28
+
29
+ if !user.equal?(nil) && !user.class.equal?(User)
30
+ ConfigCat.logger.warn("Evaluating get_value('%s'). User Object is not an instance of User type." % key)
31
+ user = nil
32
+ end
17
33
  if user === nil
18
- return setting_descriptor.fetch("Value", default_value)
34
+ if rollout_rules.size > 0 || rollout_percentage_items.size > 0
35
+ ConfigCat.logger.warn("Evaluating get_value('%s'). UserObject missing! You should pass a UserObject to get_value(), in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/" % key)
36
+ end
37
+ return_value = setting_descriptor.fetch(VALUE, default_value)
38
+ ConfigCat.logger.info("Returning [%s]" % return_value.to_s)
39
+ return return_value
19
40
  end
20
- rollout_rules = setting_descriptor.fetch("RolloutRules", [])
41
+
42
+ ConfigCat.logger.info("User object:\n%s" % user.to_s)
43
+
44
+ # Evaluate targeting rules
21
45
  for rollout_rule in rollout_rules
22
- comparison_attribute = rollout_rule.fetch("ComparisonAttribute")
46
+ comparison_attribute = rollout_rule.fetch(COMPARISON_ATTRIBUTE)
47
+ comparison_value = rollout_rule.fetch(COMPARISON_VALUE, nil)
48
+ comparator = rollout_rule.fetch(COMPARATOR, nil)
49
+
23
50
  user_value = user.get_attribute(comparison_attribute)
24
51
  if user_value === nil || !user_value
52
+ ConfigCat.logger.info(format_no_match_rule(comparison_attribute, comparator, comparison_value))
25
53
  next
26
54
  end
27
- comparison_value = rollout_rule.fetch("ComparisonValue", nil)
28
- comparator = rollout_rule.fetch("Comparator", nil)
29
- value = rollout_rule.fetch("Value", nil)
55
+
56
+ value = rollout_rule.fetch(VALUE, nil)
57
+
58
+ # IS ONE OF
30
59
  if comparator == 0
31
60
  if comparison_value.to_s.split(",").map { |x| x.strip() }.include?(user_value.to_s)
61
+ ConfigCat.logger.info(format_match_rule(comparison_attribute, comparator, comparison_value, value))
62
+ return value
63
+ end
64
+ # IS NOT ONE OF
65
+ elsif comparator == 1
66
+ if !comparison_value.to_s.split(",").map { |x| x.strip() }.include?(user_value.to_s)
67
+ ConfigCat.logger.info(format_match_rule(comparison_attribute, comparator, comparison_value, value))
32
68
  return value
33
69
  end
34
- else
35
- if comparator == 1
36
- if !comparison_value.to_s.split(",").map { |x| x.strip() }.include?(user_value.to_s)
70
+ # CONTAINS
71
+ elsif comparator == 2
72
+ if user_value.to_s.include?(comparison_value.to_s)
73
+ ConfigCat.logger.info(format_match_rule(comparison_attribute, comparator, comparison_value, value))
74
+ return value
75
+ end
76
+ # DOES NOT CONTAIN
77
+ elsif comparator == 3
78
+ if !user_value.to_s.include?(comparison_value.to_s)
79
+ ConfigCat.logger.info(format_match_rule(comparison_attribute, comparator, comparison_value, value))
80
+ return value
81
+ end
82
+ # IS ONE OF, IS NOT ONE OF (Semantic version)
83
+ elsif (4 <= comparator) && (comparator <= 5)
84
+ begin
85
+ match = false
86
+ user_value_version = Semantic::Version.new(user_value.to_s.strip())
87
+ ((comparison_value.to_s.split(",").map { |x| x.strip() }).reject { |c| c.empty? }).each { |x|
88
+ version = Semantic::Version.new(x)
89
+ match = (user_value_version == version) || match
90
+ }
91
+ if match && comparator == 4 || !match && comparator == 5
92
+ ConfigCat.logger.info(format_match_rule(comparison_attribute, comparator, comparison_value, value))
37
93
  return value
38
94
  end
39
- else
40
- if comparator == 2
41
- if user_value.to_s.include?(comparison_value.to_s)
42
- return value
43
- end
44
- else
45
- if comparator == 3
46
- if !user_value.to_s.include?(comparison_value.to_s)
47
- return value
48
- end
49
- end
95
+ rescue ArgumentError => e
96
+ ConfigCat.logger.warn(format_validation_error_rule(comparison_attribute, comparator, comparison_value, e.to_s))
97
+ next
98
+ end
99
+ # LESS THAN, LESS THAN OR EQUALS TO, GREATER THAN, GREATER THAN OR EQUALS TO (Semantic version)
100
+ elsif (6 <= comparator) && (comparator <= 9)
101
+ begin
102
+ user_value_version = Semantic::Version.new(user_value.to_s.strip())
103
+ comparison_value_version = Semantic::Version.new(comparison_value.to_s.strip())
104
+ if (comparator == 6 && user_value_version < comparison_value_version) ||
105
+ (comparator == 7 && user_value_version <= comparison_value_version) ||
106
+ (comparator == 8 && user_value_version > comparison_value_version) ||
107
+ (comparator == 9 && user_value_version >= comparison_value_version)
108
+ ConfigCat.logger.info(format_match_rule(comparison_attribute, comparator, comparison_value, value))
109
+ return value
50
110
  end
111
+ rescue ArgumentError => e
112
+ ConfigCat.logger.warn(format_validation_error_rule(comparison_attribute, comparator, comparison_value, e.to_s))
113
+ next
114
+ end
115
+ elsif (10 <= comparator) && (comparator <= 15)
116
+ begin
117
+ user_value_float = Float(user_value.to_s.gsub(",", "."))
118
+ comparison_value_float = Float(comparison_value.to_s.gsub(",", "."))
119
+ if (comparator == 10 && user_value_float == comparison_value_float) ||
120
+ (comparator == 11 && user_value_float != comparison_value_float) ||
121
+ (comparator == 12 && user_value_float < comparison_value_float) ||
122
+ (comparator == 13 && user_value_float <= comparison_value_float) ||
123
+ (comparator == 14 && user_value_float > comparison_value_float) ||
124
+ (comparator == 15 && user_value_float >= comparison_value_float)
125
+ ConfigCat.logger.info(format_match_rule(comparison_attribute, comparator, comparison_value, value))
126
+ return value
127
+ end
128
+ rescue Exception => e
129
+ ConfigCat.logger.warn(format_validation_error_rule(comparison_attribute, comparator, comparison_value, e.to_s))
130
+ next
51
131
  end
52
132
  end
133
+
134
+ ConfigCat.logger.info(format_no_match_rule(comparison_attribute, comparator, comparison_value))
53
135
  end
54
- rollout_percentage_items = setting_descriptor.fetch("RolloutPercentageItems", [])
136
+
55
137
  if rollout_percentage_items.size > 0
56
138
  user_key = user.get_identifier()
57
139
  hash_candidate = ("%s%s" % [key, user_key]).encode("utf-8")
58
140
  hash_val = Digest::SHA1.hexdigest(hash_candidate)[0...7].to_i(base=16) % 100
59
141
  bucket = 0
60
142
  for rollout_percentage_item in rollout_percentage_items || []
61
- bucket += rollout_percentage_item.fetch("Percentage", 0)
143
+ bucket += rollout_percentage_item.fetch(PERCENTAGE, 0)
62
144
  if hash_val < bucket
63
- return rollout_percentage_item.fetch("Value", nil)
145
+ percentage_value = rollout_percentage_item.fetch(VALUE, nil)
146
+ ConfigCat.logger.info("Evaluating %% options. Returning %s" % percentage_value)
147
+ return percentage_value
64
148
  end
65
149
  end
66
150
  end
67
- return setting_descriptor.fetch("Value", default_value)
151
+ def_value = setting_descriptor.fetch(VALUE, default_value)
152
+ ConfigCat.logger.info("Returning %s" % def_value)
153
+ return def_value
68
154
  end
155
+
156
+ private
157
+
158
+ def self.format_match_rule(comparison_attribute, comparator, comparison_value, value)
159
+ return "Evaluating rule: [%s] [%s] [%s] => match, returning: %s" % [comparison_attribute, COMPARATOR_TEXTS[comparator], comparison_value, value]
160
+ end
161
+
162
+ def self.format_no_match_rule(comparison_attribute, comparator, comparison_value)
163
+ return "Evaluating rule: [%s] [%s] [%s] => no match" % [comparison_attribute, COMPARATOR_TEXTS[comparator], comparison_value]
164
+ end
165
+
166
+ def self.format_validation_error_rule(comparison_attribute, comparator, comparison_value, error)
167
+ return "Evaluating rule: [%s] [%s] [%s] => SKIP rule. Validation error: %s" % [comparison_attribute, COMPARATOR_TEXTS[comparator], comparison_value, error]
168
+ end
169
+
69
170
  end
70
171
 
71
172
  end
@@ -1,3 +1,3 @@
1
1
  module ConfigCat
2
- VERSION = "1.0.1"
2
+ VERSION = "1.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configcat
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ConfigCat
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-14 00:00:00.000000000 Z
11
+ date: 2019-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: semantic
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rspec
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,20 @@ dependencies:
52
66
  - - ">="
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: coveralls
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  description: ConfigCat is a configuration as a service that lets you manage your features
56
84
  and configurations without actually deploying new code.
57
85
  email: