Skip to content

Stop same-named models in different packs from annotating each others related files by matching on owning root_dir. - #374

Open
OdenTakashi wants to merge 1 commit into
mainfrom
fix/related-files-root-dir-collision
Open

Stop same-named models in different packs from annotating each others related files by matching on owning root_dir.#374
OdenTakashi wants to merge 1 commit into
mainfrom
fix/related-files-root-dir-collision

Conversation

@OdenTakashi

Copy link
Copy Markdown
Collaborator

Summary

Prevent related-file collisions between models with the same basename in different roots.

Problem

In a Packwerk application with:

  • app/models/address.rbAddress (table: addresses)
  • packs/contacts/app/public/models/address.rbContacts::Address (table: contact_addresses)
  • packs/contacts/test/models/address_test.rb → test for Contacts::Address

both models claim the same test file as a related file. Each model writes its own schema annotation to it—addresses or contact_addresses—and the last writer wins.

As a result, a normal run reports the same file twice:

Annotated (2): packs/contacts/test/models/address_test.rb,
packs/contacts/test/models/address_test.rb

--frozen then fails for whichever model lost the last-write race, even though the annotations are not actually stale.

Root cause

With root_dir: ["", "packs/*"], PatternGetter expands related-file patterns for every configured root, rather than only for the concrete root containing the current model.

For both models, %MODEL_NAME% and %MODEL_NAME_WITHOUT_NS% resolve to address. This causes both models to generate and search the same glob, such as:

packs/*/test/models/address_test.rb

Consequently, both models match packs/contacts/test/models/address_test.rb.

Solution

After finding related files through the existing name-based globbing, filter them so that their concrete root matches the model's root:

  • app/models/address.rb belongs to the project root (nil)

    • It may match project-root related files such as test/models/address_test.rb
    • It does not match files under packs/contacts
  • packs/contacts/app/public/models/address.rb belongs to packs/contacts

    • It matches packs/contacts/test/models/address_test.rb

Files in the project root continue to match each other because both have a root of nil.

The default configuration, root_dir: [""], is unchanged because all model and related files belong to the project root.

Fixes #367

…s related files by matching on owning root_dir.

## Summary
Prevent related-file collisions between models with the same basename in different roots.

## Problem
In a Packwerk application with:

* `app/models/address.rb` → `Address` (table: `addresses`)
* `packs/contacts/app/public/models/address.rb` → `Contacts::Address` (table: `contact_addresses`)
* `packs/contacts/test/models/address_test.rb` → test for `Contacts::Address`

both models claim the same test file as a related file. Each model writes its own schema annotation to it—`addresses` or `contact_addresses`—and the last writer wins.

As a result, a normal run reports the same file twice:

```sh
Annotated (2): packs/contacts/test/models/address_test.rb,
packs/contacts/test/models/address_test.rb
```

`--frozen` then fails for whichever model lost the last-write race, even though the annotations are not actually stale.

## Root cause
With `root_dir: ["", "packs/*"]`, `PatternGetter` expands related-file patterns for every configured root, rather than only for the concrete root containing the current model.

For both models, `%MODEL_NAME%` and `%MODEL_NAME_WITHOUT_NS%` resolve to `address`. This causes both models to generate and search the same glob, such as:

```text
packs/*/test/models/address_test.rb
```

Consequently, both models match `packs/contacts/test/models/address_test.rb`.

## Solution
After finding related files through the existing name-based globbing, filter them so that their concrete root matches the model's root:

* `app/models/address.rb` belongs to the project root (`nil`)
  * It may match project-root related files such as `test/models/address_test.rb`
  * It does not match files under `packs/contacts`
* `packs/contacts/app/public/models/address.rb` belongs to `packs/contacts`

  * It matches `packs/contacts/test/models/address_test.rb`

Files in the project root continue to match each other because both have a root of `nil`.

The default configuration, `root_dir: [""]`, is unchanged because all model and related files belong to the project root.

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

Labels

None yet

Projects

None yet

1 participant