diff --git a/USAGE.md b/USAGE.md index 435ad3ac4..0841a9737 100644 --- a/USAGE.md +++ b/USAGE.md @@ -21,6 +21,8 @@ * [Understanding how to respond to new violations](#understanding-how-to-respond-to-new-violations) * [Recording existing violations](#recording-existing-violations) * [Understanding the package todo file](#understanding-the-package-todo-file) + * [Understanding the list of deprecated references](#understanding-the-list-of-deprecated-references) +* [Loading extensions](#loading-extensions) ## What problem does Packwerk solve? @@ -275,3 +277,16 @@ Above is an example of a constant violation entry in `package_todo.yml`. * `components/merchant/app/public/merchant/generate_order.rb` - path to the file containing the violated constant Violations exist within the package that makes a violating reference. This means privacy violations of your package can be found listed in `package_todo.yml` files in the packages with the reference to a private constant. + +# Loading Extensions + +You can optionally specify ruby files that you'd like to be loaded with `packwerk` by specifying a `require` directive in `packwerk.yml`: +```yml +require: + - ./path/to/file.rb + - my_gem +``` + +`packwerk` will directly call `require` with these paths. +You can prefix local files with a dot to define them relative to `packwerk.yml`, or you can use absolute paths. +You can also reference the name of a gem. diff --git a/lib/packwerk.rb b/lib/packwerk.rb index 9da66f7d8..4f2a9994c 100644 --- a/lib/packwerk.rb +++ b/lib/packwerk.rb @@ -22,6 +22,7 @@ module Packwerk autoload :ConstantNameInspector autoload :ConstNodeInspector autoload :PackageTodo + autoload :ExtensionLoader autoload :FileProcessor autoload :FilesForProcessing autoload :Graph diff --git a/lib/packwerk/configuration.rb b/lib/packwerk/configuration.rb index 4b13f1e0d..d921250a3 100644 --- a/lib/packwerk/configuration.rb +++ b/lib/packwerk/configuration.rb @@ -49,6 +49,12 @@ def initialize(configs = {}, config_path: nil) @cache_directory = Pathname.new(configs["cache_directory"] || "tmp/cache/packwerk") @config_path = config_path + if configs.key?("require") + configs["require"].each do |require_directive| + ExtensionLoader.load(require_directive, @root_path) + end + end + if configs["load_paths"] warning = <<~WARNING DEPRECATION WARNING: The 'load_paths' key in `packwerk.yml` is deprecated. diff --git a/lib/packwerk/extension_loader.rb b/lib/packwerk/extension_loader.rb new file mode 100644 index 000000000..e7e99d3fc --- /dev/null +++ b/lib/packwerk/extension_loader.rb @@ -0,0 +1,24 @@ +# typed: strict +# frozen_string_literal: true + +module Packwerk + # This class handles loading extensions to packwerk using the `require` directive + # in the `packwerk.yml` configuration. + class ExtensionLoader + class << self + extend T::Sig + sig { params(require_directive: String, config_dir_path: String).void } + def load(require_directive, config_dir_path) + # We want to transform the require directive to behave differently + # if it's a specific local file being required versus a gem + if require_directive.start_with?(".") + require File.join(config_dir_path, require_directive) + else + require require_directive + end + end + end + end + + private_constant :ExtensionLoader +end diff --git a/test/fixtures/skeleton/config/my_extension.rb b/test/fixtures/skeleton/config/my_extension.rb new file mode 100644 index 000000000..6ff1c10c3 --- /dev/null +++ b/test/fixtures/skeleton/config/my_extension.rb @@ -0,0 +1,2 @@ +module MySpecialExtension +end diff --git a/test/fixtures/skeleton/packwerk.yml b/test/fixtures/skeleton/packwerk.yml index 573a73e3b..7cea52813 100644 --- a/test/fixtures/skeleton/packwerk.yml +++ b/test/fixtures/skeleton/packwerk.yml @@ -4,3 +4,6 @@ include: exclude: - "**/temp.rb" parallel: false +require: + - ./config/my_extension.rb + - pathname diff --git a/test/integration/custom_executable_test.rb b/test/integration/custom_executable_test.rb index e0d569ec1..9b7cf681a 100644 --- a/test/integration/custom_executable_test.rb +++ b/test/integration/custom_executable_test.rb @@ -80,8 +80,8 @@ class CustomExecutableTest < Minitest::Test package_todo_content_after_update = read_package_todo expected_output = <<~EOS - 📦 Packwerk is inspecting 13 files - \\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\. + 📦 Packwerk is inspecting 14 files + \\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\. 📦 Finished in \\d+\\.\\d+ seconds No offenses detected @@ -115,8 +115,8 @@ class CustomExecutableTest < Minitest::Test package_todo_content_after_update = read_package_todo.reject { |k, _v| k.match?(timeline_package_todo_path) } expected_output = <<~EOS - 📦 Packwerk is inspecting 14 files - \\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\. + 📦 Packwerk is inspecting 15 files + \\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\.\\. 📦 Finished in \\d+\\.\\d+ seconds No offenses detected