Skip to content

Default ignores cannot be removed, so engines under vendor/engines/ are silently unanalysable #28

Description

@n-rodriguez

Summary

DEFAULT_IGNORE_PATTERNS includes vendor/**/*, and Definition#add_ignore_patterns only
ever appends (@ignore_patterns |= …). There is no DSL affordance to drop a default ignore,
so a Rails app whose engines live in vendor/engines/ cannot analyse them at all.

This interacts badly with two other facts:

  • DEFAULT_SOURCE_PATTERNS already lists engines/*/app/**/*.rb, so engines are clearly
    meant to be in scope — just not at the path Rails has historically used for them.
  • Analyzer#ruby_files applies ignored as a final reject, after
    Definition#analysis_patterns has unioned in every component's file_patterns. So the DSL
    documentation ("Component patterns are always analyzed, so most projects never need this")
    does not hold against a default ignore: the component comes out empty and every rule on it
    is vacuously satisfied — the same shape as Analyse .rake files (source globs matching *.rake are silently dropped) #24.

Declaring source does not help either, and makes things worse:

def analysis_patterns
  patterns = source_patterns.empty? ? DEFAULT_SOURCE_PATTERNS.dup : source_patterns.dup
  patterns | component_specs.values.flat_map(&:file_patterns)
end

source replaces the defaults rather than adding to them, and the ignore still wins.

Measured

A Rails app with three tenant engines under vendor/engines/ (184 .rb files), on 1.1.0:

Spec files reported Engines analysed
components declared on vendor/engines/*/**/*.rb 3532 (= app + lib + spec exactly) no
same, plus source "vendor/engines/**/*.rb" 2211 (defaults lost) no
separate spec with root 'vendor/engines' 184 yes

archspec explain vendor/engines/engine_a/app/helpers/some_helper.rb returns
no file or constant found.

Two boundary rules — "no engine may reference another engine's namespace" and "the host app
may not call an engine operation" — reported 0 violations while checking nothing. They were
only caught because a deliberate violation was injected and stayed green.

Use case

each_directory 'vendor/engines/*' do |name, path|
  component name.to_sym, in: "#{path}/**/*.rb"
end

engine_a.cannot_use :engine_b, :engine_c

The root 'vendor/engines' workaround does analyse the engines, but that graph excludes the
host application, so any rule spanning host → engine is unexpressible in it.

Suggestion

Any of these would be enough:

  1. let ignore remove a default, e.g. ignore '!vendor/**/*' or unignore 'vendor/engines/**/*';
  2. exempt explicit component file_patterns from the default ignores (keeping user-declared
    ignores authoritative), which would match what the DSL docs already promise;
  3. add vendor/engines/*/app/**/*.rb to DEFAULT_SOURCE_PATTERNS and narrow the default
    ignore to vendor/bundle/**/* and friends.

Either way, a component whose glob matches files on disk but resolves to zero analysed files
is worth a warning — that silence is what makes this class of bug survive.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions