specbandit 0.1.0 → 0.5.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: bc3e7d15445689d7dfb61865891f47958e87c89cf65052b7351c4ec788bec5d2
4
- data.tar.gz: 2b54637983a2e0cac8beb4d4521d0f7722819a0ef211b5089dc51915275c26e8
3
+ metadata.gz: dd0cef232a7dfa2dd4109d150bd63dbdaac27f65c87e9a9c4a8c495678fdc8f0
4
+ data.tar.gz: c0a7505268abdc305f6d095fd75788ee5180c4e911972af8f95397bb57241358
5
5
  SHA512:
6
- metadata.gz: 3268930d24a06356a28c8fe472a180d8ae0a84c4cd1ee7fbf33e9ae36f2cfe5b34d2d86746c1a165e7a284e0e2ba731f52036210198d1073da96cf5313a9ec89
7
- data.tar.gz: 22bd3603d6038e55d8540fc1a155182e71dfe95bdb21328a3c369e677185931a4fe9427b5d12286dcf2113f492323c199c97577fac8691f3e5bcbbc94f8f9ef7
6
+ metadata.gz: 93c598ec5a9e0a542c0f86159ba3a70f7d7712b4c7f1c0bdf264cd9316363b483470986af3f6b619d326a52ce6d14cbd4c3ffff91e681d8c7eb7ddb8f1a2e150
7
+ data.tar.gz: 7974be5fd63f662d6db8a3b99cf00aeb7a0f75b0742c74a585c8cb7388686673507e2b23e0eb836cf1ec5c6b698585ef5eba0ec106b9436f6927409cbc59c85e
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'io/wait'
4
+
3
5
  module Specbandit
4
6
  class Publisher
5
7
  attr_reader :queue, :key, :key_ttl, :output
@@ -32,8 +34,11 @@ module Specbandit
32
34
  private
33
35
 
34
36
  def resolve_files(files:, pattern:)
35
- # Priority 1: stdin (if not a TTY)
36
- return $stdin.each_line.map(&:strip).reject(&:empty?) unless $stdin.tty?
37
+ # Priority 1: stdin (only when data is actually piped in)
38
+ if !$stdin.tty? && $stdin.ready?
39
+ stdin_files = $stdin.each_line.map(&:strip).reject(&:empty?)
40
+ return stdin_files if stdin_files.any?
41
+ end
37
42
 
38
43
  # Priority 2: --pattern flag (Dir.glob in Ruby, no shell expansion)
39
44
  return Dir.glob(pattern).sort if pattern && !pattern.empty?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Specbandit
4
- VERSION = '0.1.0'
4
+ VERSION = '0.5.0'
5
5
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'stringio'
3
4
  require 'rspec/core'
4
5
 
5
6
  module Specbandit
@@ -115,10 +116,7 @@ module Specbandit
115
116
  end
116
117
 
117
118
  def run_rspec_batch(files)
118
- # Clear example state from previous batches so RSpec can run cleanly
119
- # in the same process. This preserves configuration but resets
120
- # the world (example groups, examples, shared groups, etc.).
121
- RSpec.clear_examples
119
+ reset_rspec_state
122
120
 
123
121
  args = files + rspec_opts
124
122
  err = StringIO.new
@@ -133,5 +131,33 @@ module Specbandit
133
131
  rspec_err = err&.string
134
132
  output.print(rspec_err) unless rspec_err.nil? || rspec_err.empty?
135
133
  end
134
+
135
+ # Reset RSpec state between batches so each batch runs cleanly.
136
+ #
137
+ # RSpec.clear_examples resets example groups, the reporter, filters, and
138
+ # the start-time clock -- but it leaves three critical pieces of state
139
+ # that cause cascading failures when running multiple batches in the
140
+ # same process:
141
+ #
142
+ # 1. output_stream -- After batch #1, Runner#configure sets
143
+ # output_stream to a StringIO. On batch #2+, the guard
144
+ # `if output_stream == $stdout` is permanently false, so the new
145
+ # `out` is never used. All RSpec output silently goes to the stale
146
+ # batch-1 StringIO.
147
+ #
148
+ # 2. wants_to_quit -- If any batch triggers a load error or fail-fast,
149
+ # this flag is set to true. On subsequent batches, Runner#setup
150
+ # returns immediately and Runner#run does exit_early -- specs are
151
+ # never loaded or run.
152
+ #
153
+ # 3. non_example_failure -- Once set, exit_code() unconditionally
154
+ # returns the failure exit code, even if all examples passed.
155
+ #
156
+ def reset_rspec_state
157
+ RSpec.clear_examples
158
+ RSpec.world.wants_to_quit = false
159
+ RSpec.world.non_example_failure = false
160
+ RSpec.configuration.output_stream = $stdout
161
+ end
136
162
  end
137
163
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: specbandit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ferran Basora
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-04-08 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: redis
@@ -75,7 +74,6 @@ dependencies:
75
74
  description: A work-stealing distributed RSpec runner. Push spec file paths to a Redis
76
75
  list, then multiple CI runners atomically steal batches and execute them in-process
77
76
  via RSpec::Core::Runner.
78
- email:
79
77
  executables:
80
78
  - specbandit
81
79
  extensions: []
@@ -94,7 +92,6 @@ homepage: https://github.com/factorialco/specbandit
94
92
  licenses:
95
93
  - MIT
96
94
  metadata: {}
97
- post_install_message:
98
95
  rdoc_options: []
99
96
  require_paths:
100
97
  - lib
@@ -109,8 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
106
  - !ruby/object:Gem::Version
110
107
  version: '0'
111
108
  requirements: []
112
- rubygems_version: 3.5.16
113
- signing_key:
109
+ rubygems_version: 4.0.6
114
110
  specification_version: 4
115
111
  summary: Distributed RSpec runner using Redis as a work queue
116
112
  test_files: []