rspec-buildkite-analytics 0.4.0 → 0.6.3
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 +4 -4
- data/Gemfile.lock +7 -9
- data/lib/rspec/buildkite/analytics/ci.rb +6 -2
- data/lib/rspec/buildkite/analytics/reporter.rb +55 -2
- data/lib/rspec/buildkite/analytics/session.rb +113 -45
- data/lib/rspec/buildkite/analytics/socket_connection.rb +1 -0
- data/lib/rspec/buildkite/analytics/tracer.rb +6 -4
- data/lib/rspec/buildkite/analytics/uploader.rb +15 -16
- data/lib/rspec/buildkite/analytics/version.rb +2 -1
- data/lib/rspec/buildkite/analytics.rb +2 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 499229f993ea2f8556a6d908f011325bf989de60c9a69a266338356b9f89426f
|
4
|
+
data.tar.gz: 901fec67b35b6ca85f61900a4cd9fa00293959892eb45e95339b6d4a6c27f527
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b7942d5c6b1abd45ff662cd52878d348bb1f9b3e2fa9fd1a6285eb7f521ac1d1f9dcc52007650dde979da9ddcbdd0506afe869708c785d033f9cf2e969eb009
|
7
|
+
data.tar.gz: c5484d6a416ac0faf663390c64d86e6c24184ddadbaa286b66407afd169444b7af9a6b9e665ead3438e87e719b5563ea0bc184c963643e17b13cdb8d3517ad1c
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rspec-buildkite-analytics (0.
|
4
|
+
rspec-buildkite-analytics (0.6.3)
|
5
5
|
activesupport (>= 5.2, <= 7.0)
|
6
6
|
rspec-core (~> 3.10)
|
7
7
|
rspec-expectations (~> 3.10)
|
@@ -10,18 +10,17 @@ PATH
|
|
10
10
|
GEM
|
11
11
|
remote: https://rubygems.org/
|
12
12
|
specs:
|
13
|
-
activesupport (
|
13
|
+
activesupport (7.0.0)
|
14
14
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
15
15
|
i18n (>= 1.6, < 2)
|
16
16
|
minitest (>= 5.1)
|
17
17
|
tzinfo (~> 2.0)
|
18
|
-
zeitwerk (~> 2.3)
|
19
18
|
concurrent-ruby (1.1.9)
|
20
19
|
diff-lcs (1.4.4)
|
21
|
-
i18n (1.8.
|
20
|
+
i18n (1.8.11)
|
22
21
|
concurrent-ruby (~> 1.0)
|
23
|
-
minitest (5.
|
24
|
-
rake (13.0.
|
22
|
+
minitest (5.15.0)
|
23
|
+
rake (13.0.6)
|
25
24
|
rspec (3.10.0)
|
26
25
|
rspec-core (~> 3.10.0)
|
27
26
|
rspec-expectations (~> 3.10.0)
|
@@ -31,14 +30,13 @@ GEM
|
|
31
30
|
rspec-expectations (3.10.1)
|
32
31
|
diff-lcs (>= 1.2.0, < 2.0)
|
33
32
|
rspec-support (~> 3.10.0)
|
34
|
-
rspec-mocks (3.10.
|
33
|
+
rspec-mocks (3.10.2)
|
35
34
|
diff-lcs (>= 1.2.0, < 2.0)
|
36
35
|
rspec-support (~> 3.10.0)
|
37
|
-
rspec-support (3.10.
|
36
|
+
rspec-support (3.10.3)
|
38
37
|
tzinfo (2.0.4)
|
39
38
|
concurrent-ruby (~> 1.0)
|
40
39
|
websocket (1.2.9)
|
41
|
-
zeitwerk (2.5.1)
|
42
40
|
|
43
41
|
PLATFORMS
|
44
42
|
ruby
|
@@ -14,13 +14,17 @@ module RSpec::Buildkite::Analytics::CI
|
|
14
14
|
"number" => ENV["BUILDKITE_BUILD_NUMBER"],
|
15
15
|
"job_id" => ENV["BUILDKITE_JOB_ID"],
|
16
16
|
"message" => ENV["BUILDKITE_MESSAGE"],
|
17
|
-
"debug" => ENV["BUILDKITE_ANALYTICS_DEBUG_ENABLED"]
|
17
|
+
"debug" => ENV["BUILDKITE_ANALYTICS_DEBUG_ENABLED"],
|
18
|
+
"version" => RSpec::Buildkite::Analytics::VERSION,
|
19
|
+
"collector" => RSpec::Buildkite::Analytics::NAME
|
18
20
|
}
|
19
21
|
else
|
20
22
|
{
|
21
23
|
"CI" => nil,
|
22
24
|
"key" => SecureRandom.uuid,
|
23
|
-
"debug" => ENV["BUILDKITE_ANALYTICS_DEBUG_ENABLED"]
|
25
|
+
"debug" => ENV["BUILDKITE_ANALYTICS_DEBUG_ENABLED"],
|
26
|
+
"version" => RSpec::Buildkite::Analytics::VERSION,
|
27
|
+
"collector" => RSpec::Buildkite::Analytics::NAME
|
24
28
|
}
|
25
29
|
end
|
26
30
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "time"
|
2
|
+
|
1
3
|
module RSpec::Buildkite::Analytics
|
2
4
|
class Reporter
|
3
5
|
RSpec::Core::Formatters.register self, :example_passed, :example_failed, :example_pending, :dump_summary
|
@@ -16,6 +18,7 @@ module RSpec::Buildkite::Analytics
|
|
16
18
|
|
17
19
|
if trace
|
18
20
|
trace.example = example
|
21
|
+
trace.failure_reason, trace.failure_expanded = failure_info(notification) if example.execution_result.status == :failed
|
19
22
|
RSpec::Buildkite::Analytics.session&.write_result(trace)
|
20
23
|
end
|
21
24
|
end
|
@@ -33,7 +36,7 @@ module RSpec::Buildkite::Analytics
|
|
33
36
|
|
34
37
|
# Write the debug file, if debug mode is enabled
|
35
38
|
if RSpec::Buildkite::Analytics.debug_enabled
|
36
|
-
filename = "#{RSpec::Buildkite::Analytics.debug_filepath}/bk-analytics-#{
|
39
|
+
filename = "#{RSpec::Buildkite::Analytics.debug_filepath}/bk-analytics-#{Time.now.strftime("%F-%R:%S")}-#{ENV["BUILDKITE_JOB_ID"]}.log.gz"
|
37
40
|
|
38
41
|
File.open(filename, "wb") do |f|
|
39
42
|
gz = Zlib::GzipWriter.new(f)
|
@@ -43,9 +46,59 @@ module RSpec::Buildkite::Analytics
|
|
43
46
|
end
|
44
47
|
end
|
45
48
|
end
|
46
|
-
|
49
|
+
|
47
50
|
alias_method :example_passed, :handle_example
|
48
51
|
alias_method :example_failed, :handle_example
|
49
52
|
alias_method :example_pending, :handle_example
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
MULTIPLE_ERRORS = [
|
57
|
+
RSpec::Expectations::MultipleExpectationsNotMetError,
|
58
|
+
RSpec::Core::MultipleExceptionError
|
59
|
+
]
|
60
|
+
|
61
|
+
def failure_info(notification)
|
62
|
+
failure_expanded = []
|
63
|
+
|
64
|
+
if RSpec::Buildkite::Analytics::Reporter::MULTIPLE_ERRORS.include?(notification.exception.class)
|
65
|
+
failure_reason = notification.exception.summary
|
66
|
+
notification.exception.all_exceptions.each do |exception|
|
67
|
+
# an example with multiple failures doesn't give us a
|
68
|
+
# separate message lines and backtrace object to send, so
|
69
|
+
# I've reached into RSpec internals and duplicated the
|
70
|
+
# construction of these
|
71
|
+
message_lines = RSpec::Core::Formatters::ExceptionPresenter.new(exception, notification.example).colorized_message_lines
|
72
|
+
|
73
|
+
failure_expanded << {
|
74
|
+
expanded: format_message_lines(message_lines),
|
75
|
+
backtrace: RSpec.configuration.backtrace_formatter.format_backtrace(exception.backtrace)
|
76
|
+
}
|
77
|
+
end
|
78
|
+
else
|
79
|
+
message_lines = notification.colorized_message_lines
|
80
|
+
failure_reason = strip_diff_colors(message_lines.shift)
|
81
|
+
|
82
|
+
failure_expanded << {
|
83
|
+
expanded: format_message_lines(message_lines),
|
84
|
+
backtrace: notification.formatted_backtrace
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
return failure_reason, failure_expanded
|
89
|
+
end
|
90
|
+
|
91
|
+
def format_message_lines(message_lines)
|
92
|
+
message_lines.map! { |l| strip_diff_colors(l) }
|
93
|
+
# the first line is sometimes blank, depending on the error reported
|
94
|
+
message_lines.shift if message_lines.first.blank?
|
95
|
+
# the last line is sometimes blank, depending on the error reported
|
96
|
+
message_lines.pop if message_lines.last.blank?
|
97
|
+
message_lines
|
98
|
+
end
|
99
|
+
|
100
|
+
def strip_diff_colors(string)
|
101
|
+
string.gsub(/\e\[([;\d]+)?m/, '')
|
102
|
+
end
|
50
103
|
end
|
51
104
|
end
|
@@ -35,13 +35,16 @@ module RSpec::Buildkite::Analytics
|
|
35
35
|
attr_reader :logger
|
36
36
|
|
37
37
|
def initialize(url, authorization_header, channel)
|
38
|
-
@
|
38
|
+
@establish_subscription_queue = Queue.new
|
39
39
|
@channel = channel
|
40
40
|
|
41
41
|
@unconfirmed_idents = {}
|
42
42
|
@idents_mutex = Mutex.new
|
43
|
+
@send_queue = Queue.new
|
43
44
|
@empty = ConditionVariable.new
|
44
45
|
@closing = false
|
46
|
+
@eot_queued = false
|
47
|
+
@eot_queued_mutex = Mutex.new
|
45
48
|
@reconnection_mutex = Mutex.new
|
46
49
|
|
47
50
|
@url = url
|
@@ -49,13 +52,25 @@ module RSpec::Buildkite::Analytics
|
|
49
52
|
|
50
53
|
@logger = Logger.new
|
51
54
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
+
reconnection_count = 0
|
56
|
+
|
57
|
+
begin
|
58
|
+
reconnection_count += 1
|
59
|
+
connect
|
60
|
+
rescue TimeoutError, InitialConnectionFailure => e
|
61
|
+
@logger.write("rspec-buildkite-analytics could not establish an initial connection with Buildkite due to #{e}. Attempting retry #{reconnection_count} of #{MAX_RECONNECTION_ATTEMPTS}...")
|
62
|
+
if reconnection_count > MAX_RECONNECTION_ATTEMPTS
|
63
|
+
$stderr.puts "rspec-buildkite-analytics could not establish an initial connection with Buildkite due to #{e.message} after #{MAX_RECONNECTION_ATTEMPTS} attempts. You may be missing some data for this test suite, please contact support if this issue persists."
|
64
|
+
else
|
65
|
+
sleep(WAIT_BETWEEN_RECONNECTIONS)
|
66
|
+
@logger.write("retrying reconnection")
|
67
|
+
retry
|
68
|
+
end
|
69
|
+
end
|
70
|
+
init_write_thread
|
55
71
|
end
|
56
72
|
|
57
73
|
def disconnected(connection)
|
58
|
-
reconnection_count = 0
|
59
74
|
@reconnection_mutex.synchronize do
|
60
75
|
# When the first thread detects a disconnection, it calls the disconnect method
|
61
76
|
# with the current connection. This thread grabs the reconnection mutex and does the
|
@@ -69,10 +84,13 @@ module RSpec::Buildkite::Analytics
|
|
69
84
|
return unless connection == @connection
|
70
85
|
@logger.write("starting reconnection")
|
71
86
|
|
87
|
+
reconnection_count = 0
|
88
|
+
|
72
89
|
begin
|
73
90
|
reconnection_count += 1
|
74
91
|
connect
|
75
|
-
|
92
|
+
init_write_thread
|
93
|
+
rescue SocketConnection::HandshakeError, RejectedSubscription, TimeoutError, InitialConnectionFailure, SocketConnection::SocketError => e
|
76
94
|
@logger.write("failed reconnection attempt #{reconnection_count} due to #{e}")
|
77
95
|
if reconnection_count > MAX_RECONNECTION_ATTEMPTS
|
78
96
|
$stderr.puts "rspec-buildkite-analytics experienced a disconnection and could not reconnect to Buildkite due to #{e.message}. Please contact support."
|
@@ -100,7 +118,9 @@ module RSpec::Buildkite::Analytics
|
|
100
118
|
|
101
119
|
@idents_mutex.synchronize do
|
102
120
|
@logger.write("waiting for last confirm")
|
103
|
-
# Here, we sleep for 75 seconds while waiting for the
|
121
|
+
# Here, we sleep for 75 seconds while waiting for the send
|
122
|
+
# queue to be drained and for the server to confirm the last
|
123
|
+
# idents.
|
104
124
|
# We are woken up when the unconfirmed_idents is empty, and given back the mutex to
|
105
125
|
# continue operation.
|
106
126
|
@empty.wait(@idents_mutex, CONFIRMATION_TIMEOUT) unless @unconfirmed_idents.empty?
|
@@ -108,6 +128,8 @@ module RSpec::Buildkite::Analytics
|
|
108
128
|
|
109
129
|
# Then we always disconnect cos we can't wait forever? 🤷♀️
|
110
130
|
@connection.close
|
131
|
+
# We kill the write thread cos it's got a while loop in it, so it won't finish otherwise
|
132
|
+
@write_thread&.kill
|
111
133
|
@logger.write("socket connection closed")
|
112
134
|
end
|
113
135
|
|
@@ -121,7 +143,7 @@ module RSpec::Buildkite::Analytics
|
|
121
143
|
when "welcome", "confirm_subscription"
|
122
144
|
# Push these two messages onto the queue, so that we block on waiting for the
|
123
145
|
# initializing phase to complete
|
124
|
-
@
|
146
|
+
@establish_subscription_queue.push(data)
|
125
147
|
@logger.write("received #{data['type']}")
|
126
148
|
when "reject_subscription"
|
127
149
|
@logger.write("received rejected_subscription")
|
@@ -132,13 +154,9 @@ module RSpec::Buildkite::Analytics
|
|
132
154
|
end
|
133
155
|
|
134
156
|
def write_result(result)
|
135
|
-
|
136
|
-
|
137
|
-
add_unconfirmed_idents(result.id, result_as_json)
|
138
|
-
|
139
|
-
transmit_results([result_as_json])
|
157
|
+
queue_and_track_result(result.id, result.as_hash)
|
140
158
|
|
141
|
-
@logger.write("
|
159
|
+
@logger.write("added #{result.id} to send queue")
|
142
160
|
end
|
143
161
|
|
144
162
|
def unconfirmed_idents_count
|
@@ -149,17 +167,6 @@ module RSpec::Buildkite::Analytics
|
|
149
167
|
|
150
168
|
private
|
151
169
|
|
152
|
-
def transmit_results(results_as_json)
|
153
|
-
@connection.transmit({
|
154
|
-
"identifier" => @channel,
|
155
|
-
"command" => "message",
|
156
|
-
"data" => {
|
157
|
-
"action" => "record_results",
|
158
|
-
"results" => results_as_json
|
159
|
-
}.to_json
|
160
|
-
})
|
161
|
-
end
|
162
|
-
|
163
170
|
def connect
|
164
171
|
@logger.write("starting socket connection process")
|
165
172
|
|
@@ -179,9 +186,52 @@ module RSpec::Buildkite::Analytics
|
|
179
186
|
@logger.write("connected")
|
180
187
|
end
|
181
188
|
|
189
|
+
def init_write_thread
|
190
|
+
# As this method can be called multiple times in the
|
191
|
+
# reconnection process, kill prev write threads (if any) before
|
192
|
+
# setting up the new one
|
193
|
+
@write_thread&.kill
|
194
|
+
|
195
|
+
@write_thread = Thread.new do
|
196
|
+
@logger.write("hello from write thread")
|
197
|
+
# Pretty sure this eternal loop is fine cos the call to queue.pop is blocking
|
198
|
+
loop do
|
199
|
+
data = @send_queue.pop
|
200
|
+
message_type = data["action"]
|
201
|
+
|
202
|
+
if message_type == "end_of_transmission"
|
203
|
+
# Because of the unpredictable sequencing between the test suite finishing
|
204
|
+
# (EOT gets queued) and disconnections happening (retransmit results gets
|
205
|
+
# queued), we don't want to send an EOT before any retransmits are sent.
|
206
|
+
if @send_queue.length > 0
|
207
|
+
@send_queue << data
|
208
|
+
@logger.write("putting eot at back of queue")
|
209
|
+
next
|
210
|
+
end
|
211
|
+
@eot_queued_mutex.synchronize do
|
212
|
+
@eot_queued = false
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
@connection.transmit({
|
217
|
+
"identifier" => @channel,
|
218
|
+
"command" => "message",
|
219
|
+
"data" => data.to_json
|
220
|
+
})
|
221
|
+
|
222
|
+
if RSpec::Buildkite::Analytics.debug_enabled
|
223
|
+
ids = if message_type == "record_results"
|
224
|
+
data["results"].map { |result| result["id"] }
|
225
|
+
end
|
226
|
+
@logger.write("transmitted #{message_type} #{ids}")
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
182
232
|
def pop_with_timeout(message_type)
|
183
233
|
Timeout.timeout(30, RSpec::Buildkite::Analytics::TimeoutError, "Timeout: Waited 30 seconds for #{message_type}") do
|
184
|
-
@
|
234
|
+
@establish_subscription_queue.pop
|
185
235
|
end
|
186
236
|
end
|
187
237
|
|
@@ -201,9 +251,16 @@ module RSpec::Buildkite::Analytics
|
|
201
251
|
end
|
202
252
|
end
|
203
253
|
|
204
|
-
def
|
254
|
+
def queue_and_track_result(ident, result_as_hash)
|
205
255
|
@idents_mutex.synchronize do
|
206
|
-
@unconfirmed_idents[ident] =
|
256
|
+
@unconfirmed_idents[ident] = result_as_hash
|
257
|
+
|
258
|
+
data = {
|
259
|
+
"action" => "record_results",
|
260
|
+
"results" => [result_as_hash]
|
261
|
+
}
|
262
|
+
|
263
|
+
@send_queue << data
|
207
264
|
end
|
208
265
|
end
|
209
266
|
|
@@ -222,23 +279,29 @@ module RSpec::Buildkite::Analytics
|
|
222
279
|
#
|
223
280
|
# However, there aren't any threads waiting on this signal until after we
|
224
281
|
# send the EOT message, so the prior broadcasts shouldn't do anything.
|
225
|
-
|
282
|
+
if @unconfirmed_idents.empty?
|
283
|
+
@empty.broadcast
|
284
|
+
@logger.write("broadcast empty")
|
285
|
+
else
|
286
|
+
@logger.write("still waiting on confirm for #{@unconfirmed_idents.keys}")
|
287
|
+
end
|
226
288
|
end
|
227
289
|
end
|
228
290
|
|
229
291
|
def send_eot
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
"command" => "message",
|
235
|
-
"data" => {
|
292
|
+
@eot_queued_mutex.synchronize do
|
293
|
+
return if @eot_queued
|
294
|
+
# Expect server to respond with data of indentifiers last upload part
|
295
|
+
data = {
|
236
296
|
"action" => "end_of_transmission",
|
237
297
|
"examples_count" => @examples_count.to_json
|
238
|
-
}
|
239
|
-
})
|
298
|
+
}
|
240
299
|
|
241
|
-
|
300
|
+
@send_queue << data
|
301
|
+
@eot_queued = true
|
302
|
+
|
303
|
+
@logger.write("added EOT to send queue")
|
304
|
+
end
|
242
305
|
end
|
243
306
|
|
244
307
|
def process_message(data)
|
@@ -255,14 +318,19 @@ module RSpec::Buildkite::Analytics
|
|
255
318
|
end
|
256
319
|
|
257
320
|
def retransmit
|
258
|
-
|
259
|
-
@unconfirmed_idents.values
|
260
|
-
end
|
321
|
+
@idents_mutex.synchronize do
|
322
|
+
results = @unconfirmed_idents.values
|
261
323
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
324
|
+
# queue the contents of the buffer, unless it's empty
|
325
|
+
unless results.empty?
|
326
|
+
data = {
|
327
|
+
"action" => "record_results",
|
328
|
+
"results" => results
|
329
|
+
}
|
330
|
+
|
331
|
+
@send_queue << data
|
332
|
+
@logger.write("queueing up retransmitted results #{@unconfirmed_idents.keys}")
|
333
|
+
end
|
266
334
|
end
|
267
335
|
|
268
336
|
# if we were disconnected in the closing phase, then resend the EOT
|
@@ -110,6 +110,7 @@ module RSpec::Buildkite::Analytics
|
|
110
110
|
@socket.write(frame.to_s)
|
111
111
|
rescue Errno::EPIPE, Errno::ECONNRESET, OpenSSL::SSL::SSLError => e
|
112
112
|
return unless @socket
|
113
|
+
return if type == :close
|
113
114
|
@session.logger.write("got #{e}, attempting disconnected flow")
|
114
115
|
@session.disconnected(self)
|
115
116
|
disconnect
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/hash/indifferent_access"
|
4
|
+
|
3
5
|
module RSpec::Buildkite::Analytics
|
4
6
|
class Tracer
|
5
7
|
class Span
|
@@ -13,15 +15,15 @@ module RSpec::Buildkite::Analytics
|
|
13
15
|
@children = []
|
14
16
|
end
|
15
17
|
|
16
|
-
def
|
18
|
+
def as_hash
|
17
19
|
{
|
18
20
|
section: section,
|
19
21
|
start_at: start_at,
|
20
22
|
end_at: end_at,
|
21
23
|
duration: end_at - start_at,
|
22
24
|
detail: detail,
|
23
|
-
children: children.map(&:
|
24
|
-
}
|
25
|
+
children: children.map(&:as_hash),
|
26
|
+
}.with_indifferent_access
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
@@ -57,7 +59,7 @@ module RSpec::Buildkite::Analytics
|
|
57
59
|
end
|
58
60
|
|
59
61
|
def history
|
60
|
-
@top.
|
62
|
+
@top.as_hash
|
61
63
|
end
|
62
64
|
end
|
63
65
|
end
|
@@ -22,22 +22,15 @@ require "securerandom"
|
|
22
22
|
module RSpec::Buildkite::Analytics
|
23
23
|
class Uploader
|
24
24
|
class Trace
|
25
|
-
attr_accessor :example
|
25
|
+
attr_accessor :example, :failure_reason, :failure_expanded
|
26
26
|
attr_reader :id, :history
|
27
27
|
|
28
28
|
def initialize(example, history)
|
29
29
|
@id = SecureRandom.uuid
|
30
30
|
@example = example
|
31
31
|
@history = history
|
32
|
-
|
33
|
-
|
34
|
-
def failure_message
|
35
|
-
case example.exception
|
36
|
-
when RSpec::Expectations::ExpectationNotMetError
|
37
|
-
example.exception.message
|
38
|
-
when Exception
|
39
|
-
"#{example.exception.class}: #{example.exception.message}"
|
40
|
-
end
|
32
|
+
@failure_reason = nil
|
33
|
+
@failure_expanded = []
|
41
34
|
end
|
42
35
|
|
43
36
|
def result_state
|
@@ -48,7 +41,7 @@ module RSpec::Buildkite::Analytics
|
|
48
41
|
end
|
49
42
|
end
|
50
43
|
|
51
|
-
def
|
44
|
+
def as_hash
|
52
45
|
{
|
53
46
|
id: @id,
|
54
47
|
scope: example.example_group.metadata[:full_description],
|
@@ -57,9 +50,10 @@ module RSpec::Buildkite::Analytics
|
|
57
50
|
location: example.location,
|
58
51
|
file_name: generate_file_name(example),
|
59
52
|
result: result_state,
|
60
|
-
|
53
|
+
failure_reason: failure_reason,
|
54
|
+
failure_expanded: failure_expanded,
|
61
55
|
history: history,
|
62
|
-
}
|
56
|
+
}.with_indifferent_access.compact
|
63
57
|
end
|
64
58
|
|
65
59
|
private
|
@@ -121,7 +115,8 @@ module RSpec::Buildkite::Analytics
|
|
121
115
|
"Content-Type" => "application/json",
|
122
116
|
})
|
123
117
|
contact.body = {
|
124
|
-
run_env: CI.env
|
118
|
+
run_env: CI.env,
|
119
|
+
format: "websocket"
|
125
120
|
}.to_json
|
126
121
|
|
127
122
|
response = begin
|
@@ -130,6 +125,8 @@ module RSpec::Buildkite::Analytics
|
|
130
125
|
puts "Buildkite Test Analytics: Error communicating with the server: #{e.message}"
|
131
126
|
end
|
132
127
|
|
128
|
+
return unless response
|
129
|
+
|
133
130
|
case response.code
|
134
131
|
when "401"
|
135
132
|
puts "Buildkite Test Analytics: Invalid Suite API key. Please double check your Suite API key."
|
@@ -141,10 +138,12 @@ module RSpec::Buildkite::Analytics
|
|
141
138
|
end
|
142
139
|
else
|
143
140
|
request_id = response.to_hash["x-request-id"]
|
144
|
-
puts "
|
141
|
+
puts "rspec-buildkite-analytics could not establish an initial connection with Buildkite. You may be missing some data for this test suite, please contact support."
|
145
142
|
end
|
146
143
|
else
|
147
|
-
|
144
|
+
if !!ENV["BUILDKITE_BUILD_ID"]
|
145
|
+
puts "Buildkite Test Analytics: No Suite API key provided. You can get the API key from your Suite settings page."
|
146
|
+
end
|
148
147
|
end
|
149
148
|
end
|
150
149
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "timeout"
|
4
|
+
require "tmpdir"
|
4
5
|
|
5
6
|
require_relative "analytics/version"
|
6
7
|
|
@@ -23,7 +24,7 @@ module RSpec::Buildkite::Analytics
|
|
23
24
|
self.api_token = token || ENV["BUILDKITE_ANALYTICS_TOKEN"]
|
24
25
|
self.url = url || DEFAULT_URL
|
25
26
|
self.debug_enabled = debug_enabled || !!(ENV["BUILDKITE_ANALYTICS_DEBUG_ENABLED"])
|
26
|
-
self.debug_filepath = debug_filepath || ENV["BUILDKITE_ANALYTICS_DEBUG_FILEPATH"]
|
27
|
+
self.debug_filepath = debug_filepath || ENV["BUILDKITE_ANALYTICS_DEBUG_FILEPATH"] || Dir.tmpdir
|
27
28
|
|
28
29
|
require_relative "analytics/uploader"
|
29
30
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-buildkite-analytics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Buildkite
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|