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 +4 -4
- data/CHANGELOG.md +9 -0
- data/CONTRIBUTING.md +53 -3
- data/README.md +2 -4
- data/doc/behavior.rdoc +12 -2
- data/doc/usage.rdoc +1 -1
- data/lib/rspec/osc7501/formatter.rb +3 -1
- data/lib/rspec/osc7501/version.rb +1 -1
- data/lib/rspec/osc7501/writer.rb +9 -2
- 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: c98998ec22422da0c3b18c0e1718b0f3fb8eb572d8e11c14f02848c1761d4a08
|
|
4
|
+
data.tar.gz: ec72f528a52941deacc832e7e1036b079aa4ffce792092af0840d01d9e01e154
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
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
|
|
25
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
@@ -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) &&
|
|
129
|
+
threshold.is_a?(Integer) && failure_count >= threshold
|
|
128
130
|
end
|
|
129
131
|
end
|
|
130
132
|
end
|
data/lib/rspec/osc7501/writer.rb
CHANGED
|
@@ -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
|
-
|
|
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
|