Class: Coverband::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/coverband/configuration.rb

Overview

Configuration parsing and options for the coverband gem.

Constant Summary collapse

IGNORE_TASKS =

TODO: This is is brittle and not a great solution to avoid deploy time actions polluting the 'runtime' metrics

  • Perhaps detect heroku deployment ENV var opposed to tasks?
["coverband:clear",
"coverband:coverage",
"coverband:coverage_server",
"assets:precompile",
"webpacker:compile",
"db:version",
"db:create",
"db:drop",
"db:seed",
"db:setup",
"db:test:prepare",
"db:structure:dump",
"db:structure:load",
"db:version"]
IGNORE_DEFAULTS =

Heroku when building assets runs code from a dynamic directory /tmp was added to avoid coverage from /tmp/build directories during heroku asset compilation

%w[vendor/ /tmp internal:prelude db/schema.rb] + Collectors::ViewTracker::VIEWS_PATTERNS
TRACKED_DEFAULT_PATHS =

Add in missing files which were never loaded we need to know what all paths to check for unloaded files

%w[app lib config]
SKIPPED_SETTINGS =
%w[@s3_secret_access_key @store @api_key @password @mcp_password]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfiguration

Returns a new instance of Configuration.



60
61
62
# File 'lib/coverband/configuration.rb', line 60

def initialize
  reset
end

Instance Attribute Details

#api_keyObject



310
311
312
# File 'lib/coverband/configuration.rb', line 310

def api_key
  @api_key ||= ENV["COVERBAND_API_KEY"]
end

#background_reporting_enabledObject

Returns the value of attribute background_reporting_enabled.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def background_reporting_enabled
  @background_reporting_enabled
end

#background_reporting_sleep_secondsObject

The adjustments here either protect the redis or service from being overloaded the tradeoff being the delay in when reporting data is available if running your own redis increasing this number reduces load on the redis CPU



201
202
203
204
205
206
207
208
209
210
211
# File 'lib/coverband/configuration.rb', line 201

def background_reporting_sleep_seconds
  @background_reporting_sleep_seconds ||= if service?
    # default to 10m for service
    (Coverband.configuration.coverband_env == "production") ? 600 : 60
  elsif store.is_a?(Coverband::Adapters::HashRedisStore)
    # Default to 5 minutes if using the hash redis store
    300
  else
    60
  end
end

#coverband_timeoutObject



322
323
324
# File 'lib/coverband/configuration.rb', line 322

def coverband_timeout
  @coverband_timeout ||= (coverband_env == "development") ? 5 : 2
end

#csp_policyObject

Returns the value of attribute csp_policy.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def csp_policy
  @csp_policy
end

#defer_eager_loading_dataObject

Returns the value of attribute defer_eager_loading_data.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def defer_eager_loading_data
  @defer_eager_loading_data
end

#gem_detailsObject

Returns the value of attribute gem_details.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def gem_details
  @gem_details
end

#hide_settingsObject

Returns the value of attribute hide_settings.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def hide_settings
  @hide_settings
end

#ignoreObject

Returns the value of attribute ignore.



28
29
30
# File 'lib/coverband/configuration.rb', line 28

def ignore
  @ignore
end

#loggerObject



160
161
162
163
164
165
166
# File 'lib/coverband/configuration.rb', line 160

def logger
  @logger ||= if defined?(Rails.logger) && Rails.logger
    Rails.logger
  else
    Logger.new($stdout)
  end
end

#mcp_allowed_environmentsObject



194
195
196
# File 'lib/coverband/configuration.rb', line 194

def mcp_allowed_environments
  @mcp_allowed_environments || %w[development test]
end

#mcp_enabledObject

Returns the value of attribute mcp_enabled.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def mcp_enabled
  @mcp_enabled
end

#mcp_passwordObject



190
191
192
# File 'lib/coverband/configuration.rb', line 190

def mcp_password
  @mcp_password || ENV["COVERBAND_MCP_PASSWORD"]
end

#paged_reportingObject



350
351
352
# File 'lib/coverband/configuration.rb', line 350

def paged_reporting
  !!@paged_reporting
end

#passwordObject



173
174
175
# File 'lib/coverband/configuration.rb', line 173

def password
  @password || ENV["COVERBAND_PASSWORD"]
end

#process_typeObject



334
335
336
# File 'lib/coverband/configuration.rb', line 334

def process_type
  @process_type ||= ENV["PROCESS_TYPE"] || "unknown"
end

#query_burst_query_count_thresholdObject

Returns the value of attribute query_burst_query_count_threshold.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def query_burst_query_count_threshold
  @query_burst_query_count_threshold
end

#query_burst_sql_time_threshold_msObject

Returns the value of attribute query_burst_sql_time_threshold_ms.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def query_burst_sql_time_threshold_ms
  @query_burst_sql_time_threshold_ms
end

#query_burst_trackerObject

Returns the value of attribute query_burst_tracker.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def query_burst_tracker
  @query_burst_tracker
end

#redis_namespaceObject

Returns the value of attribute redis_namespace.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def redis_namespace
  @redis_namespace
end

#redis_ttlObject

Returns the value of attribute redis_ttl.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def redis_ttl
  @redis_ttl
end

#redis_urlObject



306
307
308
# File 'lib/coverband/configuration.rb', line 306

def redis_url
  @redis_url ||= ENV["COVERBAND_REDIS_URL"] || ENV["REDIS_URL"]
end

#report_on_exitObject

Returns the value of attribute report_on_exit.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def report_on_exit
  @report_on_exit
end

#reporterObject

Returns the value of attribute reporter.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def reporter
  @reporter
end

#reporting_wiggleObject



213
214
215
# File 'lib/coverband/configuration.rb', line 213

def reporting_wiggle
  @reporting_wiggle ||= 30
end

#rootObject

Returns the value of attribute root.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def root
  @root
end

#root_pathsObject

Returns the value of attribute root_paths.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def root_paths
  @root_paths
end

#route_trackerObject

Returns the value of attribute route_tracker.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def route_tracker
  @route_tracker
end

#s3_access_key_idObject



369
370
371
# File 'lib/coverband/configuration.rb', line 369

def s3_access_key_id
  puts "deprecated, s3 is no longer support"
end

#s3_bucketObject



361
362
363
# File 'lib/coverband/configuration.rb', line 361

def s3_bucket
  puts "deprecated, s3 is no longer support"
end

#s3_regionObject



365
366
367
# File 'lib/coverband/configuration.rb', line 365

def s3_region
  puts "deprecated, s3 is no longer support"
end

#s3_secret_access_keyObject



373
374
375
# File 'lib/coverband/configuration.rb', line 373

def s3_secret_access_key
  puts "deprecated, s3 is no longer support"
end

#send_deferred_eager_loading_data=(value) ⇒ Object (writeonly)

Sets the attribute send_deferred_eager_loading_data

Parameters:

  • value

    the value to set the attribute send_deferred_eager_loading_data to.



22
23
24
# File 'lib/coverband/configuration.rb', line 22

def send_deferred_eager_loading_data=(value)
  @send_deferred_eager_loading_data = value
end

#service_dev_modeObject



326
327
328
# File 'lib/coverband/configuration.rb', line 326

def service_dev_mode
  @service_dev_mode ||= ENV["COVERBAND_ENABLE_DEV_MODE"] || false
end

#service_test_modeObject



330
331
332
# File 'lib/coverband/configuration.rb', line 330

def service_test_mode
  @service_test_mode ||= ENV["COVERBAND_ENABLE_TEST_MODE"] || false
end

#service_urlObject



314
315
316
# File 'lib/coverband/configuration.rb', line 314

def service_url
  @service_url ||= ENV["COVERBAND_URL"] || "https://coverband.io"
end

#simulate_oneshot_lines_coverageObject

Returns the value of attribute simulate_oneshot_lines_coverage.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def simulate_oneshot_lines_coverage
  @simulate_oneshot_lines_coverage
end

#test_envObject

Returns the value of attribute test_env.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def test_env
  @test_env
end

#track_gemsObject

Returns the value of attribute track_gems.



28
29
30
# File 'lib/coverband/configuration.rb', line 28

def track_gems
  @track_gems
end

#track_query_burstsObject

Returns the value of attribute track_query_bursts.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def track_query_bursts
  @track_query_bursts
end

#track_redirect_routesObject

Returns the value of attribute track_redirect_routes.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def track_redirect_routes
  @track_redirect_routes
end

#track_routesObject

Returns the value of attribute track_routes.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def track_routes
  @track_routes
end

#track_translationsObject

Returns the value of attribute track_translations.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def track_translations
  @track_translations
end

#track_viewsObject



254
255
256
257
258
# File 'lib/coverband/configuration.rb', line 254

def track_views
  return false if service_disabled_dev_test_env?

  @track_views
end

#trackersObject

Returns the value of attribute trackers.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def trackers
  @trackers
end

#translations_trackerObject

Returns the value of attribute translations_tracker.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def translations_tracker
  @translations_tracker
end

#use_oneshot_lines_coverageObject

Returns the value of attribute use_oneshot_lines_coverage.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def use_oneshot_lines_coverage
  @use_oneshot_lines_coverage
end

#verboseObject

Returns the value of attribute verbose.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def verbose
  @verbose
end

#view_trackerObject

Returns the value of attribute view_tracker.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def view_tracker
  @view_tracker
end

#web_debugObject

Returns the value of attribute web_debug.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def web_debug
  @web_debug
end

#web_enable_clearObject

Returns the value of attribute web_enable_clear.



8
9
10
# File 'lib/coverband/configuration.rb', line 8

def web_enable_clear
  @web_enable_clear
end

Instance Method Details

#all_root_pathsObject



286
287
288
289
290
291
292
# File 'lib/coverband/configuration.rb', line 286

def all_root_paths
  return @all_root_paths if @all_root_paths

  @all_root_paths = Coverband.configuration.root_paths.dup
  @all_root_paths << "#{Coverband.configuration.current_root}/"
  @all_root_paths
end

#all_root_patternsObject



294
295
296
# File 'lib/coverband/configuration.rb', line 294

def all_root_patterns
  @all_root_patterns ||= all_root_paths.map { |path| /^#{path}/ }.freeze
end

#coverband_envObject



318
319
320
# File 'lib/coverband/configuration.rb', line 318

def coverband_env
  ENV["RACK_ENV"] || ENV["RAILS_ENV"] || ((defined?(Rails) && Rails.respond_to?(:env)) ? Rails.env : "unknown")
end

#current_rootObject



282
283
284
# File 'lib/coverband/configuration.rb', line 282

def current_root
  @current_root ||= File.expand_path(Coverband.configuration.root).freeze
end

#defer_eager_loading_data?Boolean

Returns:

  • (Boolean)


342
343
344
# File 'lib/coverband/configuration.rb', line 342

def defer_eager_loading_data?
  @defer_eager_loading_data
end

#mcp_enabled?Boolean

Returns:

  • (Boolean)


177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/coverband/configuration.rb', line 177

def mcp_enabled?
  # MCP is disabled by default and explicitly controlled
  return false unless @mcp_enabled

  # Check if current environment is allowed
  current_env = (defined?(Rails) && Rails.respond_to?(:env) && Rails.env) ||
    ENV["RAILS_ENV"] ||
    ENV["RACK_ENV"] ||
    "development"

  mcp_allowed_environments.include?(current_env.to_s)
end

#railtie!Object



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/coverband/configuration.rb', line 130

def railtie!
  if Coverband.configuration.track_routes
    Coverband.configuration.route_tracker = Coverband::Collectors::RouteTracker.new
    trackers << Coverband.configuration.route_tracker
  end

  if Coverband.configuration.track_translations
    Coverband.configuration.translations_tracker = Coverband::Collectors::TranslationTracker.new
    trackers << Coverband.configuration.translations_tracker
  end

  if Coverband.configuration.track_views
    Coverband.configuration.view_tracker = if Coverband.coverband_service?
      Coverband::Collectors::ViewTrackerService.new
    else
      Coverband::Collectors::ViewTracker.new
    end
    trackers << Coverband.configuration.view_tracker
  end

  if Coverband.configuration.track_query_bursts
    Coverband.configuration.query_burst_tracker = Coverband::Collectors::QueryBurstTracker.new
    trackers << Coverband.configuration.query_burst_tracker
  end
  trackers.each { |tracker| tracker.railtie! }
rescue Redis::CannotConnectError => e
  Coverband.configuration.logger.info "Redis is not available (#{e}), Coverband not configured"
  Coverband.configuration.logger.info "If this is a setup task like assets:precompile feel free to ignore"
end

#resetObject



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/coverband/configuration.rb', line 64

def reset
  @root = Dir.pwd
  @root_paths = []
  @ignore = IGNORE_DEFAULTS.map { |ignore_str| Regexp.new(ignore_str) }
  @search_paths = TRACKED_DEFAULT_PATHS.dup
  @verbose = false
  @reporter = "scov"
  @logger = nil
  @store = nil
  @background_reporting_enabled = true
  @background_reporting_sleep_seconds = nil
  @defer_eager_loading_data = false
  @send_deferred_eager_loading_data = true
  @test_env = nil
  @web_enable_clear = false
  @track_views = true
  @view_tracker = nil
  @track_routes = false
  @track_redirect_routes = true
  @route_tracker = nil
  @track_translations = false
  @translations_tracker = nil
  @track_query_bursts = false
  @query_burst_tracker = nil
  @query_burst_query_count_threshold = 30
  @query_burst_sql_time_threshold_ms = 100.0
  @web_debug = false
  @report_on_exit = true
  @use_oneshot_lines_coverage = ENV["ONESHOT"] || false
  @simulate_oneshot_lines_coverage = false # this is being deprecated
  @current_root = nil
  @all_root_paths = nil
  @all_root_patterns = nil
  @password = nil
  @csp_policy = false
  @hide_settings = false

  # MCP (Model Context Protocol) security settings
  @mcp_enabled = false
  @mcp_password = nil
  @mcp_allowed_environments = %w[development test]

  # coverband service settings
  @api_key = nil
  @service_url = nil
  @coverband_timeout = nil
  @service_dev_mode = nil
  @service_test_mode = nil
  @process_type = nil

  @redis_url = nil
  @redis_namespace = nil
  @redis_ttl = 2_592_000 # in seconds. Default is 30 days.
  @reporting_wiggle = nil

  @trackers = []

  # TODO: these are deprecated
  @s3_region = nil
  @s3_bucket = nil
  @s3_access_key_id = nil
  @s3_secret_access_key = nil
  @track_gems = false
  @gem_details = false
end

#routes_trackerObject

Alias for backward compatibility - track_key uses :routes_tracker symbol



169
170
171
# File 'lib/coverband/configuration.rb', line 169

def routes_tracker
  route_tracker
end

#search_paths=(path_array) ⇒ Object

Don't allow the to override defaults



270
271
272
# File 'lib/coverband/configuration.rb', line 270

def search_paths=(path_array)
  @search_paths = (@search_paths + path_array).uniq
end

#send_deferred_eager_loading_data?Boolean

Returns:

  • (Boolean)


346
347
348
# File 'lib/coverband/configuration.rb', line 346

def send_deferred_eager_loading_data?
  @send_deferred_eager_loading_data
end

#service?Boolean

Returns:

  • (Boolean)


338
339
340
# File 'lib/coverband/configuration.rb', line 338

def service?
  Coverband.coverband_service? || !api_key.nil?
end

#service_disabled_dev_test_env?Boolean

Returns:

  • (Boolean)


354
355
356
357
358
359
# File 'lib/coverband/configuration.rb', line 354

def service_disabled_dev_test_env?
  return false unless service?

  (coverband_env == "test" && !Coverband.configuration.service_test_mode) ||
    (coverband_env == "development" && !Coverband.configuration.service_dev_mode)
end

#storeObject



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/coverband/configuration.rb', line 217

def store
  @store ||= if service?
    if ENV["COVERBAND_REDIS_URL"]
      raise "invalid configuration: unclear default store coverband expects either api_key or redis_url"
    end

    require "coverband/adapters/web_service_store"
    Coverband::Adapters::WebServiceStore.new(service_url)
  else
    begin
      # Redis gem automatically enables TLS when the scheme is 'rediss://'
      # For serverless ElastiCache or other TLS-required Redis instances, use:
      #   REDIS_URL=rediss://your-endpoint:6379
      Coverband::Adapters::RedisStore.new(Redis.new(url: redis_url), redis_store_options)
    rescue Redis::CannotConnectError => error
      logger.info "Redis is not available (#{error}), defaulting to NullStore"
      logger.info "If this is intended, please explicitly configure your store: config.store = Coverband::Adapters::FileStore.new('log/coverage')"
      require "coverband/adapters/null_store"
      Coverband::Adapters::NullStore.new
    end
  end
end

#store=(store) ⇒ Object



240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/coverband/configuration.rb', line 240

def store=(store)
  raise "Pass in an instance of Coverband::Adapters" unless store.is_a?(Coverband::Adapters::Base)
  if api_key && store.class.to_s != "Coverband::Adapters::WebServiceStore"
    raise "invalid configuration: only coverband service expects an API Key"
  end
  if ENV["COVERBAND_REDIS_URL"] &&
      defined?(::Coverband::Adapters::WebServiceStore) &&
      store.instance_of?(::Coverband::Adapters::WebServiceStore)
    raise "invalid configuration: coverband service shouldn't have redis url set"
  end

  @store = store
end

#to_hObject



299
300
301
302
303
304
# File 'lib/coverband/configuration.rb', line 299

def to_h
  instance_variables
    .each_with_object({}) do |var, hash|
      hash[var.to_s.delete("@")] = instance_variable_get(var) unless SKIPPED_SETTINGS.include?(var.to_s)
    end
end

#tracked_search_pathsObject

Search Paths



263
264
265
# File 'lib/coverband/configuration.rb', line 263

def tracked_search_paths
  "#{Coverband.configuration.current_root}/{#{@search_paths.join(",")}}/**/*.{rb}"
end