cloudenvoy 0.4.2 → 0.6.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/lint_rubocop.yml +20 -0
  3. data/.github/workflows/{test.yml → test_ruby_2.5_2.6.yml} +8 -13
  4. data/.github/workflows/test_ruby_2.7.yml +36 -0
  5. data/.github/workflows/test_ruby_3.x.yml +35 -0
  6. data/.gitignore +1 -0
  7. data/.rubocop.yml +17 -16
  8. data/Appraisals +24 -4
  9. data/CHANGELOG.md +18 -0
  10. data/README.md +39 -2
  11. data/cloudenvoy.gemspec +2 -6
  12. data/examples/rails/.ruby-version +1 -1
  13. data/examples/rails/Gemfile +4 -1
  14. data/examples/rails/Gemfile.lock +92 -85
  15. data/examples/rails/README.md +5 -1
  16. data/examples/rails/app/subscribers/hello_subscriber.rb +1 -1
  17. data/examples/rails/config/environments/production.rb +1 -1
  18. data/examples/rails/config/puma.rb +3 -3
  19. data/examples/sinatra/Gemfile +4 -1
  20. data/examples/sinatra/Gemfile.lock +40 -28
  21. data/examples/sinatra/README.md +4 -0
  22. data/examples/sinatra/app/subscribers/hello_subscriber.rb +1 -1
  23. data/examples/sinatra/app.rb +4 -4
  24. data/gemfiles/.bundle/config +2 -0
  25. data/gemfiles/rails_5.2.gemfile +1 -0
  26. data/gemfiles/rails_6.0.gemfile +1 -0
  27. data/gemfiles/rails_6.1.gemfile +8 -0
  28. data/gemfiles/rails_7.0.gemfile +8 -0
  29. data/gemfiles/semantic_logger_3.4.gemfile +1 -0
  30. data/gemfiles/semantic_logger_4.6.gemfile +1 -0
  31. data/gemfiles/semantic_logger_4.7.0.gemfile +1 -0
  32. data/gemfiles/semantic_logger_4.7.2.gemfile +1 -0
  33. data/lib/cloudenvoy/backend/google_pub_sub.rb +37 -5
  34. data/lib/cloudenvoy/backend/memory_pub_sub.rb +25 -1
  35. data/lib/cloudenvoy/config.rb +1 -1
  36. data/lib/cloudenvoy/message.rb +2 -2
  37. data/lib/cloudenvoy/pub_sub_client.rb +13 -1
  38. data/lib/cloudenvoy/publisher.rb +39 -5
  39. data/lib/cloudenvoy/publisher_logger.rb +1 -1
  40. data/lib/cloudenvoy/version.rb +1 -1
  41. data/lib/cloudenvoy.rb +13 -0
  42. metadata +15 -57
  43. data/gemfiles/rails_5.2.gemfile.lock +0 -264
  44. data/gemfiles/rails_6.0.gemfile.lock +0 -280
  45. data/gemfiles/semantic_logger_3.4.gemfile.lock +0 -279
  46. data/gemfiles/semantic_logger_4.6.gemfile.lock +0 -279
  47. data/gemfiles/semantic_logger_4.7.0.gemfile.lock +0 -279
  48. data/gemfiles/semantic_logger_4.7.2.gemfile.lock +0 -279
@@ -32,7 +32,7 @@ module Cloudenvoy
32
32
  # @return [Google::Cloud::Pub] The low level client instance.
33
33
  #
34
34
  def backend
35
- @backend ||= Google::Cloud::PubSub.new({
35
+ @backend ||= Google::Cloud::PubSub.new(**{
36
36
  project_id: config.gcp_project_id,
37
37
  emulator_host: development? ? Cloudenvoy::Config::EMULATOR_HOST : nil
38
38
  }.compact)
@@ -54,7 +54,7 @@ module Cloudenvoy
54
54
  # @param [Hash, String] payload The message content.
55
55
  # @param [Hash] metadata The message attributes.
56
56
  #
57
- # @return [Cloudenvoy::Message] The created message.
57
+ # @return [Cloudenvoy::Message] The published message.
58
58
  #
59
59
  def publish(topic, payload, metadata = {})
60
60
  # Retrieve the topic
@@ -72,6 +72,38 @@ module Cloudenvoy
72
72
  )
73
73
  end
74
74
 
75
+ #
76
+ # Publish multiple messages to a topic.
77
+ #
78
+ # @param [String] topic The name of the topic
79
+ # @param [Array<Array<[Hash, String]>>] msg_args A list of message [payload, metadata].
80
+ #
81
+ # @return [Array<Cloudenvoy::Message>] The published messages.
82
+ #
83
+ def publish_all(topic, msg_args)
84
+ # Retrieve the topic
85
+ ps_topic = backend.topic(topic, skip_lookup: true)
86
+
87
+ # Publish the message
88
+ ps_msgs = ps_topic.publish do |batch|
89
+ msg_args.each do |(payload, metadata)|
90
+ batch.publish(payload.to_json, metadata.to_h)
91
+ end
92
+ end
93
+
94
+ # Return the formatted messages
95
+ ps_msgs.each_with_index.map do |ps_msg, index|
96
+ payload, metadata = msg_args[index]
97
+
98
+ Message.new(
99
+ id: ps_msg.message_id,
100
+ payload: payload,
101
+ metadata: metadata,
102
+ topic: topic
103
+ )
104
+ end
105
+ end
106
+
75
107
  #
76
108
  # Create or update a subscription for a specific topic.
77
109
  #
@@ -109,7 +141,7 @@ module Cloudenvoy
109
141
  ps_topic = backend.topic(topic, skip_lookup: true)
110
142
 
111
143
  # Attempt to create the subscription
112
- ps_topic.subscribe(name, sub_config)
144
+ ps_topic.subscribe(name, **sub_config)
113
145
  rescue Google::Cloud::AlreadyExistsError
114
146
  # Update endpoint on subscription
115
147
  # Topic is not updated as it is name-dependent
@@ -134,8 +166,8 @@ module Cloudenvoy
134
166
  def upsert_topic(topic)
135
167
  ps_topic = begin
136
168
  backend.create_topic(topic)
137
- rescue Google::Cloud::AlreadyExistsError
138
- backend.topic(topic)
169
+ rescue Google::Cloud::AlreadyExistsError
170
+ backend.topic(topic)
139
171
  end
140
172
 
141
173
  # Return formatted subscription
@@ -47,7 +47,7 @@ module Cloudenvoy
47
47
  # @param [Hash, String] payload The message content.
48
48
  # @param [Hash] attrs The message attributes.
49
49
  #
50
- # @return [Cloudenvoy::Message] The created message.
50
+ # @return [Cloudenvoy::Message] The published message.
51
51
  #
52
52
  def publish(topic, payload, metadata = {})
53
53
  msg = Message.new(
@@ -61,6 +61,30 @@ module Cloudenvoy
61
61
  msg
62
62
  end
63
63
 
64
+ #
65
+ # Publish multiple messages to a topic.
66
+ #
67
+ # @param [String] topic The name of the topic
68
+ # @param [Array<Array<[Hash, String]>>] msg_args A list of message [payload, metadata].
69
+ #
70
+ # @return [Array<Cloudenvoy::Message>] The published messages.
71
+ #
72
+ def publish_all(topic, msg_args)
73
+ # Build the messages
74
+ msgs = msg_args.map do |(payload, metadata)|
75
+ Message.new(
76
+ id: SecureRandom.uuid,
77
+ payload: payload,
78
+ metadata: metadata,
79
+ topic: topic
80
+ )
81
+ end
82
+
83
+ # Push all the messages and return them
84
+ queue(topic).push(*msgs)
85
+ msgs
86
+ end
87
+
64
88
  #
65
89
  # Create or update a subscription for a specific topic.
66
90
  #
@@ -57,7 +57,7 @@ module Cloudenvoy
57
57
  # @return [Logger, any] The cloudenvoy logger.
58
58
  #
59
59
  def logger
60
- @logger ||= defined?(Rails) ? Rails.logger : ::Logger.new(STDOUT)
60
+ @logger ||= defined?(Rails) ? Rails.logger : ::Logger.new($stdout)
61
61
  end
62
62
 
63
63
  #
@@ -75,8 +75,8 @@ module Cloudenvoy
75
75
  def to_h
76
76
  {
77
77
  id: id,
78
- payload: payload&.dup,
79
- metadata: metadata&.dup,
78
+ payload: payload.dup,
79
+ metadata: metadata.dup,
80
80
  topic: topic,
81
81
  sub_uri: sub_uri
82
82
  }.compact
@@ -30,12 +30,24 @@ module Cloudenvoy
30
30
  # @param [Hash, String] payload The message content.
31
31
  # @param [Hash] attrs The message attributes.
32
32
  #
33
- # @return [Cloudenvoy::Message] The created message.
33
+ # @return [Cloudenvoy::Message] The published message.
34
34
  #
35
35
  def self.publish(topic, payload, attrs = {})
36
36
  backend.publish(topic, payload, attrs)
37
37
  end
38
38
 
39
+ #
40
+ # Publish multiple messages to a topic.
41
+ #
42
+ # @param [String] topic The name of the topic
43
+ # @param [Array<Array<[Hash, String]>>] msg_args A list of message [payload, metadata].
44
+ #
45
+ # @return [Array<Cloudenvoy::Message>] The published messages.
46
+ #
47
+ def self.publish_all(topic, msg_args)
48
+ backend.publish_all(topic, msg_args)
49
+ end
50
+
39
51
  #
40
52
  # Create or update a subscription for a specific topic.
41
53
  #
@@ -89,6 +89,40 @@ module Cloudenvoy
89
89
 
90
90
  PubSubClient.upsert_topic(default_topic)
91
91
  end
92
+
93
+ #
94
+ # Publish all messages in one batch.
95
+ #
96
+ # @param [Array<Any>] The list of publisher arguments.
97
+ #
98
+ # @return [Array<Cloudenvoy::Message>] The published messages.
99
+ #
100
+ def publish_all(arg_list)
101
+ # Build the list of publishers
102
+ publishers = arg_list.map { |e| new(msg_args: [e].flatten(1)) }
103
+
104
+ # Batches are topic specific. We must send one batch of messages per topic.
105
+ publishers.group_by { |e| e.topic(*e.msg_args) }.map do |topic, topic_publishers|
106
+ # Chain publish calls. The very last call (when the chain becomes empty)
107
+ # is the actual batch publishing of messages to pub/sub
108
+ chain = topic_publishers.dup
109
+ traverse_chain = lambda do
110
+ if chain.empty?
111
+ # Send the messages in one batch and retrospectively attach them
112
+ # to each publisher
113
+ arg_list = topic_publishers.map { |e| [e.payload(*e.msg_args), e.metadata(*e.msg_args)] }
114
+ PubSubClient.publish_all(topic, arg_list).each_with_index do |msg, pub_index|
115
+ topic_publishers[pub_index].message = msg
116
+ end
117
+ else
118
+ # Defer message publishing to the next element
119
+ # in the chain until the chain is empty
120
+ chain.shift.publish(&traverse_chain)
121
+ end
122
+ end
123
+ traverse_chain.call
124
+ end.flatten
125
+ end
92
126
  end
93
127
 
94
128
  #
@@ -155,9 +189,9 @@ module Cloudenvoy
155
189
  #
156
190
  # @return [Cloudenvoy::Message] The created message.
157
191
  #
158
- def publish
192
+ def publish(&block)
159
193
  # Format and publish message
160
- resp = execute_middleware_chain
194
+ resp = execute_middleware_chain(&block)
161
195
 
162
196
  # Log job completion and return result
163
197
  logger.info("Published message in #{publishing_duration}s") { { duration: publishing_duration } }
@@ -191,14 +225,14 @@ module Cloudenvoy
191
225
  #
192
226
  # Execute the subscriber process method through the middleware chain.
193
227
  #
194
- # @return [Any] The result of the perform method.
228
+ # @return [Cloudenvoy::Message] The published message.
195
229
  #
196
- def execute_middleware_chain
230
+ def execute_middleware_chain(&block)
197
231
  self.publishing_started_at = Time.now
198
232
 
199
233
  Cloudenvoy.config.publisher_middleware.invoke(self) do
200
234
  begin
201
- publish_message
235
+ block_given? ? block.call : publish_message
202
236
  rescue StandardError => e
203
237
  logger.error([e, e.backtrace.join("\n")].join("\n"))
204
238
  try(:on_error, e)
@@ -9,7 +9,7 @@ module Cloudenvoy
9
9
  # @return [Proc] The context processor proc.
10
10
  #
11
11
  def self.default_context_processor
12
- @default_context_processor ||= ->(loggable) { loggable.message&.to_h&.slice(:id, :metadata, :topic) || {} }
12
+ @default_context_processor ||= ->(loggable) { loggable.message.to_h&.slice(:id, :metadata, :topic) || {} }
13
13
  end
14
14
 
15
15
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cloudenvoy
4
- VERSION = '0.4.2'
4
+ VERSION = '0.6.rc1'
5
5
  end
data/lib/cloudenvoy.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_support/core_ext/string/inflections'
4
+ require 'active_support/core_ext/object/try'
4
5
 
5
6
  require 'cloudenvoy/version'
6
7
  require 'cloudenvoy/config'
@@ -62,6 +63,18 @@ module Cloudenvoy
62
63
  PubSubClient.publish(topic, payload, attrs)
63
64
  end
64
65
 
66
+ #
67
+ # Publish multiple messages to a topic. Shorthand method to Cloudenvoy::PubSubClient#publish_all.
68
+ #
69
+ # @param [String] topic The name of the topic
70
+ # @param [Array<Array<[Hash, String]>>] msg_args A list of message [payload, metadata].
71
+ #
72
+ # @return [Array<Cloudenvoy::Message>] The published messages.
73
+ #
74
+ def self.publish_all(topic, msg_args)
75
+ PubSubClient.publish_all(topic, msg_args)
76
+ end
77
+
65
78
  #
66
79
  # Return the list of registered publishers.
67
80
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudenvoy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.6.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arnaud Lachaume
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-25 00:00:00.000000000 Z
11
+ date: 2022-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -114,14 +114,14 @@ dependencies:
114
114
  requirements:
115
115
  - - '='
116
116
  - !ruby/object:Gem::Version
117
- version: 0.76.0
117
+ version: 0.93.0
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - '='
123
123
  - !ruby/object:Gem::Version
124
- version: 0.76.0
124
+ version: 0.93.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rubocop-rspec
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -178,48 +178,6 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
- - !ruby/object:Gem::Dependency
182
- name: rails
183
- requirement: !ruby/object:Gem::Requirement
184
- requirements:
185
- - - ">="
186
- - !ruby/object:Gem::Version
187
- version: '0'
188
- type: :development
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - ">="
193
- - !ruby/object:Gem::Version
194
- version: '0'
195
- - !ruby/object:Gem::Dependency
196
- name: rspec-rails
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - ">="
200
- - !ruby/object:Gem::Version
201
- version: '0'
202
- type: :development
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - ">="
207
- - !ruby/object:Gem::Version
208
- version: '0'
209
- - !ruby/object:Gem::Dependency
210
- name: sqlite3
211
- requirement: !ruby/object:Gem::Requirement
212
- requirements:
213
- - - ">="
214
- - !ruby/object:Gem::Version
215
- version: '0'
216
- type: :development
217
- prerelease: false
218
- version_requirements: !ruby/object:Gem::Requirement
219
- requirements:
220
- - - ">="
221
- - !ruby/object:Gem::Version
222
- version: '0'
223
181
  description: Cross-application messaging using GCP Pub/Sub (alpha)
224
182
  email:
225
183
  - arnaud.lachaume@keypup.io
@@ -227,7 +185,10 @@ executables: []
227
185
  extensions: []
228
186
  extra_rdoc_files: []
229
187
  files:
230
- - ".github/workflows/test.yml"
188
+ - ".github/workflows/lint_rubocop.yml"
189
+ - ".github/workflows/test_ruby_2.5_2.6.yml"
190
+ - ".github/workflows/test_ruby_2.7.yml"
191
+ - ".github/workflows/test_ruby_3.x.yml"
231
192
  - ".gitignore"
232
193
  - ".rspec"
233
194
  - ".rubocop.yml"
@@ -318,18 +279,15 @@ files:
318
279
  - examples/sinatra/app/subscribers/hello_subscriber.rb
319
280
  - examples/sinatra/bin/console
320
281
  - examples/sinatra/config/initializers/cloudenvoy.rb
282
+ - gemfiles/.bundle/config
321
283
  - gemfiles/rails_5.2.gemfile
322
- - gemfiles/rails_5.2.gemfile.lock
323
284
  - gemfiles/rails_6.0.gemfile
324
- - gemfiles/rails_6.0.gemfile.lock
285
+ - gemfiles/rails_6.1.gemfile
286
+ - gemfiles/rails_7.0.gemfile
325
287
  - gemfiles/semantic_logger_3.4.gemfile
326
- - gemfiles/semantic_logger_3.4.gemfile.lock
327
288
  - gemfiles/semantic_logger_4.6.gemfile
328
- - gemfiles/semantic_logger_4.6.gemfile.lock
329
289
  - gemfiles/semantic_logger_4.7.0.gemfile
330
- - gemfiles/semantic_logger_4.7.0.gemfile.lock
331
290
  - gemfiles/semantic_logger_4.7.2.gemfile
332
- - gemfiles/semantic_logger_4.7.2.gemfile.lock
333
291
  - lib/cloudenvoy.rb
334
292
  - lib/cloudenvoy/authentication_error.rb
335
293
  - lib/cloudenvoy/authenticator.rb
@@ -372,14 +330,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
372
330
  requirements:
373
331
  - - ">="
374
332
  - !ruby/object:Gem::Version
375
- version: 2.3.0
333
+ version: 2.4.0
376
334
  required_rubygems_version: !ruby/object:Gem::Requirement
377
335
  requirements:
378
- - - ">="
336
+ - - ">"
379
337
  - !ruby/object:Gem::Version
380
- version: '0'
338
+ version: 1.3.1
381
339
  requirements: []
382
- rubygems_version: 3.0.0
340
+ rubygems_version: 3.2.3
383
341
  signing_key:
384
342
  specification_version: 4
385
343
  summary: Cross-application messaging using GCP Pub/Sub (alpha)
@@ -1,264 +0,0 @@
1
- PATH
2
- remote: ..
3
- specs:
4
- cloudenvoy (0.4.1)
5
- activesupport
6
- google-cloud-pubsub (~> 2.0)
7
- jwt
8
- retriable
9
-
10
- GEM
11
- remote: https://rubygems.org/
12
- specs:
13
- actioncable (5.2.0)
14
- actionpack (= 5.2.0)
15
- nio4r (~> 2.0)
16
- websocket-driver (>= 0.6.1)
17
- actionmailer (5.2.0)
18
- actionpack (= 5.2.0)
19
- actionview (= 5.2.0)
20
- activejob (= 5.2.0)
21
- mail (~> 2.5, >= 2.5.4)
22
- rails-dom-testing (~> 2.0)
23
- actionpack (5.2.0)
24
- actionview (= 5.2.0)
25
- activesupport (= 5.2.0)
26
- rack (~> 2.0)
27
- rack-test (>= 0.6.3)
28
- rails-dom-testing (~> 2.0)
29
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
30
- actionview (5.2.0)
31
- activesupport (= 5.2.0)
32
- builder (~> 3.1)
33
- erubi (~> 1.4)
34
- rails-dom-testing (~> 2.0)
35
- rails-html-sanitizer (~> 1.0, >= 1.0.3)
36
- activejob (5.2.0)
37
- activesupport (= 5.2.0)
38
- globalid (>= 0.3.6)
39
- activemodel (5.2.0)
40
- activesupport (= 5.2.0)
41
- activerecord (5.2.0)
42
- activemodel (= 5.2.0)
43
- activesupport (= 5.2.0)
44
- arel (>= 9.0)
45
- activestorage (5.2.0)
46
- actionpack (= 5.2.0)
47
- activerecord (= 5.2.0)
48
- marcel (~> 0.3.1)
49
- activesupport (5.2.0)
50
- concurrent-ruby (~> 1.0, >= 1.0.2)
51
- i18n (>= 0.7, < 2)
52
- minitest (~> 5.1)
53
- tzinfo (~> 1.1)
54
- addressable (2.7.0)
55
- public_suffix (>= 2.0.2, < 5.0)
56
- appraisal (2.4.0)
57
- bundler
58
- rake
59
- thor (>= 0.14.0)
60
- arel (9.0.0)
61
- ast (2.4.2)
62
- builder (3.2.4)
63
- concurrent-ruby (1.1.8)
64
- crack (0.4.5)
65
- rexml
66
- crass (1.0.6)
67
- diff-lcs (1.4.4)
68
- erubi (1.10.0)
69
- faraday (1.4.1)
70
- faraday-excon (~> 1.1)
71
- faraday-net_http (~> 1.0)
72
- faraday-net_http_persistent (~> 1.1)
73
- multipart-post (>= 1.2, < 3)
74
- ruby2_keywords (>= 0.0.4)
75
- faraday-excon (1.1.0)
76
- faraday-net_http (1.0.1)
77
- faraday-net_http_persistent (1.1.0)
78
- gapic-common (0.4.1)
79
- faraday (~> 1.3)
80
- google-protobuf (~> 3.15, >= 3.15.2)
81
- googleapis-common-protos (>= 1.3.11, < 2.0)
82
- googleapis-common-protos-types (>= 1.0.6, < 2.0)
83
- googleauth (~> 0.15, >= 0.15.1)
84
- grpc (~> 1.36)
85
- globalid (0.4.2)
86
- activesupport (>= 4.2.0)
87
- google-cloud-core (1.6.0)
88
- google-cloud-env (~> 1.0)
89
- google-cloud-errors (~> 1.0)
90
- google-cloud-env (1.5.0)
91
- faraday (>= 0.17.3, < 2.0)
92
- google-cloud-errors (1.1.0)
93
- google-cloud-pubsub (2.5.0)
94
- concurrent-ruby (~> 1.1)
95
- google-cloud-core (~> 1.5)
96
- google-cloud-pubsub-v1 (~> 0.0)
97
- google-cloud-pubsub-v1 (0.4.0)
98
- gapic-common (~> 0.3)
99
- google-cloud-errors (~> 1.0)
100
- grpc-google-iam-v1 (>= 0.6.10, < 2.0)
101
- google-protobuf (3.15.8)
102
- googleapis-common-protos (1.3.11)
103
- google-protobuf (~> 3.14)
104
- googleapis-common-protos-types (>= 1.0.6, < 2.0)
105
- grpc (~> 1.27)
106
- googleapis-common-protos-types (1.0.6)
107
- google-protobuf (~> 3.14)
108
- googleauth (0.16.1)
109
- faraday (>= 0.17.3, < 2.0)
110
- jwt (>= 1.4, < 3.0)
111
- memoist (~> 0.16)
112
- multi_json (~> 1.11)
113
- os (>= 0.9, < 2.0)
114
- signet (~> 0.14)
115
- grpc (1.37.0)
116
- google-protobuf (~> 3.15)
117
- googleapis-common-protos-types (~> 1.0)
118
- grpc-google-iam-v1 (0.6.11)
119
- google-protobuf (~> 3.14)
120
- googleapis-common-protos (>= 1.3.11, < 2.0)
121
- grpc (~> 1.27)
122
- hashdiff (1.0.1)
123
- i18n (1.8.10)
124
- concurrent-ruby (~> 1.0)
125
- jaro_winkler (1.5.4)
126
- jwt (2.2.2)
127
- loofah (2.9.1)
128
- crass (~> 1.0.2)
129
- nokogiri (>= 1.5.9)
130
- mail (2.7.1)
131
- mini_mime (>= 0.1.1)
132
- marcel (0.3.3)
133
- mimemagic (~> 0.3.2)
134
- memoist (0.16.2)
135
- method_source (1.0.0)
136
- mimemagic (0.3.10)
137
- nokogiri (~> 1)
138
- rake
139
- mini_mime (1.1.0)
140
- mini_portile2 (2.5.0)
141
- minitest (5.14.4)
142
- multi_json (1.15.0)
143
- multipart-post (2.1.1)
144
- nio4r (2.5.7)
145
- nokogiri (1.11.3)
146
- mini_portile2 (~> 2.5.0)
147
- racc (~> 1.4)
148
- os (1.1.1)
149
- parallel (1.20.1)
150
- parser (3.0.1.0)
151
- ast (~> 2.4.1)
152
- public_suffix (4.0.6)
153
- racc (1.5.2)
154
- rack (2.2.3)
155
- rack-test (1.1.0)
156
- rack (>= 1.0, < 3)
157
- rails (5.2.0)
158
- actioncable (= 5.2.0)
159
- actionmailer (= 5.2.0)
160
- actionpack (= 5.2.0)
161
- actionview (= 5.2.0)
162
- activejob (= 5.2.0)
163
- activemodel (= 5.2.0)
164
- activerecord (= 5.2.0)
165
- activestorage (= 5.2.0)
166
- activesupport (= 5.2.0)
167
- bundler (>= 1.3.0)
168
- railties (= 5.2.0)
169
- sprockets-rails (>= 2.0.0)
170
- rails-dom-testing (2.0.3)
171
- activesupport (>= 4.2.0)
172
- nokogiri (>= 1.6)
173
- rails-html-sanitizer (1.3.0)
174
- loofah (~> 2.3)
175
- railties (5.2.0)
176
- actionpack (= 5.2.0)
177
- activesupport (= 5.2.0)
178
- method_source
179
- rake (>= 0.8.7)
180
- thor (>= 0.18.1, < 2.0)
181
- rainbow (3.0.0)
182
- rake (13.0.3)
183
- retriable (3.1.2)
184
- rexml (3.2.5)
185
- rspec (3.10.0)
186
- rspec-core (~> 3.10.0)
187
- rspec-expectations (~> 3.10.0)
188
- rspec-mocks (~> 3.10.0)
189
- rspec-core (3.10.1)
190
- rspec-support (~> 3.10.0)
191
- rspec-expectations (3.10.1)
192
- diff-lcs (>= 1.2.0, < 2.0)
193
- rspec-support (~> 3.10.0)
194
- rspec-mocks (3.10.2)
195
- diff-lcs (>= 1.2.0, < 2.0)
196
- rspec-support (~> 3.10.0)
197
- rspec-rails (5.0.1)
198
- actionpack (>= 5.2)
199
- activesupport (>= 5.2)
200
- railties (>= 5.2)
201
- rspec-core (~> 3.10)
202
- rspec-expectations (~> 3.10)
203
- rspec-mocks (~> 3.10)
204
- rspec-support (~> 3.10)
205
- rspec-support (3.10.2)
206
- rubocop (0.76.0)
207
- jaro_winkler (~> 1.5.1)
208
- parallel (~> 1.10)
209
- parser (>= 2.6)
210
- rainbow (>= 2.2.2, < 4.0)
211
- ruby-progressbar (~> 1.7)
212
- unicode-display_width (>= 1.4.0, < 1.7)
213
- rubocop-rspec (1.37.0)
214
- rubocop (>= 0.68.1)
215
- ruby-progressbar (1.11.0)
216
- ruby2_keywords (0.0.4)
217
- semantic_logger (4.7.4)
218
- concurrent-ruby (~> 1.0)
219
- signet (0.15.0)
220
- addressable (~> 2.3)
221
- faraday (>= 0.17.3, < 2.0)
222
- jwt (>= 1.5, < 3.0)
223
- multi_json (~> 1.10)
224
- sprockets (4.0.2)
225
- concurrent-ruby (~> 1.0)
226
- rack (> 1, < 3)
227
- sprockets-rails (3.2.2)
228
- actionpack (>= 4.0)
229
- activesupport (>= 4.0)
230
- sprockets (>= 3.0.0)
231
- sqlite3 (1.4.2)
232
- thor (1.1.0)
233
- thread_safe (0.3.6)
234
- timecop (0.9.4)
235
- tzinfo (1.2.9)
236
- thread_safe (~> 0.1)
237
- unicode-display_width (1.6.1)
238
- webmock (3.12.2)
239
- addressable (>= 2.3.6)
240
- crack (>= 0.3.2)
241
- hashdiff (>= 0.4.0, < 2.0.0)
242
- websocket-driver (0.7.3)
243
- websocket-extensions (>= 0.1.0)
244
- websocket-extensions (0.1.5)
245
-
246
- PLATFORMS
247
- ruby
248
-
249
- DEPENDENCIES
250
- appraisal
251
- cloudenvoy!
252
- rails (= 5.2)
253
- rake (>= 12.3.3)
254
- rspec (~> 3.0)
255
- rspec-rails
256
- rubocop (= 0.76.0)
257
- rubocop-rspec (= 1.37.0)
258
- semantic_logger
259
- sqlite3
260
- timecop
261
- webmock
262
-
263
- BUNDLED WITH
264
- 2.2.9