Make packwerk work with in-repo engines using load_path aliases
Nobody has claimed this yet.
- Dominant language
- Ruby
- Stars
- 1.9k
- Forks
- 121
- Avg merge
- 2m
- Merged PRs (30d)
- 1
Description
Description
This is similar to #47 , but there are some distinctions because we're discussing engines, which are autoloaded, vs gems that are not.
The context is that we have a mono-repo setup like this
root_dir
|- engine_1
|- engine_2
|- app_1
|- app_2
where multiple apps will use the same engines. Each engine is symlinked under an apps vendor directory like
root_dir/app_1/vendor/gems/engine_1 -> root_dir/engine_1`
We attempted to setup packwerk for a given app with a root_dir/app_1/packwerk.yml, with a root package at root_dir/app_1/package.yml and a package inside an engine like root_dir/engine_1/app/models/users/package.yml.
We found that we could properly setup the packwerk.yml include and package_paths to follow the symlinks inside of vendor and scan all the files both in the app folder, and in the engine folders, but it would never flag any violations.
In digging in, we found the problem was with the constant resolution workflow. Although the autoload paths for the engines were available in Rails.autoloaders, the path found there was root_dir/engine_1/** instead of root_dir/app_1/vendor/gems/engine_1. As a result it was being filtered out of the paths provided to the ConstantResolver by ApplicationLoadPaths.filter_relevant_paths
We experimented with monkey patching filter_relevant_paths to transform the path names for all these in-repo engines to use the full symlink path. When we did that, everything worked as expected.
I wanted to propose the idea that we upstream our patch by adding a new key to the packwerk.yml configuration file named something like load_path_aliases. This would take a hash where the keys would be the load_path as discovered in Rails.autoloaders and the value would be an alias that the path should be transformed to. Then we'd modify ApplicationLoadPaths to go through these aliases, and transform all the paths before passing them into ConstantResolver
Does this seem like a reasonable approach? If folks are open to it, I can put together a PR
To Reproduce
Setup a mono repo as described above. If folks would like a clearer example, I can setup a sample application.
Expected Behaviour
Under this proposal, a developer could a define a packwerk.yml with this new load_path_aliases something like this
load_path_aliases:
'../engine_1/': 'vendor/gems/engine_1/'
'../engine_2/': 'vendor/gems/engine_2'/
Then any paths that started with ../engine_1/ would be replaced with an equivalent starting with vendor/gems/engine_1
Version Information
- Packwerk: 2.2.0
- Ruby 2.75
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with packwerk.yml, ApplicationLoadPaths.filter_relevant_paths, and ConstantResolver, then reproduce the in-repo engine layout described in the issue. Confirm how Rails.autoloaders exposes the engine paths and evaluate the proposed load_path_aliases behavior; done means the aliased paths reach constant resolution and violations are detected.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rails, ruby
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100