rspec_junit_formatter 0.6.0 → 0.6.2

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: 903f156687c6fff260143332222e9950fca53b5306bcde7cf197c44f3af4acf7
4
- data.tar.gz: 1d2ffca113b3cd78b3230d66ed41268609ce38f06e50da6cd196af9073670500
3
+ metadata.gz: 5284f5c3c374244eebe552b1284e12e846f0db274a6758ab2b3bf988828a5ecb
4
+ data.tar.gz: bba94018c3622f87b5a25d31d1dfcf6f3f52ab306234c67f32cfdb5526168835
5
5
  SHA512:
6
- metadata.gz: f8d32b7a3b5dec828fe29c714755b3698ad8a48b1cfc92185b6f53e5eb4a6ab47adae5cb74743cbc6b5814d0a5d61d15d49b632aadd5afdede74820628796687
7
- data.tar.gz: 76537f5a365796f1e062cbfde157f8f48c163b7973ae6a1faae533cbf4684bd3c29cd26d6cb344eac8c46c0ae950f854b48f21bbf2bd28bfbf2ebab6e12b639e
6
+ metadata.gz: 130f2aa5ff8c848fd971dd432a946452561eb8509bd9503525f4716d71acc7b7ac031ce81d0468eba463c0a808cb58e3c8121d9b139613af113397a1ef422126
7
+ data.tar.gz: db4e33312c94d947595627d342be7d3b483b4ca1c98fb53672851c58637728e11352d4a3102101a4f6cf81b0cf240a272dadd92c77c1861f0a3140727f52cd41
data/README.md CHANGED
@@ -11,6 +11,18 @@
11
11
  [circleci-junit]: https://circleci.com/docs/2.0/collect-test-data/
12
12
  [gitlab-junit]: https://docs.gitlab.com/ee/ci/unit_test_reports.html#ruby-example
13
13
 
14
+ ## Legacy release
15
+
16
+ **0.6.2 is the final release for older Ruby and RSpec versions.** It retains Ruby >= 2.3 and RSpec >= 2, < 4 (except 2.12.0), with the latest encoding and aggregate failure fixes. See [tested versus permitted versions](#tested-versus-permitted-versions) for coverage and limitations.
17
+
18
+ The next release will require Ruby >= 3.3 and RSpec >= 3.13. If you must keep an older Ruby **or** an older RSpec, use:
19
+
20
+ ```ruby
21
+ gem "rspec_junit_formatter", "0.6.2", require: false
22
+ ```
23
+
24
+ Then run `bundle update rspec_junit_formatter`. Without Bundler, use `gem install rspec_junit_formatter -v 0.6.2`. Upgrading Ruby alone is not enough if your project must keep an older RSpec.
25
+
14
26
  ## Usage
15
27
 
16
28
  Install the gem:
@@ -33,7 +45,7 @@ You can use it in combination with other [formatters][rspec-formatters], too:
33
45
  rspec --format progress --format RspecJunitFormatter --out rspec.xml
34
46
  ```
35
47
 
36
- [rspec-formatters]: https://relishapp.com/rspec/rspec-core/v/3-6/docs/formatters
48
+ [rspec-formatters]: https://rspec.info/features/3-12/rspec-core/formatters/
37
49
 
38
50
  ### Using in your project with Bundler
39
51
 
@@ -42,7 +54,7 @@ Add it to your Gemfile if you're using [Bundler][bundler]. Put it in the same gr
42
54
  ```ruby
43
55
  group :test do
44
56
  gem "rspec"
45
- gem "rspec_junit_formatter"
57
+ gem "rspec_junit_formatter", require: false
46
58
  end
47
59
  ```
48
60
 
@@ -53,7 +65,7 @@ Put the same arguments as the commands above in [your `.rspec`][rspec-file]:
53
65
  --out rspec.xml
54
66
  ```
55
67
  [bundler]: https://bundler.io
56
- [rspec-file]: https://relishapp.com/rspec/rspec-core/v/3-6/docs/configuration/read-command-line-configuration-options-from-files
68
+ [rspec-file]: https://rspec.info/features/3-12/rspec-core/configuration/read-options-from-file/
57
69
 
58
70
  ### Parallel tests
59
71
 
@@ -90,23 +102,119 @@ RSpec.configure do |config|
90
102
  end
91
103
  ```
92
104
 
93
- Note that this example captures all output from every example all the time, potentially interfering with local debugging. You might like to restrict this to only on CI, or by using [rspec filters](https://relishapp.com/rspec/rspec-core/docs/hooks/filters).
105
+ Note that this example captures all output from every example all the time, potentially interfering with local debugging. You might like to restrict this to only on CI, or by using [rspec filters](https://rspec.info/features/3-12/rspec-core/hooks/filtering/).
94
106
 
95
107
  ## Caveats
96
108
 
97
109
  * XML can only represent a [limited subset of characters][xml-charsets] which excludes null bytes and most control characters. This gem will use character entities where possible and fall back to replacing invalid characters with Ruby-like escape codes otherwise. For example, the null byte becomes `\0`.
110
+ * When converting report text to UTF-8 for XML output, invalid byte sequences and characters with no UTF-8 conversion are replaced with `�` (U+FFFD REPLACEMENT CHARACTER). The formatter uses each string's declared encoding; it does not guess the encoding of binary data.
98
111
 
99
112
  [xml-charsets]: https://www.w3.org/TR/xml/#charsets
100
113
 
101
114
  ## Development
102
115
 
103
- Run the specs with `bundle exec rake`, which uses [Appraisal][appraisal] to run the specs against all supported versions of rspec.
116
+ Use Ruby 3.4 (see [`.ruby-version`](.ruby-version)) for maintenance. Ruby 3.4 is in [normal maintenance](https://www.ruby-lang.org/en/downloads/branches/). This selects the development Ruby without changing the installed gem's requirements. Keep Ruby requirements out of the root Gemfile: Appraisal copies them into legacy Gemfiles.
117
+
118
+ Install the Bundler version recorded in `Gemfile.lock`, then test the locked development bundle:
119
+
120
+ ```sh
121
+ gem install bundler -v 4.0.23
122
+ bundle install
123
+ bundle exec rake spec
124
+ ```
125
+
126
+ The [development workflow](.github/workflows/development.yml) tests this bundle separately from the [compatibility workflow](.github/workflows/ci.yml). Use `bundle update --all` to refresh the development lockfile.
127
+
128
+ Legacy bundles are defined by [Appraisal][appraisal] and have separate Gemfiles. Select a compatible Ruby and Bundler, then run an individual bundle without the root lockfile, for example on Ruby 2.6:
129
+
130
+ ```sh
131
+ BUNDLE_GEMFILE=gemfiles/rspec_2_x.gemfile bundle install
132
+ BUNDLE_GEMFILE=gemfiles/rspec_2_x.gemfile bundle exec rake spec
133
+ ```
134
+
135
+ Plain `bundle exec rake` also runs all Appraisals outside CI. Not all historical RSpec versions run on modern Ruby, so use the combinations in the compatibility workflow rather than running all Appraisals on the maintainer Ruby.
104
136
 
105
137
  [appraisal]: https://github.com/thoughtbot/appraisal
106
138
 
139
+ ### Tested versus permitted versions
140
+
141
+ The [gemspec](rspec_junit_formatter.gemspec) permits Ruby >= 2.3 and `rspec-core` >= 2, < 4, excluding 2.12.0. These requirements allow installation; they do not mean every Ruby/RSpec combination is tested or works together.
142
+
143
+ The CI workflows test these combinations:
144
+
145
+ | Ruby | RSpec | Bundle |
146
+ | --- | --- | --- |
147
+ | 2.6–3.4 | 3.4–3.13, each minor series | Legacy Appraisals |
148
+ | 2.6–3.1 | 2.14 (`< 2.99`) and 3.0–3.3, each minor series | Legacy Appraisals |
149
+ | 3.4 and 4.0 | Current 3.13, pinned by `Gemfile.lock` | Development |
150
+
151
+ Ruby 4.0 coverage initially uses only the current RSpec development bundle, not the historical Appraisals. Ruby 2.3–2.5 remain permitted but are not covered by CI. RSpec versions allowed by the gemspec but outside the Appraisal ranges are also untested. Historical RSpec versions below 3.4 are not compatible with Ruby 3.2 or newer. Retaining installation permission does not imply that an end-of-life Ruby still receives upstream security updates.
152
+
107
153
  ## Releasing
108
154
 
109
- Bump the gem version in the gemspec, and commit. Then `bundle exec rake build` to build a gem package, `bundle exec rake install` to install and test it locally, then `bundle exec rake release` to tag and push the commits and gem.
155
+ Releases use the [Release workflow](https://github.com/sj26/rspec_junit_formatter/actions/workflows/release.yml)
156
+ and [RubyGems trusted publishing](https://guides.rubygems.org/trusted-publishing/).
157
+ GitHub Actions builds **unsigned gems**: it needs no personal signing key, persistent
158
+ RubyGems API key, or maintainer machine. Local `bundle exec rake build`, `install`,
159
+ and `release` tasks remain available; local releases may retain the maintainer's
160
+ traditional gem signatures. Do not publish the same version through both paths.
161
+
162
+ 1. Bump the gemspec version and update the changelog in a reviewed PR. Merge it
163
+ into `main`. Use a new stable `X.Y.Z` version; never reuse a published version.
164
+ 2. Tag that exact commit as `vX.Y.Z` and push the tag. Record its full commit SHA
165
+ with `git rev-parse 'vX.Y.Z^{commit}'`. Pushing a tag alone does not publish.
166
+ 3. Run the Release workflow **from `main`**, supplying the tag and full SHA. Leave
167
+ `publish` unchecked for validation only. It checks tag/version/commit agreement
168
+ and main ancestry, runs the compatibility and development suites at that SHA,
169
+ builds the gem, rejects embedded signatures, and tests a clean installation
170
+ outside the checkout. PRs also exercise the package build/install check, but
171
+ their artifacts can never be published by this workflow.
172
+ 4. Run again with the same tag and SHA and `publish` checked. After the checks pass,
173
+ review the commit and package SHA-256 in the build log, then approve the
174
+ `release` environment deployment. Sam can approve his own run. The publish job
175
+ downloads that run's exact immutable artifact, uses short-lived OIDC credentials,
176
+ and does not check out or build project code.
177
+ 5. The workflow verifies that RubyGems serves identical bytes before publishing a
178
+ GitHub release with the same gem. Check both the
179
+ [RubyGems version](https://rubygems.org/gems/rspec_junit_formatter/versions) and
180
+ [GitHub release](https://github.com/sj26/rspec_junit_formatter/releases).
181
+
182
+ ### One-time configuration
183
+
184
+ The GitHub `release` environment must require approval by `sj26`, allow
185
+ self-approval, disable admin bypass, and allow deployments only from the `main`
186
+ branch. The **Immutable release tags** repository ruleset blocks updates and
187
+ deletion of `v*` tags, with no bypass actors. Under the existing gem's
188
+ **Trusted publishers** on RubyGems, configure:
189
+
190
+ | Field | Value |
191
+ | --- | --- |
192
+ | Repository owner | `sj26` |
193
+ | Repository name | `rspec_junit_formatter` |
194
+ | Workflow filename | `release.yml` |
195
+ | Environment | `release` |
196
+
197
+ Leave reusable-workflow repository fields blank. This workflow grants
198
+ `id-token: write` only to the environment-protected publish job. Do not add a
199
+ RubyGems API key or personal signing key to repository secrets.
200
+
201
+ ### Recovery
202
+
203
+ Release runs are serialized and never auto-cancel an active publication. If a
204
+ push succeeds but a later step fails, **re-run failed jobs in the original run**
205
+ while its `release-gem` artifact is retained (30 days). This reuses the validated
206
+ bytes and requires environment approval again. An existing RubyGems version is
207
+ accepted only if its SHA-256 matches, and its downloaded bytes must also match.
208
+ An incomplete GitHub draft can resume; an existing asset must match byte-for-byte
209
+ and is never overwritten. A published GitHub release missing its gem fails closed
210
+ and needs manual inspection rather than silently changing a public release.
211
+
212
+ If the tag moved, a digest differs, or the original artifact expired, stop and
213
+ investigate. Do not delete/recreate tags, yank/re-push gems, or overwrite release
214
+ assets to force a retry. A fresh run rebuilds and is safe only if it reproduces
215
+ the same bytes; otherwise recover the original artifact or use a new version
216
+ through the normal review process. Validation-only runs do not test OIDC exchange
217
+ or publication; only a real, explicitly approved new release can prove those paths.
110
218
 
111
219
  ## License
112
220
 
@@ -88,7 +88,13 @@ private
88
88
  end
89
89
 
90
90
  def failure_for(notification)
91
- strip_diff_colors(notification.message_lines.join("\n")) << "\n" << notification.formatted_backtrace.join("\n")
91
+ exception = exception_for(notification)
92
+
93
+ if aggregate_failure?(exception)
94
+ strip_diff_colors(exception.message)
95
+ else
96
+ strip_diff_colors(notification.message_lines.join("\n")) << "\n" << notification.formatted_backtrace.join("\n")
97
+ end
92
98
  end
93
99
 
94
100
  def exception_for(notification)
@@ -141,6 +147,13 @@ private
141
147
  def stderr_for(example_notification)
142
148
  example_notification.example.metadata[:stderr]
143
149
  end
150
+
151
+ def aggregate_failure?(exception)
152
+ # Introduced in rspec 3.3
153
+ return false unless defined?(RSpec::Expectations::MultipleExpectationsNotMetError)
154
+
155
+ exception.is_a?(RSpec::Expectations::MultipleExpectationsNotMetError)
156
+ end
144
157
  end
145
158
 
146
159
  # rspec-core 3.0.x forgot to mark this as a module function which causes:
@@ -166,7 +166,7 @@ private
166
166
 
167
167
  def escape(text)
168
168
  # Make sure it's utf-8, replace illegal characters with ruby-like escapes, and replace special and discouraged characters with entities
169
- text.to_s.encode(Encoding::UTF_8).gsub(ILLEGAL_REGEXP, ILLEGAL_REPLACEMENT).gsub(DISCOURAGED_REGEXP, DISCOURAGED_REPLACEMENTS)
169
+ text.to_s.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "\uFFFD").gsub(ILLEGAL_REGEXP, ILLEGAL_REPLACEMENT).gsub(DISCOURAGED_REGEXP, DISCOURAGED_REPLACEMENTS)
170
170
  end
171
171
 
172
172
  STRIP_DIFF_COLORS_BLOCK_REGEXP = /^ ( [ ]* ) Diff: (?: \e\[ 0 m )? (?: \n \1 \e\[ \d+ (?: ; \d+ )* m .* )* /x
metadata CHANGED
@@ -1,35 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec_junit_formatter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Cochran
8
- autorequire:
9
8
  bindir: bin
10
- cert_chain:
11
- - |
12
- -----BEGIN CERTIFICATE-----
13
- MIIDXDCCAkSgAwIBAgIBATANBgkqhkiG9w0BAQsFADA6MQ0wCwYDVQQDDARzajI2
14
- MRQwEgYKCZImiZPyLGQBGRYEc2oyNjETMBEGCgmSJomT8ixkARkWA2NvbTAeFw0y
15
- MjA3MDQwMDQwNDZaFw0yMzA3MDQwMDQwNDZaMDoxDTALBgNVBAMMBHNqMjYxFDAS
16
- BgoJkiaJk/IsZAEZFgRzajI2MRMwEQYKCZImiZPyLGQBGRYDY29tMIIBIjANBgkq
17
- hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr60Eo/ttCk8GMTMFiPr3GoYMIMFvLak
18
- xSmTk9YGCB6UiEePB4THSSA5w6IPyeaCF/nWkDp3/BAam0eZMWG1IzYQB23TqIM0
19
- 1xzcNRvFsn0aQoQ00k+sj+G83j3T5OOV5OZIlu8xAChMkQmiPd1NXc6uFv+Iacz7
20
- kj+CMsI9YUFdNoU09QY0b+u+Rb6wDYdpyvN60YC30h0h1MeYbvYZJx/iZK4XY5zu
21
- 4O/FL2ChjL2CPCpLZW55ShYyrzphWJwLOJe+FJ/ZBl6YXwrzQM9HKnt4titSNvyU
22
- KzE3L63A3PZvExzLrN9u09kuWLLJfXB2sGOlw3n9t72rJiuBr3/OQQIDAQABo20w
23
- azAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU99dfRjEKFyczTeIz
24
- m3ZsDWrNC80wGAYDVR0RBBEwD4ENc2oyNkBzajI2LmNvbTAYBgNVHRIEETAPgQ1z
25
- ajI2QHNqMjYuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQCsa7k3TABBcyXotr3yCq6f
26
- xsgbMG9FR71c4wRgVNQi9O3jN64fQBbxo//BQlHfPCjs1CeU4es9xdQFfhqXAPXG
27
- P7mK3+qd5jObjh6l3/rDKrTXNS+P+YO/1frlZ6xPjCA8XgGc4y0rhAjZnVBDV6t1
28
- kmdtEmue1s1OxaMakr78XRZDxEuAeLM5fg8MYnlOFygEcAH6lZkTjXavY7s9MXRB
29
- AAMioxgB6J5QhXQ42OSWIzwHZIbSv3DV9Lf5sde50HIW5f9u5jn29TUGDhSWYKkh
30
- LDvy9dfwMMOdIZi75Q8SBBib84AuwhMHIlUv9FcHhh3dXsDDYkrVrpUAwCsG6yCm
31
- -----END CERTIFICATE-----
32
- date: 2022-09-29 00:00:00.000000000 Z
9
+ cert_chain: []
10
+ date: 2026-10-21 00:00:00.000000000 Z
33
11
  dependencies:
34
12
  - !ruby/object:Gem::Dependency
35
13
  name: rspec-core
@@ -149,7 +127,6 @@ licenses:
149
127
  - MIT
150
128
  metadata:
151
129
  changelog_uri: https://github.com/sj26/rspec_junit_formatter/blob/HEAD/CHANGELOG.md
152
- post_install_message:
153
130
  rdoc_options: []
154
131
  require_paths:
155
132
  - lib
@@ -164,8 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
141
  - !ruby/object:Gem::Version
165
142
  version: 2.0.0
166
143
  requirements: []
167
- rubygems_version: 3.3.7
168
- signing_key:
144
+ rubygems_version: 3.6.9
169
145
  specification_version: 4
170
146
  summary: RSpec JUnit XML formatter
171
147
  test_files: []
checksums.yaml.gz.sig DELETED
@@ -1 +0,0 @@
1
- ��[h��bJ��9��$P�6��-�@V
data.tar.gz.sig DELETED
@@ -1,2 +0,0 @@
1
- kb�u�(5����\���<F�,���uЯ�vx��}-~rBFl���;k�;P�K1t��{<��4�rZ+۱�H��"r��W�żi��q�ws�[����Z��T�E������ D���_
2
- O9�&�Eh�R��:V�,����}����B��
metadata.gz.sig DELETED
Binary file