ci-queue 0.88.0 → 0.89.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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/ci/queue/queue_entry.rb +3 -1
- data/lib/ci/queue/redis/build_record.rb +14 -0
- data/lib/ci/queue/redis/retry.rb +15 -0
- data/lib/ci/queue/redis/worker.rb +9 -0
- data/lib/ci/queue/version.rb +1 -1
- data/lib/minitest/queue.rb +10 -1
- data/lib/rspec/queue/build_status_recorder.rb +2 -2
- data/lib/rspec/queue.rb +4 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 87b11dfe365c8f57a79ef1d5b65e4f422a1fce2bd94d51b0d653d10bfb95120a
|
|
4
|
+
data.tar.gz: 1a530c84f9883b85f0784b33e67044f5a325a5815dc06d4b89872b76d1127a74
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 25e7f86d44fc3428e6f1d08430a3940348ae9d2d2561c190894d7a6e1b197d00b22a97fefcb5ade8462d2ccc0e14255ff9d4f10571e5f1f99dd8758b45d8a066
|
|
7
|
+
data.tar.gz: 0c676475b941684ad92d43088612e31adb597f2f2c22f383e55c8d2dbc2cfa68646e013a58000191f5fecb16aee8151b5ce8f14cd97fe2d9ca2f11c3fd57cf3f
|
data/Gemfile.lock
CHANGED
data/lib/ci/queue/queue_entry.rb
CHANGED
|
@@ -17,7 +17,9 @@ module CI
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def self.format(test_id, file_path)
|
|
20
|
-
|
|
20
|
+
raise ArgumentError, "file_path is required for '#{test_id}' — the test file path must be resolvable" if file_path.nil? || file_path.empty?
|
|
21
|
+
canonical = load_error_payload?(file_path) ? file_path : ::File.expand_path(file_path)
|
|
22
|
+
JSON.dump({ test_id: test_id, file_path: canonical })
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def self.load_error_payload?(file_path)
|
|
@@ -145,6 +145,10 @@ module CI
|
|
|
145
145
|
redis.hgetall(key('error-reports')).transform_keys { |entry| CI::Queue::QueueEntry.test_id(entry) }
|
|
146
146
|
end
|
|
147
147
|
|
|
148
|
+
def failed_test_entries
|
|
149
|
+
redis.hkeys(key('error-reports'))
|
|
150
|
+
end
|
|
151
|
+
|
|
148
152
|
def flaky_reports
|
|
149
153
|
redis.smembers(key('flaky-reports')).map { |entry| CI::Queue::QueueEntry.test_id(entry) }
|
|
150
154
|
end
|
|
@@ -177,6 +181,16 @@ module CI
|
|
|
177
181
|
pipeline.hdel(key(stat_name), config.worker_id)
|
|
178
182
|
end
|
|
179
183
|
end
|
|
184
|
+
# Purge any error-report-deltas that reference this worker so that
|
|
185
|
+
# apply_error_report_delta_correction cannot double-subtract from
|
|
186
|
+
# the now-zeroed counters on a subsequent successful retry.
|
|
187
|
+
deltas = redis.hgetall(key('error-report-deltas'))
|
|
188
|
+
to_delete = deltas.filter_map do |entry, delta_json|
|
|
189
|
+
entry if JSON.parse(delta_json)['worker_id'].to_s == config.worker_id.to_s
|
|
190
|
+
rescue JSON::ParserError
|
|
191
|
+
nil
|
|
192
|
+
end
|
|
193
|
+
redis.hdel(key('error-report-deltas'), *to_delete) unless to_delete.empty?
|
|
180
194
|
end
|
|
181
195
|
|
|
182
196
|
private
|
data/lib/ci/queue/redis/retry.rb
CHANGED
|
@@ -28,9 +28,24 @@ module CI
|
|
|
28
28
|
self
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
# Queue a Redis SADD so that BuildRecord#record_success can include this
|
|
32
|
+
# in its multi-exec transaction. Without this, Static#acknowledge returns
|
|
33
|
+
# a Ruby value (not a Redis future), shifting the result indices and
|
|
34
|
+
# breaking the stats delta correction.
|
|
35
|
+
def acknowledge(entry, error: nil, pipeline: redis)
|
|
36
|
+
@progress += 1
|
|
37
|
+
return @progress unless pipeline
|
|
38
|
+
test_id = CI::Queue::QueueEntry.test_id(entry)
|
|
39
|
+
pipeline.sadd(key('processed'), test_id)
|
|
40
|
+
end
|
|
41
|
+
|
|
31
42
|
private
|
|
32
43
|
|
|
33
44
|
attr_reader :redis
|
|
45
|
+
|
|
46
|
+
def key(*args)
|
|
47
|
+
['build', config.build_id, *args].join(':')
|
|
48
|
+
end
|
|
34
49
|
end
|
|
35
50
|
end
|
|
36
51
|
end
|
|
@@ -158,6 +158,15 @@ module CI
|
|
|
158
158
|
log.select! { |entry| failures.include?(CI::Queue::QueueEntry.test_id(entry)) }
|
|
159
159
|
log.uniq! { |entry| CI::Queue::QueueEntry.test_id(entry) }
|
|
160
160
|
log.reverse!
|
|
161
|
+
|
|
162
|
+
if log.empty?
|
|
163
|
+
# Per-worker log has no matching failures — this worker didn't run
|
|
164
|
+
# the failing tests (e.g. Buildkite rebuild with new worker IDs,
|
|
165
|
+
# or a different parallel slot). Fall back to ALL unresolved
|
|
166
|
+
# failures from error-reports so any worker can retry them.
|
|
167
|
+
log = redis.hkeys(key('error-reports'))
|
|
168
|
+
end
|
|
169
|
+
|
|
161
170
|
Retry.new(log, config, redis: redis)
|
|
162
171
|
end
|
|
163
172
|
|
data/lib/ci/queue/version.rb
CHANGED
data/lib/minitest/queue.rb
CHANGED
|
@@ -330,7 +330,16 @@ module Minitest
|
|
|
330
330
|
end
|
|
331
331
|
|
|
332
332
|
def queue_entry
|
|
333
|
-
@queue_entry ||=
|
|
333
|
+
@queue_entry ||= begin
|
|
334
|
+
unless runnable.is_a?(Module)
|
|
335
|
+
raise ArgumentError, "runnable must be a Module (got #{runnable.class}). " \
|
|
336
|
+
"Do not create SingleExample with string class names."
|
|
337
|
+
end
|
|
338
|
+
file_path = runnable.instance_method(method_name).source_location&.first
|
|
339
|
+
raise ArgumentError, "Cannot resolve source file for #{id} — " \
|
|
340
|
+
"ensure the test method is defined in a Ruby source file" if file_path.nil?
|
|
341
|
+
CI::Queue::QueueEntry.format(id, file_path)
|
|
342
|
+
end
|
|
334
343
|
end
|
|
335
344
|
|
|
336
345
|
def <=>(other)
|
|
@@ -18,13 +18,13 @@ module RSpec
|
|
|
18
18
|
|
|
19
19
|
def example_passed(notification)
|
|
20
20
|
example = notification.example
|
|
21
|
-
entry = CI::Queue::QueueEntry.format(example.id,
|
|
21
|
+
entry = CI::Queue::QueueEntry.format(example.id, example.file_path)
|
|
22
22
|
build.record_success(entry)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def example_failed(notification)
|
|
26
26
|
example = notification.example
|
|
27
|
-
entry = CI::Queue::QueueEntry.format(example.id,
|
|
27
|
+
entry = CI::Queue::QueueEntry.format(example.id, example.file_path)
|
|
28
28
|
build.record_error(entry, dump(notification))
|
|
29
29
|
end
|
|
30
30
|
|
data/lib/rspec/queue.rb
CHANGED
|
@@ -254,7 +254,10 @@ module RSpec
|
|
|
254
254
|
end
|
|
255
255
|
|
|
256
256
|
def queue_entry
|
|
257
|
-
@queue_entry ||=
|
|
257
|
+
@queue_entry ||= begin
|
|
258
|
+
file_path = example.metadata[:absolute_file_path] || example.file_path
|
|
259
|
+
CI::Queue::QueueEntry.format(id, file_path)
|
|
260
|
+
end
|
|
258
261
|
end
|
|
259
262
|
|
|
260
263
|
def <=>(other)
|