busybee 0.1.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +23 -0
- data/LICENSE.txt +21 -0
- data/README.md +214 -0
- data/docs/grpc.md +106 -0
- data/docs/testing.md +680 -0
- data/lib/busybee/grpc/gateway_pb.rb +91 -0
- data/lib/busybee/grpc/gateway_services_pb.rb +278 -0
- data/lib/busybee/grpc.rb +4 -0
- data/lib/busybee/testing/activated_job.rb +140 -0
- data/lib/busybee/testing/helpers.rb +251 -0
- data/lib/busybee/testing/matchers/have_activated.rb +66 -0
- data/lib/busybee/testing/matchers/have_received_headers.rb +21 -0
- data/lib/busybee/testing/matchers/have_received_variables.rb +21 -0
- data/lib/busybee/testing.rb +54 -0
- data/lib/busybee/version.rb +5 -0
- data/lib/busybee.rb +7 -0
- metadata +94 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "securerandom"
|
|
4
|
+
require "base64"
|
|
5
|
+
require "json"
|
|
6
|
+
require "busybee/grpc"
|
|
7
|
+
require_relative "activated_job"
|
|
8
|
+
|
|
9
|
+
module Busybee
|
|
10
|
+
module Testing
|
|
11
|
+
# Raised when no job is available for activation
|
|
12
|
+
class NoJobAvailable < StandardError; end
|
|
13
|
+
|
|
14
|
+
# RSpec helper methods for testing BPMN workflows against Zeebe.
|
|
15
|
+
module Helpers
|
|
16
|
+
# Deploy a BPMN process file to Zeebe.
|
|
17
|
+
#
|
|
18
|
+
# By default, deploys the BPMN file as-is using its original process ID.
|
|
19
|
+
# Optionally, you can uniquify the process ID for test isolation.
|
|
20
|
+
#
|
|
21
|
+
# @param path [String] path to BPMN file
|
|
22
|
+
# @param uniquify [nil, true, String] uniquification behavior:
|
|
23
|
+
# - nil (default): deploy as-is with original process ID
|
|
24
|
+
# - true: auto-generate unique process ID like "test-process-abc123"
|
|
25
|
+
# - String: use provided string as custom process ID
|
|
26
|
+
# @return [Hash] deployment info with keys:
|
|
27
|
+
# - :process [ProcessMetadata] - GRPC process metadata object
|
|
28
|
+
# - :process_id [String] - the BPMN process ID (uniquified or original)
|
|
29
|
+
#
|
|
30
|
+
# @example Deploy as-is (most common)
|
|
31
|
+
# result = deploy_process("path/to/process.bpmn")
|
|
32
|
+
# result[:process_id] #=> "simple-process" (from BPMN file)
|
|
33
|
+
#
|
|
34
|
+
# @example Deploy with auto-generated unique ID (for test isolation)
|
|
35
|
+
# result = deploy_process("path/to/process.bpmn", uniquify: true)
|
|
36
|
+
# result[:process_id] #=> "test-process-a1b2c3d4e5f6"
|
|
37
|
+
#
|
|
38
|
+
# @example Deploy with custom ID
|
|
39
|
+
# result = deploy_process("path/to/process.bpmn", uniquify: "my-test-process")
|
|
40
|
+
# result[:process_id] #=> "my-test-process"
|
|
41
|
+
def deploy_process(path, uniquify: nil)
|
|
42
|
+
if uniquify
|
|
43
|
+
process_id = uniquify == true ? unique_process_id : uniquify
|
|
44
|
+
bpmn_content = bpmn_with_unique_id(path, process_id)
|
|
45
|
+
else
|
|
46
|
+
bpmn_content = File.read(path)
|
|
47
|
+
process_id = extract_process_id(bpmn_content)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
resource = Busybee::GRPC::Resource.new(
|
|
51
|
+
name: File.basename(path),
|
|
52
|
+
content: bpmn_content
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
request = Busybee::GRPC::DeployResourceRequest.new(
|
|
56
|
+
resources: [resource]
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
response = grpc_client.deploy_resource(request)
|
|
60
|
+
|
|
61
|
+
{
|
|
62
|
+
process: response.deployments.first.process,
|
|
63
|
+
process_id: process_id
|
|
64
|
+
}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Create a process instance, yield its key, and cancel on block exit.
|
|
68
|
+
#
|
|
69
|
+
# @param process_name [String] BPMN process ID
|
|
70
|
+
# @param variables [Hash] variables to start the process with
|
|
71
|
+
# @yield [Integer] the process instance key
|
|
72
|
+
def with_process_instance(process_name, variables = {})
|
|
73
|
+
request = Busybee::GRPC::CreateProcessInstanceRequest.new(
|
|
74
|
+
bpmnProcessId: process_name,
|
|
75
|
+
version: -1,
|
|
76
|
+
variables: JSON.generate(variables)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
response = grpc_client.create_process_instance(request)
|
|
80
|
+
@current_process_instance_key = response.processInstanceKey
|
|
81
|
+
|
|
82
|
+
yield @current_process_instance_key
|
|
83
|
+
ensure
|
|
84
|
+
if @current_process_instance_key
|
|
85
|
+
cancel_process_instance(@current_process_instance_key)
|
|
86
|
+
@last_process_instance_key = @current_process_instance_key
|
|
87
|
+
@current_process_instance_key = nil
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Returns the current process instance key (set by with_process_instance).
|
|
92
|
+
#
|
|
93
|
+
# @return [Integer, nil]
|
|
94
|
+
def process_instance_key
|
|
95
|
+
@current_process_instance_key
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Returns the last process instance key from the most recent with_process_instance call.
|
|
99
|
+
# Useful for debugging failed tests by tying failures to residual data in ElasticSearch.
|
|
100
|
+
#
|
|
101
|
+
# @return [Integer, nil]
|
|
102
|
+
def last_process_instance_key
|
|
103
|
+
@last_process_instance_key
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Checks if Zeebe is available and responsive.
|
|
107
|
+
#
|
|
108
|
+
# This method attempts to connect to Zeebe and call the topology endpoint
|
|
109
|
+
# to verify the service is running and healthy.
|
|
110
|
+
#
|
|
111
|
+
# @param timeout [Integer] timeout in seconds for the connection check
|
|
112
|
+
# @return [Boolean] true if Zeebe is available, false otherwise
|
|
113
|
+
def zeebe_available?(timeout: 5)
|
|
114
|
+
request = Busybee::GRPC::TopologyRequest.new
|
|
115
|
+
grpc_client.topology(request, deadline: Time.now + timeout)
|
|
116
|
+
true
|
|
117
|
+
rescue GRPC::Unavailable, GRPC::DeadlineExceeded, GRPC::Core::CallError, GRPC::Unauthenticated
|
|
118
|
+
false
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Activate a single job of the given type.
|
|
122
|
+
#
|
|
123
|
+
# @param type [String] job type
|
|
124
|
+
# @return [ActivatedJob]
|
|
125
|
+
# @raise [NoJobAvailable] if no job is available
|
|
126
|
+
def activate_job(type)
|
|
127
|
+
jobs = activate_jobs_raw(type, max_jobs: 1)
|
|
128
|
+
raise NoJobAvailable, "No job of type '#{type}' available" if jobs.empty?
|
|
129
|
+
|
|
130
|
+
ActivatedJob.new(jobs.first, client: grpc_client)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Activate multiple jobs of the given type.
|
|
134
|
+
#
|
|
135
|
+
# @param type [String] job type
|
|
136
|
+
# @param max_jobs [Integer] maximum number of jobs to activate
|
|
137
|
+
# @return [Enumerator<ActivatedJob>]
|
|
138
|
+
def activate_jobs(type, max_jobs:)
|
|
139
|
+
Enumerator.new do |yielder|
|
|
140
|
+
activate_jobs_raw(type, max_jobs: max_jobs).each do |raw_job|
|
|
141
|
+
yielder << ActivatedJob.new(raw_job, client: grpc_client)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Publish a message to Zeebe.
|
|
147
|
+
#
|
|
148
|
+
# @param name [String] message name
|
|
149
|
+
# @param correlation_key [String] correlation key
|
|
150
|
+
# @param variables [Hash] message variables
|
|
151
|
+
# @param ttl_ms [Integer] time-to-live in milliseconds
|
|
152
|
+
def publish_message(name, correlation_key:, variables: {}, ttl_ms: 5000)
|
|
153
|
+
request = Busybee::GRPC::PublishMessageRequest.new(
|
|
154
|
+
name: name,
|
|
155
|
+
correlationKey: correlation_key,
|
|
156
|
+
variables: JSON.generate(variables),
|
|
157
|
+
timeToLive: ttl_ms
|
|
158
|
+
)
|
|
159
|
+
grpc_client.publish_message(request)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Set variables on a process scope.
|
|
163
|
+
#
|
|
164
|
+
# @param scope_key [Integer] element instance key
|
|
165
|
+
# @param variables [Hash] variables to set
|
|
166
|
+
# @param local [Boolean] whether variables are local to scope
|
|
167
|
+
def set_variables(scope_key, variables, local: true)
|
|
168
|
+
request = Busybee::GRPC::SetVariablesRequest.new(
|
|
169
|
+
elementInstanceKey: scope_key,
|
|
170
|
+
variables: JSON.generate(variables),
|
|
171
|
+
local: local
|
|
172
|
+
)
|
|
173
|
+
grpc_client.set_variables(request)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Assert that the current process instance has completed.
|
|
177
|
+
#
|
|
178
|
+
# @param wait [Float] seconds to wait before checking
|
|
179
|
+
# @raise [RuntimeError] if process is still running
|
|
180
|
+
def assert_process_completed!(wait: 0.25)
|
|
181
|
+
sleep(wait) if wait.positive?
|
|
182
|
+
|
|
183
|
+
request = Busybee::GRPC::CancelProcessInstanceRequest.new(
|
|
184
|
+
processInstanceKey: process_instance_key
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
begin
|
|
188
|
+
grpc_client.cancel_process_instance(request)
|
|
189
|
+
rescue ::GRPC::NotFound
|
|
190
|
+
true # Expected - process has completed
|
|
191
|
+
else
|
|
192
|
+
raise "Process instance #{process_instance_key} is still running (expected it to be completed)"
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
private
|
|
197
|
+
|
|
198
|
+
def unique_process_id
|
|
199
|
+
"test-process-#{SecureRandom.hex(6)}"
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def extract_process_id(bpmn_content)
|
|
203
|
+
match = bpmn_content.match(/<bpmn:process id="([^"]+)"/)
|
|
204
|
+
match ? match[1] : nil
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def bpmn_with_unique_id(bpmn_path, process_id)
|
|
208
|
+
bpmn_content = File.read(bpmn_path)
|
|
209
|
+
bpmn_content
|
|
210
|
+
.gsub(/(<bpmn:process id=")[^"]+/, "\\1#{process_id}")
|
|
211
|
+
# Possessive quantifiers (++, *+) prevent polynomial backtracking
|
|
212
|
+
.gsub(/(<bpmndi:BPMNPlane\s++[^>]*+bpmnElement=")[^"]++/, "\\1#{process_id}")
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def cancel_process_instance(key)
|
|
216
|
+
request = Busybee::GRPC::CancelProcessInstanceRequest.new(
|
|
217
|
+
processInstanceKey: key
|
|
218
|
+
)
|
|
219
|
+
grpc_client.cancel_process_instance(request)
|
|
220
|
+
true
|
|
221
|
+
rescue ::GRPC::NotFound
|
|
222
|
+
# Process already completed, ignore
|
|
223
|
+
false
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def activate_jobs_raw(type, max_jobs:)
|
|
227
|
+
worker = "#{type}-#{SecureRandom.hex(4)}"
|
|
228
|
+
request = Busybee::GRPC::ActivateJobsRequest.new(
|
|
229
|
+
type: type,
|
|
230
|
+
worker: worker,
|
|
231
|
+
timeout: 30_000,
|
|
232
|
+
maxJobsToActivate: max_jobs,
|
|
233
|
+
requestTimeout: Busybee::Testing.activate_request_timeout
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
jobs = []
|
|
237
|
+
grpc_client.activate_jobs(request).each do |response|
|
|
238
|
+
jobs.concat(response.jobs.to_a)
|
|
239
|
+
end
|
|
240
|
+
jobs
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def grpc_client
|
|
244
|
+
@grpc_client ||= Busybee::GRPC::Gateway::Stub.new(
|
|
245
|
+
Busybee::Testing.address,
|
|
246
|
+
:this_channel_is_insecure
|
|
247
|
+
)
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rspec/expectations"
|
|
4
|
+
require_relative "../activated_job"
|
|
5
|
+
|
|
6
|
+
RSpec::Matchers.define :have_activated do |job_type|
|
|
7
|
+
match do |helper|
|
|
8
|
+
@job_type = job_type
|
|
9
|
+
@helper = helper
|
|
10
|
+
|
|
11
|
+
begin
|
|
12
|
+
@activated_job = helper.activate_job(job_type)
|
|
13
|
+
@job_activated = true
|
|
14
|
+
rescue Busybee::Testing::NoJobAvailable
|
|
15
|
+
@job_activated = false
|
|
16
|
+
return false
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# If we have chained expectations, validate them
|
|
20
|
+
if @expected_variables
|
|
21
|
+
expected_stringified = @expected_variables.transform_keys(&:to_s)
|
|
22
|
+
actual = @activated_job.variables
|
|
23
|
+
unless actual.slice(*expected_stringified.keys) == expected_stringified
|
|
24
|
+
@variables_mismatch = true
|
|
25
|
+
@actual_variables = actual
|
|
26
|
+
return false
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
if @expected_headers
|
|
31
|
+
expected_stringified = @expected_headers.transform_keys(&:to_s)
|
|
32
|
+
actual = @activated_job.headers
|
|
33
|
+
unless actual.slice(*expected_stringified.keys) == expected_stringified
|
|
34
|
+
@headers_mismatch = true
|
|
35
|
+
@actual_headers = actual
|
|
36
|
+
return false
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
true
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
chain :with_variables do |expected|
|
|
44
|
+
@expected_variables = expected
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
chain :with_headers do |expected|
|
|
48
|
+
@expected_headers = expected
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
failure_message do
|
|
52
|
+
if !@job_activated
|
|
53
|
+
"No job of type '#{@job_type}' was activated"
|
|
54
|
+
elsif @variables_mismatch
|
|
55
|
+
"expected job variables to include #{@expected_variables.inspect}\n" \
|
|
56
|
+
"actual variables: #{@actual_variables.inspect}"
|
|
57
|
+
elsif @headers_mismatch
|
|
58
|
+
"expected job headers to include #{@expected_headers.inspect}\n" \
|
|
59
|
+
"actual headers: #{@actual_headers.inspect}"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
failure_message_when_negated do
|
|
64
|
+
"expected no job of type '#{@job_type}' to be activated, but one was"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rspec/expectations"
|
|
4
|
+
|
|
5
|
+
RSpec::Matchers.define :have_received_headers do |expected|
|
|
6
|
+
match do |job|
|
|
7
|
+
expected_stringified = expected.transform_keys(&:to_s)
|
|
8
|
+
@actual = job.headers
|
|
9
|
+
@actual.slice(*expected_stringified.keys) == expected_stringified
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
failure_message do
|
|
13
|
+
"expected job headers to include #{expected.inspect}\n" \
|
|
14
|
+
"actual headers: #{@actual.inspect}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
failure_message_when_negated do
|
|
18
|
+
"expected job headers not to include #{expected.inspect}\n" \
|
|
19
|
+
"actual headers: #{@actual.inspect}"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rspec/expectations"
|
|
4
|
+
|
|
5
|
+
RSpec::Matchers.define :have_received_variables do |expected|
|
|
6
|
+
match do |job|
|
|
7
|
+
expected_stringified = expected.transform_keys(&:to_s)
|
|
8
|
+
@actual = job.variables
|
|
9
|
+
@actual.slice(*expected_stringified.keys) == expected_stringified
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
failure_message do
|
|
13
|
+
"expected job variables to include #{expected.inspect}\n" \
|
|
14
|
+
"actual variables: #{@actual.inspect}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
failure_message_when_negated do
|
|
18
|
+
"expected job variables not to include #{expected.inspect}\n" \
|
|
19
|
+
"actual variables: #{@actual.inspect}"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "busybee/grpc"
|
|
4
|
+
|
|
5
|
+
module Busybee
|
|
6
|
+
# Testing support for BPMN workflows with RSpec.
|
|
7
|
+
#
|
|
8
|
+
# @example Configuration
|
|
9
|
+
# Busybee::Testing.configure do |config|
|
|
10
|
+
# config.address = "localhost:26500"
|
|
11
|
+
# config.username = "demo"
|
|
12
|
+
# config.password = "demo"
|
|
13
|
+
# config.activate_request_timeout = 2000
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
module Testing
|
|
17
|
+
class << self
|
|
18
|
+
attr_writer :address, :username, :password, :activate_request_timeout
|
|
19
|
+
|
|
20
|
+
def configure
|
|
21
|
+
yield self
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def address
|
|
25
|
+
@address || ENV["ZEEBE_ADDRESS"] || "localhost:26500"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def username
|
|
29
|
+
@username || ENV["ZEEBE_USERNAME"] || "demo"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def password
|
|
33
|
+
@password || ENV["ZEEBE_PASSWORD"] || "demo"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def activate_request_timeout
|
|
37
|
+
@activate_request_timeout || 1000
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Auto-load RSpec integration if RSpec is available
|
|
44
|
+
if defined?(RSpec)
|
|
45
|
+
require "busybee/testing/helpers"
|
|
46
|
+
require "busybee/testing/activated_job"
|
|
47
|
+
require "busybee/testing/matchers/have_received_variables"
|
|
48
|
+
require "busybee/testing/matchers/have_received_headers"
|
|
49
|
+
require "busybee/testing/matchers/have_activated"
|
|
50
|
+
|
|
51
|
+
RSpec.configure do |config|
|
|
52
|
+
config.include Busybee::Testing::Helpers
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/busybee.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: busybee
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Andy Rusterholz
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2025-12-30 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: base64
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: grpc
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.76'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.76'
|
|
41
|
+
description: The missing Ruby gem for Camunda 8. Production-ready worker framework
|
|
42
|
+
that runs out of the box - define your job handlers and go. Idiomatic Zeebe client
|
|
43
|
+
with sensible defaults and configuration where you want it. RSpec testing helpers
|
|
44
|
+
and CI/CD deployment tooling for BPMNs.
|
|
45
|
+
email:
|
|
46
|
+
- andyrusterholz@gmail.com
|
|
47
|
+
executables: []
|
|
48
|
+
extensions: []
|
|
49
|
+
extra_rdoc_files: []
|
|
50
|
+
files:
|
|
51
|
+
- CHANGELOG.md
|
|
52
|
+
- LICENSE.txt
|
|
53
|
+
- README.md
|
|
54
|
+
- docs/grpc.md
|
|
55
|
+
- docs/testing.md
|
|
56
|
+
- lib/busybee.rb
|
|
57
|
+
- lib/busybee/grpc.rb
|
|
58
|
+
- lib/busybee/grpc/gateway_pb.rb
|
|
59
|
+
- lib/busybee/grpc/gateway_services_pb.rb
|
|
60
|
+
- lib/busybee/testing.rb
|
|
61
|
+
- lib/busybee/testing/activated_job.rb
|
|
62
|
+
- lib/busybee/testing/helpers.rb
|
|
63
|
+
- lib/busybee/testing/matchers/have_activated.rb
|
|
64
|
+
- lib/busybee/testing/matchers/have_received_headers.rb
|
|
65
|
+
- lib/busybee/testing/matchers/have_received_variables.rb
|
|
66
|
+
- lib/busybee/version.rb
|
|
67
|
+
homepage: https://github.com/rusterholz/busybee
|
|
68
|
+
licenses:
|
|
69
|
+
- MIT
|
|
70
|
+
metadata:
|
|
71
|
+
homepage_uri: https://github.com/rusterholz/busybee
|
|
72
|
+
source_code_uri: https://github.com/rusterholz/busybee
|
|
73
|
+
changelog_uri: https://github.com/rusterholz/busybee/blob/main/CHANGELOG.md
|
|
74
|
+
rubygems_mfa_required: 'true'
|
|
75
|
+
post_install_message:
|
|
76
|
+
rdoc_options: []
|
|
77
|
+
require_paths:
|
|
78
|
+
- lib
|
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
80
|
+
requirements:
|
|
81
|
+
- - ">="
|
|
82
|
+
- !ruby/object:Gem::Version
|
|
83
|
+
version: 3.2.0
|
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0'
|
|
89
|
+
requirements: []
|
|
90
|
+
rubygems_version: 3.5.22
|
|
91
|
+
signing_key:
|
|
92
|
+
specification_version: 4
|
|
93
|
+
summary: A complete Ruby toolkit for BPMN workflow orchestration.
|
|
94
|
+
test_files: []
|