rspec-osc7501 0.1.0 → 0.1.1

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: d5789a92d347d7a152a9b2ce9a2edd188a21d6209beb9f41247f1a0713598233
4
- data.tar.gz: 7ed3f5e657885323cb1381ecdb6202f299dd1f7db5f7239120329b9cecdb9c29
3
+ metadata.gz: c98998ec22422da0c3b18c0e1718b0f3fb8eb572d8e11c14f02848c1761d4a08
4
+ data.tar.gz: ec72f528a52941deacc832e7e1036b079aa4ffce792092af0840d01d9e01e154
5
5
  SHA512:
6
- metadata.gz: 1934634e2afade69128ade89e9d1aa8a27eafa1449142c5b3807411e9af5eec7b8e6b538c13fd3e2fb70a63b773719a76cc85521688761919aece4dac57699b8
7
- data.tar.gz: 1b0a02f82acf691eb1e36dc9f6c44f7078daeef4faff113da8c1bc18d210493cc745f1131359dc2c4018929364a82d2a997ee89be43333d5b77f98f485c7d84f
6
+ metadata.gz: 2de8d63a1811c22b49e379ff10ad2e270ee45f9d6b71567a80c1a4f3a194558f3eda12e85cba8993df4e37068067647a48d41b77bbffacb41758474cc8ded60b
7
+ data.tar.gz: 9ddaf26a6534c8a8f38d65b9bc4af8f507ed67ecf81ab9fe30a2e8ee56518d231c53a3b71562637cf8a7e5e2f9b2e7b7082158a037f89ef3d379b235e5f1fd5c
data/CHANGELOG.md CHANGED
@@ -2,5 +2,14 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.1.1 - 2026-11-08
6
+
7
+ - Fix formatter outcomes and stream handling ([3454f8a](https://github.com/cosgroveb/rspec-osc7501/commit/3454f8a63e05e8955ac42038d494d90cfaec9429))
8
+ - Bound formatter text sanitization work ([5d2fc9f](https://github.com/cosgroveb/rspec-osc7501/commit/5d2fc9f9c5465e3086d3673e699e03fd3d8f5c86))
9
+ - Automate tested RubyGems releases ([86f87f3](https://github.com/cosgroveb/rspec-osc7501/commit/86f87f3faadfb313377d1ece592e12d45f228632))
10
+ - Bound CI runtime and cancel superseded checks ([0d4660d](https://github.com/cosgroveb/rspec-osc7501/commit/0d4660d2d6b90a4208fc8f0faeac8e50e5c3796c))
11
+
12
+ ## 0.1.0 - 2026-11-07
13
+
5
14
  - Add an opt-in OSC 7501 formatter for RSpec suite progress and outcomes.
6
15
  - Support TTY detection, explicit output capture, and a configurable suite title.
data/CONTRIBUTING.md CHANGED
@@ -18,8 +18,58 @@ bundle exec rake package
18
18
  bundle exec rake rdoc
19
19
  ```
20
20
 
21
- The package is `pkg/rspec-osc7501-0.1.0.gem`. Open `tmp/rdoc/index.html` to check
21
+ The package is `pkg/rspec-osc7501-<version>.gem`. Open `tmp/rdoc/index.html` to check
22
22
  rendered documentation. Keep generated files out of commits.
23
23
 
24
- Update usage or behavior documentation for user-visible changes and add a brief
25
- entry under `Unreleased` in `CHANGELOG.md`. Preserve the Apache-2.0 license text.
24
+ Update usage or behavior documentation for user-visible changes. Write commit
25
+ subjects that describe the change, because release notes use those subjects.
26
+ Do not maintain `Unreleased` entries by hand. Preserve the Apache-2.0 license text.
27
+
28
+ ## Release
29
+
30
+ Release the reviewed commits on remote `main` with an explicit stable version:
31
+
32
+ ```sh
33
+ gh workflow run release.yml --ref main -f version=0.1.1
34
+ ```
35
+
36
+ The workflow captures `main`, updates `VERSION`, and generates CHANGELOG bullets
37
+ from non-merge commit subjects since the previous release tag. It preserves
38
+ older changelog sections and uses the same notes for the GitHub Release.
39
+ Versions must use `major.minor.patch` without a `v` prefix or prerelease suffix.
40
+ A new version must exceed the current version and include new commits.
41
+
42
+ The full CI matrix tests the prepared release commit before the workflow pushes
43
+ it and its tag together. If `main` advances during testing, the workflow stops.
44
+ After the push, it publishes to RubyGems, then creates the GitHub Release. No
45
+ intermediate approval is required.
46
+
47
+ ### One-time publishing setup
48
+
49
+ On the gem's RubyGems page, configure a Trusted Publisher with owner `cosgroveb`,
50
+ repository `rspec-osc7501`, and workflow `release.yml`. Leave the environment
51
+ blank. The workflow uses short-lived OIDC credentials, with no RubyGems token
52
+ stored in GitHub secrets. Repository Actions permissions must permit the
53
+ workflow's `contents: write` and `id-token: write` requests.
54
+
55
+ ### Failed releases
56
+
57
+ Inspect the run and its publication summary:
58
+
59
+ ```sh
60
+ gh run list --workflow release.yml
61
+ gh run view <run-id> --log-failed
62
+ ```
63
+
64
+ RubyGems publication is the release. A later GitHub Release failure leaves the
65
+ workflow failed but does not undo the published gem. Rerun the same version to
66
+ finish missing steps:
67
+
68
+ ```sh
69
+ gh workflow run release.yml --ref main -f version=0.1.1
70
+ ```
71
+
72
+ When the tag exists, the workflow uses that exact commit and recorded notes,
73
+ verifies matching publications, and skips completed steps. It does not move
74
+ tags, replace published gems, or retry automatically. If the retry fails,
75
+ inspect the logs before trying again.
data/README.md CHANGED
@@ -8,14 +8,12 @@ Requires MRI Ruby 3.3 or newer and `rspec-core >= 3.12, < 4`.
8
8
 
9
9
  ## Install
10
10
 
11
- This gem is unreleased. Add the source branch to your Gemfile:
11
+ Add the gem to your Gemfile:
12
12
 
13
13
  ```ruby
14
14
  group :test do
15
15
  gem "rspec"
16
- gem "rspec-osc7501",
17
- git: "https://github.com/cosgroveb/rspec-osc7501",
18
- branch: "feature/osc7501-formatter"
16
+ gem "rspec-osc7501", "~> 0.1"
19
17
  end
20
18
  ```
21
19
 
data/doc/behavior.rdoc CHANGED
@@ -7,10 +7,12 @@ ordinary formatter too if you want RSpec's progress or documentation output.
7
7
  == Output and settings
8
8
 
9
9
  The formatter uses the stream RSpec supplies, including <tt>--out</tt>. It leaves
10
- that stream open. Settings apply when RSpec constructs the formatter.
10
+ that stream open and flushes each frame when the stream supports flushing.
11
+ Settings apply when RSpec constructs the formatter.
11
12
 
12
13
  [<tt>RSPEC_OSC7501=auto</tt>]
13
- Emit to a TTY. This is the default, including an unset variable.
14
+ Emit to a TTY. Streams without <tt>tty?</tt> remain silent.
15
+ This is the default, including an unset variable.
14
16
  [<tt>RSPEC_OSC7501=off</tt>]
15
17
  Emit no frames.
16
18
  [<tt>RSPEC_OSC7501=force</tt>]
@@ -47,10 +49,13 @@ The final frame includes RSpec's summary counts and duration, with no progress:
47
49
 
48
50
  The formatter reads RSpec's private early-stop flag at summary time. A reached
49
51
  fail-fast threshold or outside-example error takes precedence over that flag.
52
+ Zero and negative fail-fast thresholds follow RSpec's threshold comparison.
50
53
  A coincident SIGINT can therefore report error. An early stop after a failure
51
54
  can report idle and retain the failure count. The formatter preserves RSpec's
52
55
  exit status.
53
56
 
57
+ An exception already active when the suite starts does not determine its result.
58
+
54
59
  Close emits no additional frame after a summary. A started run that closes
55
60
  without a summary reports an incomplete error once.
56
61
 
@@ -74,6 +79,11 @@ replaces invalid encoding, and truncates on character boundaries. Decoded titles
74
79
  are at most 192 bytes, decoded messages at most 2048 bytes, and frames at most
75
80
  4096 bytes.
76
81
 
82
+ Before sanitization, the formatter keeps at most 288 input bytes for titles and
83
+ 3072 for messages. This bounds sanitization work with 50% headroom for stripped
84
+ controls. Control-heavy input can produce shorter output. A character split by
85
+ the input cap becomes a replacement character before the final output limit.
86
+
77
87
  IOError or SystemCallError disables further status output for that formatter
78
88
  instance. Other exceptions propagate.
79
89
 
data/doc/usage.rdoc CHANGED
@@ -1,7 +1,7 @@
1
1
  = Usage
2
2
 
3
3
  Add OSC 7501 status alongside an ordinary RSpec formatter.
4
- See the {README}[rdoc-ref:README.md] for source installation.
4
+ See the {README}[rdoc-ref:README.md] for installation.
5
5
 
6
6
  == Configure a project
7
7
 
@@ -22,6 +22,7 @@ module RSpec
22
22
 
23
23
  # Starts suite progress from the example count in +notification+.
24
24
  def start(notification)
25
+ @inherited_exception = $!
25
26
  @started = true
26
27
  @total = notification.count
27
28
  @completed = @failed = @pending = 0
@@ -62,6 +63,7 @@ module RSpec
62
63
  # Final output bypasses throttling and omits progress.
63
64
  def dump_summary(notification)
64
65
  active_exception = $!
66
+ active_exception = nil if active_exception.equal?(@inherited_exception)
65
67
  @summarized = true
66
68
  state = final_state(notification, active_exception)
67
69
  outcome = { "done" => "Completed", "error" => "Failed", "idle" => "Stopped" }.fetch(state)
@@ -124,7 +126,7 @@ module RSpec
124
126
  def fail_fast_reached?(failure_count)
125
127
  threshold = RSpec.configuration.fail_fast
126
128
  threshold = 1 if threshold == true
127
- threshold.is_a?(Integer) && threshold.positive? && failure_count >= threshold
129
+ threshold.is_a?(Integer) && failure_count >= threshold
128
130
  end
129
131
  end
130
132
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RSpec
4
4
  module OSC7501
5
- VERSION = "0.1.0"
5
+ VERSION = "0.1.1"
6
6
  end
7
7
  end
@@ -7,7 +7,7 @@ module RSpec
7
7
  raise ArgumentError, "RSPEC_OSC7501 must be auto, off, or force" unless %w[auto off force].include?(mode)
8
8
 
9
9
  @output = output
10
- @enabled = mode == "force" || (mode == "auto" && output.tty?)
10
+ @enabled = mode == "force" || (mode == "auto" && output.respond_to?(:tty?) && output.tty?)
11
11
  @title = encode(title, 192) if @enabled
12
12
  rescue IOError, SystemCallError
13
13
  @enabled = false
@@ -19,6 +19,7 @@ module RSpec
19
19
  fields = ["app=rspec", "title=#{@title}", "state=#{state}", "msg=#{encode(msg, 2048)}"]
20
20
  fields << "progress=#{progress.to_i.clamp(0, 100)}" if state == "working" && !progress.nil?
21
21
  @output.write("\e]7501;#{fields.join(':')}\e\\")
22
+ @output.flush if @output.respond_to?(:flush)
22
23
  rescue IOError, SystemCallError
23
24
  @enabled = false
24
25
  end
@@ -26,7 +27,8 @@ module RSpec
26
27
  private
27
28
 
28
29
  def encode(text, byte_limit)
29
- clean = text.to_s.encode("UTF-8", invalid: :replace, undef: :replace).gsub(/[\u0000-\u001F\u007F-\u009F]/, "")
30
+ input = text.to_s.byteslice(0, sanitization_byte_limit(byte_limit))
31
+ clean = input.encode("UTF-8", invalid: :replace, undef: :replace).gsub(/[\u0000-\u001F\u007F-\u009F]/, "")
30
32
  bytes = 0
31
33
  bounded = clean.each_char.take_while do |char|
32
34
  bytes += char.bytesize
@@ -34,6 +36,11 @@ module RSpec
34
36
  end.join
35
37
  [bounded].pack("m0")
36
38
  end
39
+
40
+ # Bound sanitization work with 50% headroom for stripped controls.
41
+ def sanitization_byte_limit(output_byte_limit)
42
+ output_byte_limit + output_byte_limit / 2
43
+ end
37
44
  end
38
45
  end
39
46
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-osc7501
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Cosgrove