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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ac982ecc1b30c78d14e45bbbe7d8e26841879eae6fec791dd82508159ce6c8dd
4
- data.tar.gz: 7f960c1a77b8e93bd8c18894b86f428df16f181f671bb7e000063a968e50374c
3
+ metadata.gz: 87b11dfe365c8f57a79ef1d5b65e4f422a1fce2bd94d51b0d653d10bfb95120a
4
+ data.tar.gz: 1a530c84f9883b85f0784b33e67044f5a325a5815dc06d4b89872b76d1127a74
5
5
  SHA512:
6
- metadata.gz: 1582e95243e4939268acc7bbaced2fc90471b0b86934d35169647ccde1e19c8d03027650e1f9efa909c2d6aafc85c8cce8a251c65de3cecdc906e64da8bb2a0b
7
- data.tar.gz: d8c67176e15c7d78b175af35309bab1136a3053da0db9404449d5770b764bba1e0d25c6671607c090d5e8951e65711ea94eded4cd59f50032b8336fea1eeed7b
6
+ metadata.gz: 25e7f86d44fc3428e6f1d08430a3940348ae9d2d2561c190894d7a6e1b197d00b22a97fefcb5ade8462d2ccc0e14255ff9d4f10571e5f1f99dd8758b45d8a066
7
+ data.tar.gz: 0c676475b941684ad92d43088612e31adb597f2f2c22f383e55c8d2dbc2cfa68646e013a58000191f5fecb16aee8151b5ce8f14cd97fe2d9ca2f11c3fd57cf3f
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ci-queue (0.88.0)
4
+ ci-queue (0.89.0)
5
5
  logger
6
6
 
7
7
  GEM
@@ -17,7 +17,9 @@ module CI
17
17
  end
18
18
 
19
19
  def self.format(test_id, file_path)
20
- JSON.dump({ test_id: test_id, file_path: file_path })
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
@@ -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
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module CI
4
4
  module Queue
5
- VERSION = '0.88.0'
5
+ VERSION = '0.89.0'
6
6
  DEV_SCRIPTS_ROOT = ::File.expand_path('../../../../../redis', __FILE__)
7
7
  RELEASE_SCRIPTS_ROOT = ::File.expand_path('../redis', __FILE__)
8
8
  end
@@ -330,7 +330,16 @@ module Minitest
330
330
  end
331
331
 
332
332
  def queue_entry
333
- @queue_entry ||= CI::Queue::QueueEntry.format(id, nil)
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, nil)
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, nil)
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 ||= CI::Queue::QueueEntry.format(id, nil)
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)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ci-queue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.88.0
4
+ version: 0.89.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean Boussier