Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RuboCop pulls in .rubocop.yml files from *excluded* directories when specifying explicit target despite using "--force-exclusion" #12667

Closed
immerrr opened this issue Feb 1, 2024 · 2 comments
Labels

Comments

@immerrr
Copy link

immerrr commented Feb 1, 2024

At the first sight my issue is similar to #9832, but I was unable to fix it using the solutions that were proposed there.

One of the dependent gems of my project located in vendor/cache/... includes its own .rubocop.yml with rubocop-performance plugin. Pre-commit hook fails for my project if I update that gem, because rubocop-performance is not installed. I double checked that vendor/**/* is excluded in the config.

The final command generated by the pre-commit hook boils down to:

$ rubocop --debug --force-exclusion  vendor/cache/jsonapi-serializer-d030cfa7db1f/lib/fast_jsonapi.rb 

And excludes in root .rubocop.yml look like this:

AllCops:
  ...
  Exclude:
    - tmp/**/*
    - db/schema.rb
    - vendor/**/*
    - db/**/*
    - bin/**/*
    - test/fixtures/**/*

Expected behavior

I'd expect rubocop not to go into the excluded directory when --force-exclusion is specified alongside an excluded target. But looks like it may not be possible with the current implementation that checks exclusion only after loading the corresponding config file (in this case, the one that is also located in an ignored directory)

      files.reject do |file|
        config = @config_store.for(file)
        config.file_to_exclude?(file)
      end

Actual behavior

Describe here what actually happened.
Please use rubocop --debug when pasting rubocop output as it contains additional information.

$ rubocop --debug --force-exclusion  vendor/cache/jsonapi-serializer-d030cfa7db1f/lib/fast_jsonapi.rb
For /home/immerrr/src/rails: configuration from /home/immerrr/src/rails/.rubocop.yml
configuration from /home/immerrr/.asdf/installs/ruby/2.7.8/lib/ruby/gems/2.7.0/gems/rubocop-rails-2.23.1/config/default.yml
configuration from /home/immerrr/.asdf/installs/ruby/2.7.8/lib/ruby/gems/2.7.0/gems/rubocop-rails-2.23.1/config/default.yml
Default configuration from /home/immerrr/.asdf/installs/ruby/2.7.8/lib/ruby/gems/2.7.0/gems/rubocop-1.60.2/config/default.yml
For vendor/cache/jsonapi-serializer-d030cfa7db1f/lib: configuration from /home/immerrr/src/rails/vendor/cache/jsonapi-serializer-d030cfa7db1f/.rubocop.yml
cannot load such file -- rubocop-performance
/home/immerrr/.asdf/installs/ruby/2.7.8/lib/ruby/gems/2.7.0/gems/rubocop-1.60.2/lib/rubocop/feature_loader.rb:46:in `rescue in rescue in load'

Steps to reproduce the problem

  • select or create a file that is excluded with AllCops/Exclude configuration
  • create a .rubocop.yml next to that excluded file
  • run rubocop specifying the excluded file explicitly and adding --force-exclusion --debug
  • observe how the .rubocop.yml is loaded
$ touch vendor/test.rb
$ touch vendor/.rubocop.yml
$ rubocop --debug --force-exclusion vendor/test.rb
For /home/immerrr/src/rails: configuration from /home/immerrr/src/rails/.rubocop.yml
configuration from /home/immerrr/.asdf/installs/ruby/2.7.8/lib/ruby/gems/2.7.0/gems/rubocop-rails-2.9.1/config/default.yml
configuration from /home/immerrr/.asdf/installs/ruby/2.7.8/lib/ruby/gems/2.7.0/gems/rubocop-rails-2.9.1/config/default.yml
Default configuration from /home/immerrr/.asdf/installs/ruby/2.7.8/lib/ruby/gems/2.7.0/gems/rubocop-1.60.2/config/default.yml
For vendor: configuration from /home/immerrr/src/rails/vendor/.rubocop.yml
AllCops/Exclude configuration from /home/immerrr/src/rails/.rubocop.yml

<..snip..>

Inspecting 0 files


0 files inspected, no offenses detected
Finished in 0.27509697404457256 seconds

RuboCop version

Include the output of rubocop -V or bundle exec rubocop -V if using Bundler.
If you see extension cop versions (e.g. rubocop-performance, rubocop-rspec, and others)
output by rubocop -V, include them as well. Here's an example:

$ rubocop -V
1.60.2 (using Parser 3.3.0.5, rubocop-ast 1.30.0, running on ruby 2.7.8) [x86_64-linux]
  - rubocop-rails 2.23.1
@immerrr
Copy link
Author

immerrr commented Feb 1, 2024

For now, I was able to work this around by adding explicit --config .rubocop.yml to my pre-commit hook, but opening an issue here if it is indeed an unexpected behaviour.

@jonas054
Copy link
Collaborator

This is a very special case. Quite tricky. But I think it's valid and I'm adding the bug label. I'll see if I can come up with a solution.

@jonas054 jonas054 added the bug label Feb 28, 2024
jonas054 added a commit to jonas054/rubocop that referenced this issue Mar 2, 2024
This change fixes an error that can occur when file names are
given explicity on the command line together with
`--force-exclusion`.

In order to check if the given files are to be excluded, we
must load configuration. The problem is that `.rubocop.yml`
files in directories with excluded files (e.g. a `vendor`
directory) might contain directives that will cause RuboCop
to crash, such as `require` with an extension that's not
available.

What saves us in this situation is that we don't need to
load configuration for the file as such. We can load
configuration for the current directory instead. The reason
is that `Exclude` parameters on the top level are not
shadowed by `Exclude` in other `.rubocop.yml` files in
subdirectories, as documented here:

https://docs.rubocop.org/rubocop/1.60/configuration.html#include-and-exclude-are-relative-to-their-directory

The `--ignore-parent-exclusion` flag, if given, changes the
situation and we must load the most adjacent `.rubocop.yml`
file.
jonas054 added a commit to jonas054/rubocop that referenced this issue Mar 2, 2024
This change fixes an error that can occur when file names are
given explicitly on the command line together with
`--force-exclusion`.

In order to check if the given files are to be excluded, we
must load configuration. The problem is that `.rubocop.yml`
files in directories with excluded files (e.g. a `vendor`
directory) might contain directives that will cause RuboCop
to crash, such as `require` with an extension that's not
available.

What saves us in this situation is that we don't need to
load configuration for the file as such. We can load
configuration for the current directory instead. The reason
is that `Exclude` parameters on the top level are not
shadowed by `Exclude` in other `.rubocop.yml` files in
subdirectories, as documented here:

https://docs.rubocop.org/rubocop/1.60/configuration.html#include-and-exclude-are-relative-to-their-directory

The `--ignore-parent-exclusion` flag, if given, changes the
situation and we must load the most adjacent `.rubocop.yml`
file.
@bbatsov bbatsov closed this as completed in 664ba3d Mar 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants