prefab-cloud-ruby 0.24.1 → 0.24.3

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: 9b54e4d5e0b52064cc19b41e33d9c7552cc8534bcab59cc42b48e4fc77fd5b58
4
- data.tar.gz: bd6901fcb99e35fc859ae382fb7d0354c1cd484fb75a1dbba27d0d0e07cdb397
3
+ metadata.gz: 29a3d9257f166fad534f81a44879cd82abc0cdd729714ab6feb2423d7b913a4d
4
+ data.tar.gz: b11f8e29260760dd64a78f26c016bd936fe0a5e75100329c645915bddd094ebc
5
5
  SHA512:
6
- metadata.gz: 96249d926438ccf2b4c239ae3b65a3649bb8b8e279e05774431376188b9ee330e71211f52bb7a51d5edf457be1997bfb5609e2a91debde4a2719f9ff4f34ae4a
7
- data.tar.gz: fd42fd6be60e9572eb5a857253eabbb44693d46927ecef0b57ed72213c1af875511c4b2ad86bd5e7257e75ac063bde78a49f03f62a0d0350348d18d696d4a59d
6
+ metadata.gz: f74cda2cf6f657f72c15d118d9fb622d24d049261436691bff28e42ad5656beb53ec192e148e30e0f025a5becb094682fc68f4860c2cf5b3ed351b7954e3b587
7
+ data.tar.gz: 90125b61cd874c12376eecc726aa2fef0d6158565150830f95f642f97fad849b53570238593ce617dc39b05960abb47d4c2e6cd4a974e30c69fc40ec2720958b
data/README.md CHANGED
@@ -41,7 +41,7 @@ $prefab.set_rails_loggers
41
41
  ```ruby
42
42
  #puma.rb
43
43
  on_worker_boot do
44
- $prefab = Prefab::Client.new
44
+ $prefab = $prefab.fork
45
45
  $prefab.set_rails_loggers
46
46
  end
47
47
  ```
@@ -49,7 +49,7 @@ end
49
49
  ```ruby
50
50
  # unicorn.rb
51
51
  after_fork do |server, worker|
52
- $prefab = Prefab::Client.new(options)
52
+ $prefab = $prefab.fork
53
53
  $prefab.set_rails_loggers
54
54
  end
55
55
  ```
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.24.1
1
+ 0.24.3
data/lib/prefab/client.rb CHANGED
@@ -111,6 +111,15 @@ module Prefab
111
111
  config_client.resolver
112
112
  end
113
113
 
114
+ # When starting a forked process, use this to re-use the options
115
+ # on_worker_boot do
116
+ # $prefab = $prefab.fork
117
+ # $prefab.set_rails_loggers
118
+ # end
119
+ def fork
120
+ Prefab::Client.new(@options)
121
+ end
122
+
114
123
  private
115
124
 
116
125
  def is_ff?(key)
@@ -55,10 +55,11 @@ module Prefab
55
55
  end
56
56
 
57
57
  def get(key, default = NO_DEFAULT_PROVIDED, properties = NO_DEFAULT_PROVIDED)
58
- value = _get(key, properties)
58
+ context = @config_resolver.make_context(properties)
59
+ value = _get(key, context)
59
60
 
60
61
  if value
61
- Prefab::ConfigValueUnwrapper.unwrap(value, key, properties)
62
+ Prefab::ConfigValueUnwrapper.unwrap(value, key, context)
62
63
  else
63
64
  handle_default(key, default)
64
65
  end
@@ -42,7 +42,7 @@ module Prefab
42
42
  project_env_id: @project_env_id,
43
43
  resolver: self,
44
44
  namespace: @base_client.options.namespace,
45
- base_client: @base_client).evaluate(context(properties))
45
+ base_client: @base_client).evaluate(make_context(properties))
46
46
  end
47
47
 
48
48
  def update
@@ -55,9 +55,7 @@ module Prefab
55
55
  @on_update = block
56
56
  end
57
57
 
58
- private
59
-
60
- def context(properties)
58
+ def make_context(properties)
61
59
  if properties == NO_DEFAULT_PROVIDED
62
60
  Context.current
63
61
  elsif properties.is_a?(Context)
@@ -67,6 +65,8 @@ module Prefab
67
65
  end
68
66
  end
69
67
 
68
+ private
69
+
70
70
  def make_local
71
71
  @lock.with_write_lock do
72
72
  @local_store = @config_loader.calc_config
@@ -14,7 +14,7 @@ module Prefab
14
14
  value = Prefab::WeightedValueResolver.new(
15
15
  config_value.weighted_values.weighted_values,
16
16
  config_key,
17
- context[config_value.weighted_values.hash_by_property_name]
17
+ context.get(config_value.weighted_values.hash_by_property_name)
18
18
  ).resolve
19
19
 
20
20
  unwrap(value.value, config_key, context)
@@ -77,18 +77,10 @@ module Prefab
77
77
  end
78
78
  end
79
79
 
80
- def merge!(name, hash)
81
- @contexts[name.to_s] = context(name).merge!(hash)
82
- end
83
-
84
80
  def set(name, hash)
85
81
  @contexts[name.to_s] = NamedContext.new(name, hash)
86
82
  end
87
83
 
88
- def []=(name, hash)
89
- set(name, hash)
90
- end
91
-
92
84
  def get(property_key)
93
85
  name, key = property_key.split('.', 2)
94
86
 
@@ -100,10 +92,6 @@ module Prefab
100
92
  contexts[name] && contexts[name].get(key)
101
93
  end
102
94
 
103
- def [](property_key)
104
- get(property_key)
105
- end
106
-
107
95
  def to_h
108
96
  contexts.map { |name, context| [name, context.to_h] }.to_h
109
97
  end
@@ -53,8 +53,9 @@ module Prefab
53
53
 
54
54
  return true if @logdev.nil? || severity < level_of(path) || @silences[local_log_id]
55
55
 
56
- progname = "#{path}: #{progname || @progname}"
57
-
56
+ if progname.nil?
57
+ progname = @progname
58
+ end
58
59
  if message.nil?
59
60
  if block_given?
60
61
  message = yield
@@ -65,7 +66,7 @@ module Prefab
65
66
  end
66
67
 
67
68
  @logdev.write(
68
- format_message(format_severity(severity), Time.now, progname, message)
69
+ format_message(format_severity(severity), Time.now, progname, message, path)
69
70
  )
70
71
  true
71
72
  end
@@ -169,6 +170,20 @@ module Prefab
169
170
  path.slice! SEP
170
171
  path
171
172
  end
173
+
174
+ def format_message(severity, datetime, progname, msg, path)
175
+ formatter = (@formatter || @default_formatter)
176
+
177
+ if formatter.arity == 5
178
+ formatter.call(severity, datetime, progname, msg, path)
179
+ else
180
+ formatter.call(severity, datetime, join_path_and_progname(path, progname), msg)
181
+ end
182
+ end
183
+
184
+ def join_path_and_progname(path, progname)
185
+ (progname.nil? || progname.empty?) ? path : "#{progname}: #{path}"
186
+ end
172
187
  end
173
188
 
174
189
  # StubConfigClient to be used while config client initializes
@@ -21,6 +21,15 @@ module Prefab
21
21
  DEFAULT_LOG_FORMATTER = proc { |severity, datetime, progname, msg|
22
22
  "#{severity.ljust(5)} #{datetime}:#{' ' if progname}#{progname} #{msg}\n"
23
23
  }
24
+ JSON_LOG_FORMATTER = proc { |severity, datetime, progname, msg, path|
25
+ {
26
+ type: severity,
27
+ time: datetime,
28
+ progname: progname,
29
+ message: msg,
30
+ path: path
31
+ }.compact.to_json << "\n"
32
+ }
24
33
 
25
34
  module ON_INITIALIZATION_FAILURE
26
35
  RAISE = 1
@@ -45,7 +45,7 @@ module Prefab
45
45
  hash[k] = ConfigRow.new(k, nil, nil, nil)
46
46
  else
47
47
  config = @resolver.evaluate(v[:config])
48
- value = Prefab::ConfigValueUnwrapper.unwrap(config, k, {})
48
+ value = Prefab::ConfigValueUnwrapper.unwrap(config, k, Prefab::Context.new)
49
49
  hash[k] = ConfigRow.new(k, value, v[:match], v[:source])
50
50
  end
51
51
  end
@@ -67,7 +67,7 @@ module Prefab
67
67
  elements << 'tombstone'
68
68
  else
69
69
  config = @resolver.evaluate(v[:config], {})
70
- value = Prefab::ConfigValueUnwrapper.unwrap(config, k, {})
70
+ value = Prefab::ConfigValueUnwrapper.unwrap(config, k, Prefab::Context.new)
71
71
  elements << value.to_s.slice(0..34).ljust(35)
72
72
  elements << value.class.to_s.slice(0..6).ljust(7)
73
73
  elements << "Match: #{v[:match]}".slice(0..29).ljust(30)
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: prefab-cloud-ruby 0.24.1 ruby lib
5
+ # stub: prefab-cloud-ruby 0.24.3 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "prefab-cloud-ruby".freeze
9
- s.version = "0.24.1"
9
+ s.version = "0.24.3"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Jeff Dwyer".freeze]
14
- s.date = "2023-04-26"
14
+ s.date = "2023-05-15"
15
15
  s.description = "Feature Flags, Live Config, and Dynamic Log Levels as a service".freeze
16
16
  s.email = "jdwyer@prefab.cloud".freeze
17
17
  s.extra_rdoc_files = [
@@ -12,7 +12,9 @@ class IntegrationTest
12
12
  end
13
13
 
14
14
  def test_type
15
- if @expected[:status] == 'raise'
15
+ if @input[0] && @input[0].start_with?('log-level.')
16
+ :log_level
17
+ elsif @expected[:status] == 'raise'
16
18
  :raise
17
19
  elsif @expected[:value].nil?
18
20
  :nil
@@ -4,45 +4,46 @@ require 'test_helper'
4
4
 
5
5
  class TestConfigValueUnwrapper < Minitest::Test
6
6
  CONFIG_KEY = 'config_key'
7
+ EMPTY_CONTEXT = Prefab::Context.new()
7
8
 
8
9
  def test_unwrapping_int
9
10
  config_value = Prefab::ConfigValue.new(int: 123)
10
- assert_equal 123, Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, {})
11
+ assert_equal 123, Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, EMPTY_CONTEXT)
11
12
  end
12
13
 
13
14
  def test_unwrapping_string
14
15
  config_value = Prefab::ConfigValue.new(string: 'abc')
15
- assert_equal 'abc', Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, {})
16
+ assert_equal 'abc', Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, EMPTY_CONTEXT)
16
17
  end
17
18
 
18
19
  def test_unwrapping_double
19
20
  config_value = Prefab::ConfigValue.new(double: 1.23)
20
- assert_equal 1.23, Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, {})
21
+ assert_equal 1.23, Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, EMPTY_CONTEXT)
21
22
  end
22
23
 
23
24
  def test_unwrapping_bool
24
25
  config_value = Prefab::ConfigValue.new(bool: true)
25
- assert_equal true, Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, {})
26
+ assert_equal true, Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, EMPTY_CONTEXT)
26
27
 
27
28
  config_value = Prefab::ConfigValue.new(bool: false)
28
- assert_equal false, Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, {})
29
+ assert_equal false, Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, EMPTY_CONTEXT)
29
30
  end
30
31
 
31
32
  def test_unwrapping_log_level
32
33
  config_value = Prefab::ConfigValue.new(log_level: :INFO)
33
- assert_equal :INFO, Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, {})
34
+ assert_equal :INFO, Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, EMPTY_CONTEXT)
34
35
  end
35
36
 
36
37
  def test_unwrapping_string_list
37
38
  config_value = Prefab::ConfigValue.new(string_list: Prefab::StringList.new(values: %w[a b c]))
38
- assert_equal %w[a b c], Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, {})
39
+ assert_equal %w[a b c], Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, EMPTY_CONTEXT)
39
40
  end
40
41
 
41
42
  def test_unwrapping_weighted_values
42
43
  # single value
43
44
  config_value = Prefab::ConfigValue.new(weighted_values: weighted_values([['abc', 1]]))
44
45
 
45
- assert_equal 'abc', Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, {})
46
+ assert_equal 'abc', Prefab::ConfigValueUnwrapper.unwrap(config_value, CONFIG_KEY, EMPTY_CONTEXT)
46
47
 
47
48
  # multiple values, evenly distributed
48
49
  config_value = Prefab::ConfigValue.new(weighted_values: weighted_values([['abc', 1], ['def', 1], ['ghi', 1]]))
data/test/test_context.rb CHANGED
@@ -86,7 +86,7 @@ class TestContext < Minitest::Test
86
86
  Prefab::Context.with_context(EXAMPLE_PROPERTIES) do
87
87
  context = Prefab::Context.current
88
88
  assert_equal(stringify(EXAMPLE_PROPERTIES), context.to_h)
89
- assert_equal('some-user-key', context['user.key'])
89
+ assert_equal('some-user-key', context.get('user.key'))
90
90
  end
91
91
  end
92
92
 
@@ -105,34 +105,24 @@ class TestContext < Minitest::Test
105
105
  def test_setting
106
106
  context = Prefab::Context.new({})
107
107
  context.set('user', { key: 'value' })
108
- context[:other] = { key: 'different', something: 'other' }
108
+ context.set(:other, { key: 'different', something: 'other' })
109
109
  assert_equal(stringify({ user: { key: 'value' }, other: { key: 'different', something: 'other' } }), context.to_h)
110
110
  end
111
111
 
112
112
  def test_getting
113
113
  context = Prefab::Context.new(EXAMPLE_PROPERTIES)
114
114
  assert_equal('some-user-key', context.get('user.key'))
115
- assert_equal('some-user-key', context['user.key'])
116
115
  assert_equal('pro', context.get('team.plan'))
117
- assert_equal('pro', context['team.plan'])
118
116
  end
119
117
 
120
118
  def test_dot_notation_getting
121
119
  context = Prefab::Context.new({ 'user' => { 'key' => 'value' } })
122
120
  assert_equal('value', context.get('user.key'))
123
- assert_equal('value', context['user.key'])
124
121
  end
125
122
 
126
123
  def test_dot_notation_getting_with_symbols
127
124
  context = Prefab::Context.new({ user: { key: 'value' } })
128
125
  assert_equal('value', context.get('user.key'))
129
- assert_equal('value', context['user.key'])
130
- end
131
-
132
- def test_merge
133
- context = Prefab::Context.new(EXAMPLE_PROPERTIES)
134
- context.merge!(:other, { key: 'different' })
135
- assert_equal(stringify(EXAMPLE_PROPERTIES.merge(other: { key: 'different' })), context.to_h)
136
126
  end
137
127
 
138
128
  def test_clear
@@ -13,7 +13,7 @@ class TestIntegration < Minitest::Test
13
13
  parent_context = test['context']
14
14
 
15
15
  test['cases'].each do |test_case|
16
- define_method(:"test_#{test_case['name']}") do
16
+ define_method(:"test_#{test['name']}_#{test_case['name']}") do
17
17
  it = IntegrationTest.new(test_case)
18
18
 
19
19
  with_parent_context_maybe(parent_context) do
@@ -30,6 +30,10 @@ class TestIntegration < Minitest::Test
30
30
  assert_equal it.expected[:value], it.test_client.send(it.func, flag, context)
31
31
  when :simple_equality
32
32
  assert_equal it.expected[:value], it.test_client.send(it.func, *it.input)
33
+ when :log_level
34
+ assert_equal it.expected[:value].to_sym, it.test_client.send(it.func, *it.input)
35
+ else
36
+ raise "Unknown test type: #{it.test_type}"
33
37
  end
34
38
  end
35
39
  end
data/test/test_logger.rb CHANGED
@@ -85,46 +85,47 @@ class TestLogger < Minitest::Test
85
85
  end
86
86
 
87
87
  def test_log_internal
88
- logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- cloud.prefab.client.test.path: : test message/)
89
- logger.log_internal('test message', 'test.path', '', ::Logger::WARN)
90
- mock_logdev.verify
88
+ prefab, io = captured_logger
89
+ prefab.log.log_internal('test message', 'test.path', '', ::Logger::WARN)
90
+ assert_logged io, 'WARN', "cloud.prefab.client.test.path", "test message"
91
91
  end
92
92
 
93
93
  def test_log_internal_unknown
94
- logger, mock_logdev = mock_logger_expecting(/A, \[.*\] ANY -- cloud.prefab.client.test.path: : test message/)
95
- logger.log_internal('test message', 'test.path', '', ::Logger::UNKNOWN)
96
- mock_logdev.verify
94
+ prefab, io = captured_logger
95
+ prefab.log.log_internal('test message', 'test.path', '', ::Logger::UNKNOWN)
96
+ assert_logged io, 'ANY', "cloud.prefab.client.test.path", "test message"
97
97
  end
98
98
 
99
99
  def test_log_internal_silencing
100
- logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- cloud.prefab.client.test.path: : should log/,
101
- calls: 2)
102
- logger.silence do
103
- logger.log_internal('should not log', 'test.path', '', ::Logger::WARN)
100
+ prefab, io = captured_logger
101
+ prefab.log.silence do
102
+ prefab.log.log_internal('should not log', 'test.path', '', ::Logger::WARN)
104
103
  end
105
- logger.log_internal('should log', 'test.path', '', ::Logger::WARN)
106
- mock_logdev.verify
104
+ prefab.log.log_internal('should log', 'test.path', '', ::Logger::WARN)
105
+ assert_logged io, 'WARN', "cloud.prefab.client.test.path", "should log"
106
+ refute_logged io, 'should not log'
107
107
  end
108
108
 
109
109
  def test_log
110
- logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- test.path: : test message/)
111
- logger.log('test message', 'test.path', '', ::Logger::WARN)
112
- mock_logdev.verify
110
+ prefab, io = captured_logger
111
+ prefab.log.log('test message', 'test.path', '', ::Logger::WARN)
112
+ assert_logged io, 'WARN', "test.path", "test message"
113
113
  end
114
114
 
115
115
  def test_log_unknown
116
- logger, mock_logdev = mock_logger_expecting(/A, \[.*\] ANY -- test.path: : test message/)
117
- logger.log('test message', 'test.path', '', ::Logger::UNKNOWN)
118
- mock_logdev.verify
116
+ prefab, io = captured_logger
117
+ prefab.log.log('test message', 'test.path', '', ::Logger::UNKNOWN)
118
+ assert_logged io, 'ANY', "test.path", "test message"
119
119
  end
120
120
 
121
121
  def test_log_silencing
122
- logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- test.path: : should log/, calls: 2)
123
- logger.silence do
124
- logger.log('should not log', 'test.path', '', ::Logger::WARN)
122
+ prefab, io = captured_logger
123
+ prefab.log.silence do
124
+ prefab.log.log('should not log', 'test.path', '', ::Logger::WARN)
125
125
  end
126
- logger.log('should log', 'test.path', '', ::Logger::WARN)
127
- mock_logdev.verify
126
+ prefab.log.log('should log', 'test.path', '', ::Logger::WARN)
127
+ assert_logged io, 'WARN', "test.path", "should log"
128
+ refute_logged io, 'should not log'
128
129
  end
129
130
 
130
131
  def test_logging_with_prefix
@@ -163,7 +164,7 @@ class TestLogger < Minitest::Test
163
164
  prefab.log.progname = 'MY_PROGNAME'
164
165
  prefab.log.error message
165
166
 
166
- assert_logged io, 'ERROR', 'MY_PROGNAME test.test_logger.test_logging_with_a_progname', message
167
+ assert_logged io, 'ERROR', 'MY_PROGNAME: test.test_logger.test_logging_with_a_progname', message
167
168
  end
168
169
 
169
170
  def test_logging_with_a_progname_and_no_message
@@ -172,7 +173,7 @@ class TestLogger < Minitest::Test
172
173
  prefab.log.progname = 'MY_PROGNAME'
173
174
  prefab.log.error
174
175
 
175
- assert_logged io, 'ERROR', 'MY_PROGNAME test.test_logger.test_logging_with_a_progname_and_no_message', 'MY_PROGNAME'
176
+ assert_logged io, 'ERROR', 'MY_PROGNAME: test.test_logger.test_logging_with_a_progname_and_no_message', 'MY_PROGNAME'
176
177
  end
177
178
 
178
179
  def test_logging_with_criteria_on_top_level_key
@@ -399,35 +400,19 @@ class TestLogger < Minitest::Test
399
400
  raise 'THIS WILL NEVER BE EVALUATED'
400
401
  end
401
402
 
402
- assert_logged io, 'ERROR', 'test.test_logger.test_logging_with_a_block', ' ' + message
403
+ assert_logged io, 'ERROR', 'test.test_logger.test_logging_with_a_block', message
403
404
  end
404
405
 
405
406
  private
406
407
 
407
408
  def assert_logged(logged_io, level, path, message)
408
- assert_match(/#{level}\s+\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]?\d+:\s+#{path}: #{message}\n/, logged_io.string)
409
+ assert_match(/#{level}\s+\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]?\d+:\s+#{path} #{message}\n/, logged_io.string)
409
410
  end
410
411
 
411
412
  def refute_logged(logged_io, message)
412
413
  refute_match(/#{message}/, logged_io.string)
413
414
  end
414
415
 
415
- def mock_logger_expecting(pattern, configs = {}, calls: 1)
416
- mock_logdev = Minitest::Mock.new
417
- mock_logdev.expect :write, nil do |arg|
418
- pattern.match(arg)
419
- end
420
-
421
- calls.times.each do
422
- mock_logdev.expect(:nil?, false)
423
- end
424
-
425
- logger = Prefab::LoggerClient.new($stdout)
426
- logger.instance_variable_set('@logdev', mock_logdev)
427
- logger.set_config_client(MockConfigClient.new(configs))
428
- [logger, mock_logdev]
429
- end
430
-
431
416
  def captured_logger(options = {})
432
417
  io = StringIO.new
433
418
  options = Prefab::Options.new(**options.merge(
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prefab-cloud-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.24.1
4
+ version: 0.24.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Dwyer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-26 00:00:00.000000000 Z
11
+ date: 2023-05-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby