rspec-tracer 1.2.4 → 2.0.0.pre.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.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +191 -164
  3. data/README.md +439 -429
  4. data/bin/rspec-tracer +15 -0
  5. data/lib/rspec_tracer/cache/Rakefile +43 -0
  6. data/lib/rspec_tracer/cli/cache_clear.rb +98 -0
  7. data/lib/rspec_tracer/cli/cache_info.rb +103 -0
  8. data/lib/rspec_tracer/cli/doctor.rb +275 -0
  9. data/lib/rspec_tracer/cli/explain.rb +148 -0
  10. data/lib/rspec_tracer/cli/report_open.rb +82 -0
  11. data/lib/rspec_tracer/cli.rb +116 -0
  12. data/lib/rspec_tracer/configuration.rb +1100 -3
  13. data/lib/rspec_tracer/engine.rb +1076 -0
  14. data/lib/rspec_tracer/example.rb +24 -113
  15. data/lib/rspec_tracer/filter.rb +35 -0
  16. data/lib/rspec_tracer/line_stub.rb +61 -0
  17. data/lib/rspec_tracer/load_config.rb +2 -2
  18. data/lib/rspec_tracer/logger.rb +15 -0
  19. data/lib/rspec_tracer/rails/README.md +78 -0
  20. data/lib/rspec_tracer/rails/i18n_tracking.rb +137 -0
  21. data/lib/rspec_tracer/rails/notifications.rb +263 -0
  22. data/lib/rspec_tracer/rails/preset.rb +94 -0
  23. data/lib/rspec_tracer/rails/railtie.rb +22 -0
  24. data/lib/rspec_tracer/rails.rb +15 -0
  25. data/lib/rspec_tracer/remote_cache/README.md +140 -0
  26. data/lib/rspec_tracer/remote_cache/Rakefile +35 -11
  27. data/lib/rspec_tracer/remote_cache/archive.rb +137 -0
  28. data/lib/rspec_tracer/remote_cache/backend.rb +73 -0
  29. data/lib/rspec_tracer/remote_cache/git_ancestry.rb +241 -0
  30. data/lib/rspec_tracer/remote_cache/local_fs_backend.rb +439 -0
  31. data/lib/rspec_tracer/remote_cache/redis_backend.rb +554 -0
  32. data/lib/rspec_tracer/remote_cache/s3_backend.rb +712 -0
  33. data/lib/rspec_tracer/remote_cache/user_tasks.rb +397 -0
  34. data/lib/rspec_tracer/remote_cache/validator.rb +40 -62
  35. data/lib/rspec_tracer/remote_cache.rb +22 -0
  36. data/lib/rspec_tracer/reporters/README.md +103 -0
  37. data/lib/rspec_tracer/reporters/base.rb +87 -0
  38. data/lib/rspec_tracer/reporters/coverage_json_reporter.rb +338 -0
  39. data/lib/rspec_tracer/reporters/html/.gitignore +19 -0
  40. data/lib/rspec_tracer/reporters/html/.prettierignore +4 -0
  41. data/lib/rspec_tracer/reporters/html/.prettierrc.json +9 -0
  42. data/lib/rspec_tracer/reporters/html/README.md +80 -0
  43. data/lib/rspec_tracer/reporters/html/dist/assets/index.css +2 -0
  44. data/lib/rspec_tracer/reporters/html/dist/assets/index.js +1 -0
  45. data/lib/rspec_tracer/reporters/html/dist/index.html +24 -0
  46. data/lib/rspec_tracer/reporters/html/eslint.config.js +62 -0
  47. data/lib/rspec_tracer/reporters/html/package-lock.json +4941 -0
  48. data/lib/rspec_tracer/reporters/html/package.json +29 -0
  49. data/lib/rspec_tracer/reporters/html/src/app.jsx +130 -0
  50. data/lib/rspec_tracer/reporters/html/src/components/AllExamples.jsx +86 -0
  51. data/lib/rspec_tracer/reporters/html/src/components/DuplicateExamples.jsx +68 -0
  52. data/lib/rspec_tracer/reporters/html/src/components/ExamplesDependency.jsx +78 -0
  53. data/lib/rspec_tracer/reporters/html/src/components/FilesDependency.jsx +72 -0
  54. data/lib/rspec_tracer/reporters/html/src/components/FlakyExamples.jsx +42 -0
  55. data/lib/rspec_tracer/reporters/html/src/components/ReportTable.jsx +131 -0
  56. data/lib/rspec_tracer/reporters/html/src/components/SearchBar.jsx +19 -0
  57. data/lib/rspec_tracer/reporters/html/src/index.html +23 -0
  58. data/lib/rspec_tracer/reporters/html/src/main.jsx +37 -0
  59. data/lib/rspec_tracer/reporters/html/src/styles.css +434 -0
  60. data/lib/rspec_tracer/reporters/html/vite.config.js +42 -0
  61. data/lib/rspec_tracer/reporters/html_reporter.rb +266 -0
  62. data/lib/rspec_tracer/reporters/json_reporter.rb +88 -0
  63. data/lib/rspec_tracer/reporters/payload_builder.rb +235 -0
  64. data/lib/rspec_tracer/reporters/registry.rb +120 -0
  65. data/lib/rspec_tracer/reporters/terminal_reporter.rb +264 -0
  66. data/lib/rspec_tracer/rspec/README.md +73 -0
  67. data/lib/rspec_tracer/rspec/installation.rb +97 -0
  68. data/lib/rspec_tracer/rspec/metadata.rb +96 -0
  69. data/lib/rspec_tracer/rspec/parallel_tests.rb +459 -0
  70. data/lib/rspec_tracer/rspec/reporter_hook.rb +84 -0
  71. data/lib/rspec_tracer/rspec/runner_hook.rb +178 -0
  72. data/lib/rspec_tracer/source_file.rb +24 -7
  73. data/lib/rspec_tracer/storage/README.md +35 -0
  74. data/lib/rspec_tracer/storage/backend.rb +68 -0
  75. data/lib/rspec_tracer/storage/json_backend.rb +866 -0
  76. data/lib/rspec_tracer/storage/lazy_snapshot.rb +65 -0
  77. data/lib/rspec_tracer/storage/schema.rb +43 -0
  78. data/lib/rspec_tracer/storage/serializer/json.rb +41 -0
  79. data/lib/rspec_tracer/storage/serializer/msgpack.rb +90 -0
  80. data/lib/rspec_tracer/storage/snapshot.rb +127 -0
  81. data/lib/rspec_tracer/storage/sqlite_backend.rb +686 -0
  82. data/lib/rspec_tracer/time_formatter.rb +37 -18
  83. data/lib/rspec_tracer/tracker/README.md +36 -0
  84. data/lib/rspec_tracer/tracker/coverage_adapter.rb +174 -0
  85. data/lib/rspec_tracer/tracker/declared_globs.rb +100 -0
  86. data/lib/rspec_tracer/tracker/dependency_graph.rb +134 -0
  87. data/lib/rspec_tracer/tracker/env_matcher.rb +127 -0
  88. data/lib/rspec_tracer/tracker/env_snapshot.rb +77 -0
  89. data/lib/rspec_tracer/tracker/example_registry.rb +153 -0
  90. data/lib/rspec_tracer/tracker/file_digest.rb +61 -0
  91. data/lib/rspec_tracer/tracker/filter.rb +127 -0
  92. data/lib/rspec_tracer/tracker/input.rb +99 -0
  93. data/lib/rspec_tracer/tracker/io_hooks/file.rb +55 -0
  94. data/lib/rspec_tracer/tracker/io_hooks/io.rb +24 -0
  95. data/lib/rspec_tracer/tracker/io_hooks/json.rb +23 -0
  96. data/lib/rspec_tracer/tracker/io_hooks/kernel.rb +26 -0
  97. data/lib/rspec_tracer/tracker/io_hooks/yaml.rb +38 -0
  98. data/lib/rspec_tracer/tracker/io_hooks.rb +195 -0
  99. data/lib/rspec_tracer/tracker/loaded_files_tracker.rb +295 -0
  100. data/lib/rspec_tracer/tracker/new_file_detector.rb +62 -0
  101. data/lib/rspec_tracer/tracker/whole_suite_invalidators.rb +96 -0
  102. data/lib/rspec_tracer/version.rb +4 -1
  103. data/lib/rspec_tracer.rb +223 -493
  104. metadata +93 -44
  105. data/lib/rspec_tracer/cache.rb +0 -207
  106. data/lib/rspec_tracer/coverage_merger.rb +0 -42
  107. data/lib/rspec_tracer/coverage_reporter.rb +0 -187
  108. data/lib/rspec_tracer/coverage_writer.rb +0 -58
  109. data/lib/rspec_tracer/html_reporter/Rakefile +0 -18
  110. data/lib/rspec_tracer/html_reporter/assets/javascripts/application.js +0 -56
  111. data/lib/rspec_tracer/html_reporter/assets/javascripts/libraries/jquery.js +0 -10881
  112. data/lib/rspec_tracer/html_reporter/assets/javascripts/plugins/datatables.js +0 -15381
  113. data/lib/rspec_tracer/html_reporter/assets/stylesheets/application.css +0 -196
  114. data/lib/rspec_tracer/html_reporter/assets/stylesheets/plugins/datatables.css +0 -459
  115. data/lib/rspec_tracer/html_reporter/assets/stylesheets/plugins/jquery-ui.css +0 -436
  116. data/lib/rspec_tracer/html_reporter/assets/stylesheets/print.css +0 -92
  117. data/lib/rspec_tracer/html_reporter/assets/stylesheets/reset.css +0 -265
  118. data/lib/rspec_tracer/html_reporter/public/application.css +0 -5
  119. data/lib/rspec_tracer/html_reporter/public/application.js +0 -6
  120. data/lib/rspec_tracer/html_reporter/public/datatables/images/sort_asc.png +0 -0
  121. data/lib/rspec_tracer/html_reporter/public/datatables/images/sort_asc_disabled.png +0 -0
  122. data/lib/rspec_tracer/html_reporter/public/datatables/images/sort_both.png +0 -0
  123. data/lib/rspec_tracer/html_reporter/public/datatables/images/sort_desc.png +0 -0
  124. data/lib/rspec_tracer/html_reporter/public/datatables/images/sort_desc_disabled.png +0 -0
  125. data/lib/rspec_tracer/html_reporter/public/favicon.png +0 -0
  126. data/lib/rspec_tracer/html_reporter/public/loading.gif +0 -0
  127. data/lib/rspec_tracer/html_reporter/reporter.rb +0 -242
  128. data/lib/rspec_tracer/html_reporter/views/duplicate_examples.erb +0 -34
  129. data/lib/rspec_tracer/html_reporter/views/examples.erb +0 -58
  130. data/lib/rspec_tracer/html_reporter/views/examples_dependency.erb +0 -36
  131. data/lib/rspec_tracer/html_reporter/views/files_dependency.erb +0 -36
  132. data/lib/rspec_tracer/html_reporter/views/flaky_examples.erb +0 -38
  133. data/lib/rspec_tracer/html_reporter/views/layout.erb +0 -38
  134. data/lib/rspec_tracer/remote_cache/aws.rb +0 -176
  135. data/lib/rspec_tracer/remote_cache/cache.rb +0 -77
  136. data/lib/rspec_tracer/remote_cache/repo.rb +0 -210
  137. data/lib/rspec_tracer/report_generator.rb +0 -158
  138. data/lib/rspec_tracer/report_merger.rb +0 -68
  139. data/lib/rspec_tracer/report_writer.rb +0 -141
  140. data/lib/rspec_tracer/reporter.rb +0 -204
  141. data/lib/rspec_tracer/rspec_reporter.rb +0 -41
  142. data/lib/rspec_tracer/rspec_runner.rb +0 -56
  143. data/lib/rspec_tracer/ruby_coverage.rb +0 -9
  144. data/lib/rspec_tracer/runner.rb +0 -278
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5a5c7bccaf770c4b630f3aafbe2965e7a88eebf912d4e5f331eb6001613e0559
4
- data.tar.gz: cd2c8bb4ea28fa5c70807e8ca7e9249e16a7313f9e17662e3b76d20cc26a91ab
3
+ metadata.gz: 04d2e3c76b8351f5f71f93cd722af23975f80da067f19970471455b3b2ed16aa
4
+ data.tar.gz: 0ab86f0d744275db42ed0d355d5781d25a6f65ed49a76fcd70d3df1acd7e01b4
5
5
  SHA512:
6
- metadata.gz: 2a5889f5a017183e40e63b56c10b6abf2309dff7b18ca941c2f36552e947b508ca3ac144290143a44b2bf78c7f76569eba96d1d580f69eb9a2d2a138e3c004ba
7
- data.tar.gz: 79ff93be56d9f9bee3c397b0d78ef0cb4114b5c746879d9afcbf6372d2eb55a8950b75f772372c78aaea3852a12a0750a1098758cf343c41c9caa86b485ac054
6
+ metadata.gz: e802e4c67a41d1d1ebd16df2fd4ee874f0993678097563f38b5bd3e443024662040547df140dd45196c0e81e7d510ecfe79dbf4a3e01ab1a4685f380f9ec829f
7
+ data.tar.gz: 72435a0282503ff2c90b6b80168fb810bd48412bc162043b4d70780b35f74478fc5236c43710bb9e948657b2c6c17734a59406fc617cb712eaba7e1a3c2e4dfb
data/CHANGELOG.md CHANGED
@@ -1,181 +1,208 @@
1
- ## [1.2.4] - 2026-05-17
1
+ ## [2.0.0.pre.1] - 2026-05-06
2
2
 
3
- ### Fixed
4
-
5
- - **`example_id` was unstable across runs — a long-standing bug since
6
- v1.0.0.** `RSpecTracer::Example.from` built the MD5 identity hash
7
- over a payload that included `example_group.name` (RSpec's
8
- generated class name, which carries a load-order-dependent `_2` /
9
- `_3` suffix when two spec files share a `describe` name) and the
10
- example's `line_number`. The same example got a different id
11
- depending on rspec's file load order — silently thrashing the
12
- cache and breaking the always-re-run guarantees for failed,
13
- pending, and flaky examples. A no-op blank-line edit above the
14
- example flipped the id with the same effect.
15
-
16
- The digest now uses a stable subset: the describe block's
17
- *description* string (the user-supplied text, not RSpec's
18
- generated class name), the example's `description`,
19
- `full_description`, `shared_group` inclusion locations with the
20
- trailing `:LINE` stripped, and `file_name`. `line_number` /
21
- `rerun_file_name` / `rerun_line_number` still ride along in the
22
- returned Hash for the HTML and JSON reporters' location columns,
23
- but no longer enter the digest. Contract: **rename = new identity;
24
- restructure = same identity.**
25
-
26
- Unnamed examples (`it { }`, `specify { }`, `example { }`) needed
27
- an extra step. RSpec's pre-run `description` for an unnamed
28
- example is the line-bearing `"example at <path>:<line>"`
29
- fallback, which would have re-leaked the line number straight
30
- into the digest. The digest substitutes a line-independent
31
- positional discriminator: the example's ordinal among the
32
- *unnamed* examples of its group. Stability is preserved across
33
- blank-line edits and across adding or renaming *named* siblings;
34
- reordering the unnamed examples re-keys them (the documented
35
- trade-off — give the example an explicit description for a fully
36
- reorder-stable id).
37
-
38
- **Upgrade note**: the cache file format is unchanged, so a v1.2.3
39
- cache loads cleanly through v1.2.4 code. But every cached
40
- `example_id` was computed against the old payload and the new
41
- lookups will not match them, so the first run after upgrade
42
- treats every example as `:no_cache` and re-runs the full suite.
43
- Warm caches resume from the second run onward.
44
-
45
- Surfaced by 2.0.0.pre.1 field testing against third-party Rails
46
- apps. Fixed upstream in
47
- [#209](https://github.com/avmnu-sng/rspec-tracer/pull/209) and
48
- [#211](https://github.com/avmnu-sng/rspec-tracer/pull/211).
49
-
50
- - **`RSpecTracer.start` crashed when the user pre-started
51
- `::Coverage`.** Users opting into branch coverage typically call
52
- `Coverage.start(lines: true, branches: true)` before loading
53
- rspec-tracer. The tracer's `setup_coverage` then called bare
54
- `::Coverage.start` with no `running?` guard, raising
55
- `RuntimeError: coverage measurement is already setup` and taking
56
- the tracer down at boot.
57
-
58
- Add a `Coverage.running?` predicate guard before the start call,
59
- plus a defensive `RuntimeError` rescue with a `logger.warn` for
60
- the case where the predicate returns false but `start` still
61
- raises. Graceful degradation: coverage measurement is skipped
62
- with a visible warn, the rest of the tracer pipeline continues.
63
-
64
- Partial port of upstream
65
- [#207](https://github.com/avmnu-sng/rspec-tracer/pull/207); the
66
- `coverage_modes` config DSL half is 2.0-only.
67
-
68
- - **`remote_cache` success paths were silent at default log level.**
69
- `RemoteCache::Cache#download` and `#upload` returned without
70
- emitting anything after the underlying AWS calls succeeded, so a
71
- successful `rake rspec_tracer:remote_cache:download` produced
72
- zero output. Users couldn't tell from CI logs whether the cache
73
- was actually restored or whether the run was cold.
74
-
75
- Emit a single `RSpecTracer.logger.info` line on each operation's
76
- success path: `"rspec-tracer remote_cache: restored cache from
77
- <sha>"` on download, `"rspec-tracer remote_cache: uploaded cache
78
- to <ref>"` on upload.
79
-
80
- Partial port of upstream
81
- [#201](https://github.com/avmnu-sng/rspec-tracer/pull/201); the
82
- cross-branch-fallback qualifier is specific to 2.0's multi-tier
83
- cache model and not applicable here.
84
-
85
- ### Changed
3
+ The first pre-release of the 2.0 line. Architecture rewrite around
4
+ the input-taxonomy mental model documented in
5
+ [`ARCHITECTURE.md`](ARCHITECTURE.md): every test is a pure function
6
+ of its inputs; tracking is input identification; cache invalidation
7
+ is input-digest mismatch.
86
8
 
87
- - **`rspec-tracer.gemspec` now declares `rubygems_mfa_required`** so
88
- RubyGems enforces MFA on every publish. Packaging metadata only;
89
- no behaviour change for users of the gem. Mirrors upstream
90
- [#214](https://github.com/avmnu-sng/rspec-tracer/pull/214).
9
+ The 1.x cache is not readable by 2.0 — first run on the new version
10
+ is cold, then warm caches resume. Existing CI integration (`rake
11
+ rspec_tracer:remote_cache:download` / `:upload`, the env vars,
12
+ the `rspec_tracer_cache/` / `rspec_tracer_coverage/` /
13
+ `rspec_tracer_report/` directory contracts) is preserved bit-for-bit.
91
14
 
92
- - **`.github/workflows/release.yml` tag-trigger pattern tightened
93
- to the strict `'v[0-9]+.[0-9]+.[0-9]+'` form** (1.x is
94
- final-release only). The previous loose `'v*.*.*'` form would
95
- have matched 4-segment shapes like `v2.0.0.rc.1` accidentally
96
- because `*` greedy-matches dots; the strict per-segment digit
97
- class rejects any non-digit. Documentation block above the
98
- pattern explains the GHA filter-pattern flavor for future
99
- maintainers. Workflow-only; no user-visible change.
15
+ ### Added
100
16
 
101
- ## [1.2.3] - 2026-05-06
17
+ - **Pluggable storage backends.** `storage_backend :json` (default,
18
+ preserves 1.x JSON layout) or `storage_backend :sqlite` (single-
19
+ file SQLite database; MRI only — JRuby falls back to `:json` with
20
+ a one-time warn). The 10-file per-run JSON layout (`last_run.json`
21
+ + `<run_id>/{all_examples,duplicate_examples,interrupted_examples,
22
+ flaky_examples,failed_examples,pending_examples,skipped_examples,
23
+ all_files,dependency,examples_coverage}.json`) is unchanged.
24
+ - **Pluggable remote-cache backends.** `remote_cache_backend :s3`
25
+ (preserves the 1.x S3 layout including `awslocal` / LocalStack
26
+ support), `:local_fs` (filesystem-backed; no S3 needed), or
27
+ `:redis` (with optional per-key TTL + `<prefix>:pr_branches`
28
+ sidecar SADD on PR-tier uploads for ops dashboards).
29
+ - **Per-example `tracks:` DSL.** Annotate any describe / context /
30
+ example with `tracks: { files: 'app/policies/**/*.rb', env:
31
+ 'ROLE_CONFIG' }` to declare extra inputs the tracker can't auto-
32
+ observe — config files baked at boot, env-var branches, and
33
+ similar. `:files` accepts a string glob or array; `:env` accepts a
34
+ literal name, array, or single-wildcard pattern (`'RAILS_*'`,
35
+ `'*_TOKEN'`, `'*'`). Cascade unions parent + child without
36
+ clobbering.
37
+ - **`track_env(*names)` config-level DSL** for env vars every test
38
+ depends on (`AUTH_TOKEN`, `DATABASE_URL`, `RAILS_ENV`). Same
39
+ wildcard syntax as the per-example `tracks: { env: ... }`.
40
+ Persists as `env_snapshot.json` (concrete keys only, no pattern
41
+ leakage).
42
+ - **`track_files(*globs)` config-level DSL** for files every test
43
+ depends on (`Gemfile.lock`, schema, locale catalogs).
44
+ - **Rails preset** via `track_rails_defaults` — auto-attaches the
45
+ common Rails-side declared globs (views, locales, fixtures,
46
+ factories, helpers, config). `track_rails_defaults except:
47
+ [:views, :schema]` opts specific globs out so framework-event
48
+ subscribers (`render_template.action_view` for views; the opt-in
49
+ `sql.active_record` observer enabled by
50
+ `track_ar_schema_notifications` for `db/schema.rb`) attribute
51
+ them per-example instead.
52
+ - **Auto-detection of Rails** at start time; the engine attaches
53
+ `ActionView` template + `ActiveRecord` schema (when opted in)
54
+ notification observers automatically when `::Rails::VERSION` is
55
+ defined.
56
+ - **`bin/rspec-tracer` CLI** with five sub-commands:
57
+ `doctor` (config + environment diagnosis, schema-version + remote-
58
+ cache reachability + AR-schema-narrow checks), `cache:info`
59
+ (size, last run, invalidation stats), `cache:clear` (rm cache
60
+ dirs), `report:open` (open the HTML report in the default
61
+ browser), `explain <example_id>` (show why a given example is
62
+ scheduled to run or skip). The CLI is opt-in for local-dev
63
+ convenience; the `rake rspec_tracer:remote_cache:*` tasks remain
64
+ first-class for CI integration.
65
+ - **Boot-time warns** for two common user-trust traps:
66
+ - SimpleCov loaded but not started before `RSpecTracer.start`
67
+ (load-order is part of the documented contract; the warn
68
+ surfaces it instead of silently bolting onto a Coverage already
69
+ in flight).
70
+ - `track_ar_schema_notifications` enabled with
71
+ `use_transactional_fixtures` defaulting to true (per-example
72
+ BEGIN/COMMIT fires `sql.active_record` and attributes
73
+ `db/schema.rb` to every AR-touching example; the warn points
74
+ at the README "Narrow AR-schema attribution" guidance).
75
+ - **`.rspec-tracer` DSL typo `did you mean?` suggestions** at config
76
+ load — typos like `track_filez` raise `InvalidUsageError` with a
77
+ pointer at `track_files`.
78
+ - **Rails 8.0 CI-gated support** (Ruby 3.2+ required; Rails 8.0
79
+ dropped Ruby 3.1 support upstream). `jruby-9.4 × Rails 8.0` is
80
+ unsupported (no `activerecord-jdbcsqlite3-adapter ~> 80.0`
81
+ upstream).
82
+ - **Schema-version field** in `last_run.json` for explicit
83
+ cross-version cache validation. Cache-shape changes bump the
84
+ field; mismatched caches refuse-to-load with an info-level "cold
85
+ run" log line.
86
+ - **`docs/CI_RECIPES.md`** translating the
87
+ [`.github/workflows/example-tracer-cache.yml`](.github/workflows/example-tracer-cache.yml)
88
+ GitHub Actions cache pattern to CircleCI / GitLab CI / Buildkite
89
+ / Heroku CI. The 4-component cache key (`runner.os` +
90
+ `.ruby-version` + `lib/rspec_tracer/version.rb` + Gemfile-hash)
91
+ translates 1:1 across providers; only the YAML envelope is
92
+ GHA-specific.
93
+ - **Coexistence smokes** for `rspec-retry`, `rspec-rerun`, and
94
+ `knapsack`. All three compose with rspec-tracer's `Module#prepend`
95
+ chain on `RSpec::Core::Runner` / `Reporter` without override.
96
+ - **`bin/rspec-tracer doctor` reachability checks** for the
97
+ configured remote-cache backend (S3 / Local-FS / Redis) — surfaces
98
+ misconfigured credentials / missing buckets / unreachable Redis
99
+ hosts at first invocation instead of mid-CI-run.
100
+ - **HTML reporter** (committed build output, no `assets:precompile`
101
+ step on user installs) and **JSON reporter** (machine-readable,
102
+ for CI dashboards) alongside the existing terminal output. The
103
+ terminal line now includes a `by reason:` breakdown
104
+ (`12 Files changed · 3 Whole-suite invalidator changed · ...`)
105
+ and a cache size + delta suffix (`14.4 MiB; +6.7 KiB vs prev
106
+ run`).
102
107
 
103
- ### Fixed
108
+ ### Changed
104
109
 
105
- - **Parallel-tests purge race when a sibling worker is still mid-flush**
106
- the elected worker trusted only `parallel_tests`'s pid-file barrier
107
- (`ParallelTests.wait_for_other_processes_to_finish`), which under
108
- specific scheduling/I/O timing on GHA Linux x86_64 can return while a
109
- sibling's `parallel_tests_N/` dir hasn't fully flushed. The elected
110
- then merged + purged, racing the in-progress sibling. Symptoms:
111
- intermittent leftover `parallel_tests_N/` dir post-purge AND/OR
112
- silently dropped peer caches in the merge.
113
-
114
- Backport of upstream PR
115
- [#168](https://github.com/avmnu-sng/rspec-tracer/pull/168). Adds a
116
- filesystem barrier layered on top of the pid-file wait. Each worker
117
- writes a `.rspec_tracer_boot` marker at `RSpecTracer.start` time and
118
- a `.rspec_tracer_done` marker as the first step of its at_exit tasks;
119
- the elected worker waits for every booted peer's `.done` to
120
- materialize before proceeding to merge + purge. Two independent
121
- signals (pid file + filesystem) must agree before the elected worker
122
- declares the peer set stable. Bounded at 5 s with a graceful warn for
123
- crashed peers their dirs are purged regardless of completion state,
124
- and the merge accepts whatever's on disk.
125
-
126
- ## [1.2.2] - 2026-05-04
110
+ - **Ruby 3.1** is the floor (1.x supported Ruby 2.5+). 3.2, 3.3,
111
+ 3.4, 4.0 + JRuby 9.4 are CI-gated. Rails 7.0 / 7.1 / 7.2 / 8.0 +
112
+ RSpec 3.12 / 3.13 are CI-gated.
113
+ - **SimpleCov branch coverage now works alongside rspec-tracer.**
114
+ The 1.x caveat ("SimpleCov would not report branch coverage
115
+ results even when enabled") is **no longer applicable** — the
116
+ coverage-stack rewrite decoupled rspec-tracer's line-only
117
+ emission from SimpleCov's branch-tracking. Users who turned
118
+ `enable_coverage :branch` off when adopting rspec-tracer 1.x can
119
+ re-enable in 2.0.
120
+ - **Cache schema bump.** First run on 2.0 is cold; subsequent runs
121
+ return to warm.
122
+ - **Coverage adapter** consolidated: a single
123
+ `Reporters::CoverageJsonReporter` owns `coverage.json` emission
124
+ (replacing the 1.x `CoverageReporter` + `CoverageWriter` pair).
125
+ Output shape preserved.
126
+ - **Parallel-tests reporter behavior:** terminal / JSON / HTML
127
+ reports now emit ONCE at the merged top-level location after
128
+ `merge_snapshot!` runs, instead of per-worker (where
129
+ `purge_worker_dirs!` then removed them and left users with no
130
+ usable output). Per-worker emission was a pre-2.0 behavior bug.
127
131
 
128
132
  ### Fixed
129
133
 
134
+ - **ERB template tracking via `render_template.action_view`** (closes
135
+ the issue behind upstream
136
+ [#66](https://github.com/avmnu-sng/rspec-tracer/issues/66)). The
137
+ Rails subscriber attributes rendered ERB partials to the example
138
+ that triggered the render.
139
+ - **Phantom `metadata[:file_path]` graceful skip** (closes the issue
140
+ behind upstream
141
+ [#72](https://github.com/avmnu-sng/rspec-tracer/issues/72)). Specs
142
+ whose `metadata[:file_path]` doesn't resolve to a readable file
143
+ (gem-generated examples, deleted-between-runs files) now log
144
+ debug + skip dependency registration instead of raising.
130
145
  - **Default filter list now excludes rspec-tracer's own output
131
- directories** (`rspec_tracer_cache/`, `rspec_tracer_coverage/`,
132
- `rspec_tracer_report/`, and the `rspec_tracer.lock` file). Prior
133
- versions did not exclude these paths, so any spec that read a tracer
134
- cache file (typical for outer integration specs that assert on cache
135
- state after a fixture subprocess run) had those paths attributed as
136
- dependencies. The user-visible symptom was reverse-dependency reports
137
- showing tracer-self paths as deps of unrelated specs, plus
138
- spurious files-changed re-runs whenever the tracer rewrote its own
139
- cache. Both `add_filter` and `add_coverage_filter` defaults updated.
140
-
141
- - **Carry-forward filter contract** — newly added filters now apply
142
- uniformly to both fresh attribution AND prior-snapshot carry-forward.
143
- Previously, `Cache#load_all_files_cache` and `load_dependency_cache`
144
- read previous-run state without re-applying the current filter list.
145
- A user adding a new filter mid-development saw the filter take
146
- effect only for fresh attributions on cold runs; previously-cached
147
- paths matching the new filter persisted in `all_files` and
148
- `dependency` until the next cold run. Filter additions now take
146
+ directories** `rspec_tracer_cache/`, `rspec_tracer_coverage/`,
147
+ `rspec_tracer_report/`, `rspec_tracer.lock`. Previously, tests
148
+ that read the tracer's own cache files (e.g. integration specs
149
+ asserting on cache state after a fixture subprocess run) got
150
+ those paths attributed as deps. The tracer's output is
151
+ regenerated every run by design and should never invalidate a
152
+ test. Both `add_filter` (dep graph) and `add_coverage_filter`
153
+ (coverage report) lists were updated.
154
+ - **`add_filter` / `add_coverage_filter` now apply uniformly to
155
+ both fresh attributions AND prior-snapshot carry-forward.**
156
+ Previously, `Engine#seed_all_files_from_previous` and
157
+ `Engine#seed_graph_from_previous` seeded paths from the previous
158
+ run's snapshot WITHOUT re-applying the current filter list — so
159
+ a filter added between runs would NOT exclude already-cached
160
+ paths until a cold run wiped them. Filter additions now take
149
161
  effect on the very next warm run.
150
162
 
151
- ## [1.2.1] - 2026-05-01
163
+ ### Deprecated
152
164
 
153
- ### Fixed
165
+ The 1.x configuration surface keeps working; each deprecated entry
166
+ fires one `logger.warn` at first use pointing at the replacement.
167
+ The deprecated values still resolve semantically. All four are slated
168
+ for removal in 3.0.
169
+
170
+ - **`reports_s3_path(uri)`** → use **`remote_cache_uri(uri)`**.
171
+ - **`use_local_aws(bool)`** → use **`remote_cache_backend :s3,
172
+ local: true`**.
173
+ - **`RSPEC_TRACER_REPORTS_S3_PATH`** → use
174
+ **`RSPEC_TRACER_REMOTE_CACHE_URI`**.
175
+ - **`RSPEC_TRACER_USE_LOCAL_AWS`** → fold into
176
+ `remote_cache_backend` params.
177
+
178
+ ### Removed
154
179
 
155
- - **Parallel-tests merge silently dropped peer caches and left worker
156
- directories behind** when the spawned-worker count exceeded
157
- `ENV['PARALLEL_TEST_GROUPS']`. The merge + purge call-sites in
158
- `lib/rspec_tracer.rb` (`merge_parallel_tests_reports`,
159
- `merge_parallel_tests_coverage_reports`,
160
- `purge_parallel_tests_reports`) iterated `1..ENV['PARALLEL_TEST_GROUPS']`
161
- to construct per-worker directory names. But parallel_tests sets
162
- `PARALLEL_TEST_GROUPS = num_processes.to_s` for each child, where
163
- `num_processes` is the user-requested process count
164
- (`Parallel.processor_count` by default) — not the actual worker
165
- count. When `num_processes < spawned_worker_count` (e.g. when the
166
- spec-count partition produces more non-empty groups than
167
- `num_processes`, or shared-runner CPU detection drifts mid-run),
168
- peer caches with `TEST_ENV_NUMBER` above the env bound were silently
169
- dropped from the merge (warm-run skip decisions get made against
170
- an under-sampled merged manifest) and left behind by the purge
171
- (visible as straggler `parallel_tests_<N>/` directories under
172
- `rspec_tracer_cache/`). The same gem behaviour was documented on
173
- v1.1.1's `last_process?` fix
174
- ([PR #101](https://github.com/avmnu-sng/rspec-tracer/pull/101)) but
175
- the iteration call-sites kept the buggy bound. Each method now globs
176
- the actual `parallel_tests_*` subdirectories under its base path,
177
- making the merge + purge robust to whatever count parallel_tests
178
- spawned. No cache format change.
180
+ - **Cucumber feature-file integration suite.** Contributor-facing
181
+ only; users see no change. Replaced by RSpec subprocess
182
+ integration specs under `spec/integration/`. The `bundle exec
183
+ rake` legacy entry point is removed; `task` (Taskfile) is the
184
+ canonical dev loop.
185
+ - **Ruby ≤ 3.0 and Rails ≤ 6.x support** (already dropped in 1.1.0;
186
+ re-stated here for clarity at the major boundary).
187
+ - **Windows support** (no CI gate; never actively maintained).
188
+
189
+ ### Deferred to 2.1
190
+
191
+ - **Per-example dependency attribution under Rails
192
+ `config.eager_load = true`.** When `eager_load = true` (Rails
193
+ default for CI tests to mirror prod), all `app/` files load at
194
+ boot and land in the boot-set; the whole-suite invalidator fires
195
+ on any `app/` edit, re-running every example. This is SAFE (never
196
+ misses a dep) but coarser than per-example attribution. The 2.1
197
+ enhancement will install a class-attribution mechanism (working
198
+ name: `track_class_attribution`) using `TracePoint(:class)` at
199
+ boot + `TracePoint(:call)` per example to trim the invalidator
200
+ scope to only examples that touched the changed file's class /
201
+ method surface. Opt-in by default; designed from scratch on the
202
+ user-shape problem (not a resurrection of any 1.x DSL name).
203
+ Today's escape hatches: set `config.eager_load = false` in test
204
+ env for full per-example precision, or use `tracks: { files:
205
+ '...' }` for per-example narrowing on specific groups.
179
206
 
180
207
  ## [1.2.0] - 2026-04-24
181
208