diff --git a/README.md b/README.md index 2566bbd..8a9110e 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,13 @@ Crawlscope requires Ruby 3.3 or newer. Add this line to your application's Gemfile: ```ruby -gem "crawlscope" +gem "crawlscope", require: false ``` +`require: false` keeps Crawlscope and its crawl stack out of normal Rails web +and job process boot. Require `crawlscope` at the application boundary that +runs an audit, or use the task setup below. + And then execute: ```bash @@ -142,6 +146,19 @@ puts result.issues.to_a.map(&:message) ## Rails Usage +For an app that uses Crawlscope through rake tasks, load the task entrypoint +only when a Crawlscope task is requested. In the application's `Rakefile`, +before `require_relative "config/application"`: + +```ruby +list_tasks = Rake.application.options.show_tasks || ARGV.any? { |argument| ["-T", "--tasks"].include?(argument) } +require "crawlscope/tasks" if list_tasks || ARGV.any? { |argument| argument.start_with?("crawlscope:") } +``` + +This preserves `bin/rails --tasks` and the `crawlscope:*` tasks without loading +Crawlscope during normal Rails boot. Runtime callers should explicitly +`require "crawlscope"` immediately before configuring or using the gem. + In an initializer: ```ruby diff --git a/lib/crawlscope.rb b/lib/crawlscope.rb index 4798509..ea32c9b 100644 --- a/lib/crawlscope.rb +++ b/lib/crawlscope.rb @@ -29,6 +29,7 @@ def reset! Crawlscope.instance_variable_set(:@loader, Zeitwerk::Loader.for_gem) Crawlscope.loader.ignore("#{__dir__}/tasks") Crawlscope.loader.ignore("#{__dir__}/crawlscope/railtie.rb") +Crawlscope.loader.ignore("#{__dir__}/crawlscope/tasks.rb") Crawlscope.loader.setup require "crawlscope/railtie" if defined?(Rails::Railtie) diff --git a/lib/crawlscope/railtie.rb b/lib/crawlscope/railtie.rb index 692fe10..e49f7e0 100644 --- a/lib/crawlscope/railtie.rb +++ b/lib/crawlscope/railtie.rb @@ -3,7 +3,7 @@ module Crawlscope class Railtie < Rails::Railtie rake_tasks do - load File.expand_path("../tasks/crawlscope_tasks.rake", __dir__) + require "crawlscope/tasks" end end end diff --git a/lib/crawlscope/tasks.rb b/lib/crawlscope/tasks.rb new file mode 100644 index 0000000..e034149 --- /dev/null +++ b/lib/crawlscope/tasks.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require "crawlscope" +require "rake" + +unless Rake::Task.task_defined?("crawlscope:validate") + load File.expand_path("../tasks/crawlscope_tasks.rake", __dir__) +end diff --git a/test/crawlscope/loader_test.rb b/test/crawlscope/loader_test.rb index 5432b7b..bbe4ed8 100644 --- a/test/crawlscope/loader_test.rb +++ b/test/crawlscope/loader_test.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true require "test_helper" +require "open3" +require "rbconfig" class CrawlscopeLoaderTest < Minitest::Test def test_eager_loads_cleanly @@ -8,4 +10,39 @@ def test_eager_loads_cleanly Crawlscope.loader.eager_load end end + + def test_entrypoint_does_not_load_crawl_dependencies + script = <<~RUBY + require "crawlscope" + + loaded = $LOADED_FEATURES.grep(%r{/(?:async|faraday|json-schema|nokogiri)(?:/|\\.rb)}) + abort loaded.join("\\n") unless loaded.empty? + RUBY + + _stdout, stderr, status = Open3.capture3( + RbConfig.ruby, + "-I#{File.expand_path("../../lib", __dir__)}", + "-e", + script + ) + + assert status.success?, stderr + end + + def test_task_entrypoint_registers_tasks + script = <<~RUBY + require "crawlscope/tasks" + + abort "task missing" unless Rake::Task.task_defined?("crawlscope:validate") + RUBY + + _stdout, stderr, status = Open3.capture3( + RbConfig.ruby, + "-I#{File.expand_path("../../lib", __dir__)}", + "-e", + script + ) + + assert status.success?, stderr + end end