Skip to content

Make ruby-coverage optional until capture starts#43

Closed
samuel-williams-shopify wants to merge 1 commit into
mainfrom
gaia-autopr-lazy-ruby-coverage
Closed

Make ruby-coverage optional until capture starts#43
samuel-williams-shopify wants to merge 1 commit into
mainfrom
gaia-autopr-lazy-ruby-coverage

Conversation

@samuel-williams-shopify

Copy link
Copy Markdown
Contributor

TL;DR

Make ruby-coverage optional until coverage capture is actually started, so consumers can load covered/sus without installing or building the native ruby-coverage extension.

Context

This came up while fixing socketry/io-event CI. io-event loads covered/sus from its Sus configuration, but normal test jobs do not set COVERAGE. Even though Covered::Sus already avoids loading Covered::Config unless COVERAGE is set, covered still declared ruby-coverage as a runtime dependency and Covered::Policy eagerly required covered/capture, which required ruby/coverage.

That means applications can pay the native dependency install/build cost even when they are not recording coverage. On platforms where ruby-coverage is not usable, that fails before tests get to run.

Changes

  • Move ruby-coverage from a runtime dependency to a development dependency.
  • Defer covered/capture loading until Covered::Policy#capture is used.
  • Keep an explicit ruby/coverage require in Covered::Capture, but convert missing dependency failures into a targeted LoadError explaining what gem to add when recording coverage.
  • Add a Covered::Sus regression test that runs in a child Ruby process with a trap ruby/coverage.rb earlier in $LOAD_PATH; requiring covered/sus with COVERAGE unset must not trigger that trap.

Tophatting

PATH=/Users/samuel/.local/state/tec/profiles/base/current/global/bin:$PATH /Users/samuel/.local/state/tec/profiles/base/current/global/bin/bundle exec bake test
# 71 passed out of 71 total

/Users/samuel/.local/state/tec/profiles/base/current/global/bin/bundle exec sus test/covered/sus.rb
# 4 passed out of 4 total

Move ruby-coverage from a runtime dependency to a development dependency so applications that only load integrations such as Covered::Sus do not install the native extension unless they actually record coverage.

Defer loading covered/capture from Covered::Policy#capture so requiring covered or covered/sus does not immediately require ruby/coverage. If capture is used without ruby-coverage installed, raise a targeted LoadError explaining how to add the optional dependency.

Add a Sus regression test that runs in a child process with a trap ruby/coverage file earlier on the load path. Requiring covered/sus with COVERAGE unset must not trigger that file.

Validation: PATH=/Users/samuel/.local/state/tec/profiles/base/current/global/bin:$PATH /Users/samuel/.local/state/tec/profiles/base/current/global/bin/bundle exec bake test

Validation: /Users/samuel/.local/state/tec/profiles/base/current/global/bin/bundle exec sus test/covered/sus.rb
@samuel-williams-shopify samuel-williams-shopify force-pushed the gaia-autopr-lazy-ruby-coverage branch from 89aec93 to 1488bad Compare June 15, 2026 08:30
@samuel-williams-shopify

Copy link
Copy Markdown
Contributor Author

Closing this draft. The better fix is to keep Covered::Sus as-is, since it already defers configuration loading, and handle the optional coverage dependency in the consumer workflow/bundle instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant