Modernize wisper for the current Ruby ecosystem - #219
Open
dior001 wants to merge 2 commits into
Open
Conversation
added 2 commits
July 26, 2026 04:13
.necro/summary.json and NECRO_MODERNIZATION_REPORT.md are NecroRuby's internal notes, not part of the gem. They were committed by mistake -- the modernization agent writes them into the checkout root and `git add -A` staged them. They have no business in this diff. Sorry for the noise.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
NecroRuby has revived
wisperNecroRuby is a bot that brings quality open-source Ruby libraries
up-to-date with the modern Ruby ecosystem — upgrading dependencies,
restoring test coverage, tightening security, and improving documentation
for gems whose last release is over a year old.
NecroRuby is a fully autonomous process and is capable of mistakes. If you
disagree with any of these changes, just say so on this PR (or close it) and
NecroRuby will move on. If you have questions, ask here — NecroRuby monitors
this PR and will respond.
Modernized and tested on Ruby 4.0.6, the latest Ruby release.
Wisper Modernization Report
This PR modernizes Wisper for the current Ruby ecosystem, targeting Ruby 4.0.6
(and 3.2 - 3.4) while keeping the gem's public API and behavior unchanged. All 111
tests pass, with 100% line and branch coverage, and the codebase is fully
RuboCop-clean.
Summary
required_ruby_version>= 2.7>= 3.2coveralls(broken install)simplecov, enforced at 100%bundler-audit, zero advisories1. Dependencies
coveralls. It is unmaintained (last released 2020) and itsdependency chain (old
faraday,thor,tins,term-ansicolor) no longerresolves cleanly against a modern Bundler/RubyGems, which meant
bundle installfailed outright on Ruby 4.0.6 before this PR. Replaced with
simplecov,which needs no service/API key, runs fully offline, and is actively maintained.
spec/spec_helper.rbnow callsSimpleCov.startwithenable_coverage :branchand
minimum_coverage line: 100, branch: 100, so the suite itself fails ifcoverage regresses.
rubocop+rubocop-performance+rubocop-rspec(dev group) forstatic analysis, with a repo-specific
.rubocop.yml.bundler-audit(dev group) for dependency vulnerability scanning,wired into
Rakefile(rake bundle:audit:check) and a newauditCI job.flaydependency. It was listed but unused anywhere in theRakefile or docs; removing it keeps the dev dependency set lean, consistent
with the project's own "Wisper is a micro library and will remain lean"
philosophy (CONTRIBUTING.md).
pryandyard(both actively maintained) in the:extrasgroup.remains, empty; only stdlib (
set,singleton,forwardable) is used.All of the above are pinned to currently-installed, current major versions in
Gemfile.lock(not committed, per this repo's existing.gitignore— same asbefore).
2. Compatibility fixes for Ruby 4.0.6 (and 3.2+)
.ruby-versionadded, set to4.0.6. It was previously listed in.gitignore(unusual for a repo that wants a declared target); the ignorerule was removed so the file is actually tracked.
required_ruby_versionraised to>= 3.2. 2.7-3.1 are long past theirupstream EOL; 3.2 is the oldest version in active/security maintenance today
and the oldest version this PR's CI matrix (3.2, 3.3, 3.4, 4.0) verifies.
JRuby was dropped from the matrix — there's no current evidence it tracks
Ruby 4.0 language/semantic changes, and this environment has no JRuby to
verify it against; re-adding it is a reasonable follow-up if someone can
confirm compatibility.
Hash#inspectformat change (Ruby 3.4+). Ruby 3.4 changedHash#inspectto render symbol keys as{x: :y}instead of{:x=>:y}.spec/lib/wisper/broadcasters/logger_broadcaster_spec.rbhad fourhardcoded
{:x=>:y}-style expectations that broke on Ruby 4.0.6 as aresult (
LoggerBroadcaster#kwargs_infosimply callskwargs.inspect, sothe library code was never wrong — only the test literals were
version-specific). Fixed by interpolating
kwargs.inspectinstead ofhardcoding the expected string, so the spec is correct for any Ruby.
RUBY_VERSION < '3.0'branches removed fromsend_broadcaster_spec.rbandlogger_broadcaster_spec.rb. These datedfrom the Ruby 2.7 -> 3.0 keyword-argument separation change and are
unreachable now that the floor is 3.2.
Style/EnvHomecop suggestsDir.homeoverENV['HOME'], butDir.homeraises if it can't resolve a home directory (e.g.
HOME/USERbothunset, as on some minimal CI/container images) — that's exactly the bug
fixed in Wisper 2.0.1 ("fix: safely get signing key in gemspec when HOME
is not set"). Applying the cop's suggestion blindly would have
reintroduced that bug. Kept
ENV.fetch('HOME', nil), which degrades to anempty string, with the cop locally disabled and a comment explaining why.
Verified with
env -u HOME -u USER gem build wisper.gemspec(succeedsbefore and after).
uses
set,singleton, andforwardable, all still present andunchanged in 4.0.6.
frozen_string_literal: trueadded to everylib/andspec/file.Audited every string mutation site (
Prefix#initialize'sreplace) toconfirm it mutates
self(an instance under construction), never a frozenliteral, so this is safe.
def foo(*, **, &); bar(*, **, &); end) applied throughout by RuboCop'sStyle/ArgumentsForwardingautocorrect, used only where arguments werepure pass-through (never where the code inspected
args/kwargsitself). Verified semantically equivalent and re-ran the full suite after
each batch of changes.
3. Test coverage
coverallscould not even be installed on Ruby 4.0.6.branch coverage (32/32), enforced by
SimpleCov.minimum_coverage.LoggerBroadcaster#namebranches onobject.class == Class(nowobject.instance_of?(Class)) to format class-listeners (e.g. when alistener is subscribed as a class rather than an instance, per the
README's "the listener may need to be a class instead of an object")
differently from instance-listeners. No existing spec exercised a real
Classas listener/publisher, so that branch was silently untested. Addedlogger_broadcaster_spec.rb's "when the listener is a class rather thanan instance" example, using a real named class rather than a stubbed
double (a double's
.classisRSpec::Mocks::Double, notClass, so itcan't exercise this branch).
exception occurs" test in
temporary_global_listeners_spec.rb: it usedto define a
MyErrorconstant inline and silently rescue it, which meanta bug causing the wrong exception to propagate would have failed
silently. It now asserts the exception explicitly propagates via
expect { ... }.to raise_error(...).4. Documentation
@param,@return,@example, etc.) toevery public class and module in
lib/, including previously-undocumentedones:
Wisper::Configuration,Wisper::Configuration::Broadcasters,Wisper::GlobalListeners,Wisper::TemporaryListeners,Wisper::Registration,Wisper::BlockRegistration,Wisper::ObjectRegistration,Wisper::Broadcasters::SendBroadcaster,Wisper::Broadcasters::LoggerBroadcaster, and the top-levelWispermodule/class methods. This also satisfies RuboCop's
Style/Documentationcop, so it's enforced going forward.
README.md: dropped the dead Coveralls badge (service no longer used),documented the Ruby 3.2+ requirement, and added "Linting" plus
bundler-audit instructions under "Security".
CHANGELOG.md: added a "HEAD (unreleased)" entry per this repo's ownCONTRIBUTING.md guidance.
5. Lint
.rubocop.yml(RuboCop + rubocop-performance + rubocop-rspec,TargetRubyVersion: 3.2,NewCops: enable). Ranrubocop -Aand thenhand-fixed everything that couldn't be safely auto-corrected.
Metrics/*cops are disabled: Wisper is intentionally a small,single-purpose library (per CONTRIBUTING.md) where short classes/methods
are the point, not something to be flagged.
in
.rubocop.yml(e.g.listener_1/listener_2naming, empty blocksthat intentionally test chainability, the mixed
key:/:key =>hashsyntax the specs use on purpose to exercise both call styles).
auto-correct: moved
Publisher.includedaboveprivate(aprivatemodifier has no effect on
self.foomethods, so its old position wasmisleading —
Lint/IneffectiveAccessModifier); replacedmethods.keys.detect(&list.method(:is_a?))with an explicit block inValueObjects::Events(Performance/MethodObjectAsBlock— method-objectblock-passing allocates an extra
Methodobject per call); split anover-long interpolated log string in
LoggerBroadcasterinto a namedlog_messageprivate method.rake rubocop/rake rubocop:autocorrect(_all)tasks added; alintCI job runs
bundle exec rubocopon every push/PR.6. Security
bundle exec bundler-audit check --updateagainst the full dependencytree (1219 advisories in
ruby-advisory-dbas of this PR):no vulnerabilities found.
gem.metadata['rubygems_mfa_required'] = 'true'to the gemspec(RuboCop's
Gemspec/RequireMFA), so futuregem pushto RubyGems.orgrequires the publishing account to have MFA enabled.
coveralls, which pinned old, less-maintained transitivedependencies (
faraday< 1,thor< 1,tins) that were themselvessources of latent supply-chain risk, even though no specific CVE was the
trigger — that dependency chain simply had no reason to exist anymore.
bundler-auditCI job (audit) so future dependency bumps arechecked automatically, not just at release time.
Design decisions worth flagging for review
compatibility with Ruby 4.0-era syntax/semantics (e.g. anonymous
argument forwarding) is unverified in this environment (no JRuby
available to test against), and the original task instructions require
the suite to pass on Ruby 4.0.6 specifically. If JRuby support is a
priority, it should be re-added and verified separately.
required_ruby_versionset to>= 3.2, not>= 4.0. The code has noRuby-4.0-only syntax; 3.2/3.3/3.4 are still reasonable, supportable
floors, and narrowing further would drop real users for no functional
benefit. The CI matrix verifies all of 3.2, 3.3, 3.4, and 4.0.
broadcast/subscribesemantics, or the
VERSIONconstant — this PR is purelyinfrastructure/compatibility/quality, not a behavior change.
🤖 Opened automatically by NecroRuby, an UpWoof.ai service.