lib/coverband.rb
# frozen_string_literal: true
require "logger"
require "json"
require "redis"
require "coverband/version"
require "coverband/at_exit"
require "coverband/utils/relative_file_converter"
require "coverband/utils/absolute_file_converter"
require "coverband/adapters/base"
require "coverband/adapters/redis_store"
require "coverband/adapters/hash_redis_store"
require "coverband/adapters/file_store"
require "coverband/adapters/stdout_store"
require "coverband/adapters/null_store"
require "coverband/adapters/memcached_store"
require "coverband/utils/file_hasher"
require "coverband/collectors/coverage"
require "coverband/collectors/abstract_tracker"
require "coverband/collectors/view_tracker"
require "coverband/collectors/view_tracker_service"
require "coverband/collectors/route_tracker"
require "coverband/collectors/translation_tracker"
require "coverband/reporters/base"
require "coverband/reporters/console_report"
require "coverband/integrations/background"
require "coverband/integrations/background_middleware"
require "coverband/integrations/rack_server_check"
require "coverband/configuration"
Coverband::Adapters::RedisStore = Coverband::Adapters::HashRedisStore if ENV["COVERBAND_HASH_REDIS_STORE"]
module Coverband
@@configured = false
SERVICE_CONFIG = "./config/coverband_service.rb"
CONFIG_FILE = "./config/coverband.rb"
RUNTIME_TYPE = :runtime
EAGER_TYPE = :eager_loading
MERGED_TYPE = :merged
TYPES = [RUNTIME_TYPE, EAGER_TYPE]
ALL_TYPES = TYPES + [:merged]
def self.configure(file = nil)
configuration_file = file || ENV["COVERBAND_CONFIG"]
if configuration_file.nil?
configuration_file = coverband_service? ? SERVICE_CONFIG : CONFIG_FILE
end
configuration
if block_given?
yield(configuration)
elsif File.exist?(configuration_file)
load configuration_file
else
configuration.logger.debug("using default configuration") if Coverband.configuration.verbose
end
@@configured = true
coverage_instance.reset_instance
end
def self.coverband_service?
!!File.exist?(SERVICE_CONFIG)
end
def self.configured?
@@configured
end
def self.report_coverage
coverage_instance.report_coverage
end
def self.configuration
@configuration ||= Configuration.new
end
def self.start
Coverband::Collectors::Coverage.instance
# TODO: Railtie sets up at_exit after forks, via middleware, perhaps this should be
# added if not rails or if rails but not rackserverrunning
AtExit.register unless tasks_to_ignore?
Background.start if configuration.background_reporting_enabled && !RackServerCheck.running? && !tasks_to_ignore?
end
def self.tasks_to_ignore?
defined?(Rake) &&
Rake.respond_to?(:application) &&
(Rake&.application&.top_level_tasks || []).any? { |task| Coverband::Configuration::IGNORE_TASKS.include?(task) }
end
def self.eager_loading_coverage!
coverage_instance.eager_loading!
end
def self.eager_loading_coverage(...)
coverage_instance.eager_loading(...)
end
def self.runtime_coverage!
coverage_instance.runtime!
end
private_class_method def self.coverage_instance
Coverband::Collectors::Coverage.instance
end
unless ENV["COVERBAND_DISABLE_AUTO_START"]
begin
# Coverband should be setup as early as possible
# to capture usage of things loaded by initializers or other Rails engines
# but after gems are loaded to avoid slowing down gem usage
# best is in application.rb after the bundler line but we get close with Railtie
if defined? ::Rails::Railtie
require "coverband/utils/railtie"
else
configure
start
end
require "coverband/integrations/resque" if defined? ::Resque
require "coverband/integrations/sidekiq_swarm" if defined? ::Sidekiq::Enterprise::Swarm
rescue Redis::CannotConnectError => error
Coverband.configuration.logger.info "Redis is not available (#{error}), Coverband not configured"
Coverband.configuration.logger.info "If this is a setup task like assets:precompile feel free to ignore"
end
end
module Reporters
class Web
###
# NOTE: if the user doesn't setup the webreporter
# we don't need any of the below files loaded or using memory
###
def initialize
require "coverband/reporters/web"
require "coverband/utils/html_formatter"
require "coverband/utils/result"
require "coverband/utils/file_list"
require "coverband/utils/source_file"
require "coverband/utils/lines_classifier"
require "coverband/utils/results"
require "coverband/reporters/html_report"
require "coverband/reporters/json_report"
init_web
end
def self.call(env)
@app ||= new
@app.call(env)
end
end
end
end