This message was imported from the Ruby/Rails Modularity Slack server. Find more info in the import thread.
Message originally sent by slack user U7242JFKJGS
Hi. Looking at possibly adding Packwerk to a large monorepo, which contains a core rails app and then several gems and engines. Because Packwerk uses Zeitwerk, do the gems and engine paths need to be added to the core rails app eager_loaded_paths , for Packwerk to be able to see them? Or does Packwerk not take Rails’ Zeitwerk configuration into account?
If your main application is able to load constants from engines, packwerk should be able to see those constants just fine. Packwerk loads Rails to find the autoload paths.
If your gem is configured to use zeitwerk, it should also be visible to packwerk. Otherwise, packwerk will not be able to see it at all. For a net new implementation of packwerk you might consider giving packs a try, which doesn’t depend on rails/zeitwerk, so you don’t need to worry about autoloading or anything like that.
Right. I was trying to figure out if I need to use Packs instead.
So in summary, Packwerk will know about engines/gems outside of the rails app autoload paths because of how they’re included as gems.
Packwerk will not know about a gem/engine that is not in an autoload path and not included in the rails app gemfile. But could know about it with stephan’s suggestion above.
do you mind elaborating on detecting more_?_ my understanding is that because packs does not relying on zeitwerk, the package boundaries can be placed anywhere in the project directory
The answer is the last part of @AlexEvanczuk comment. Packwerk, through zeitwerk, is limited to detecting autoloaded constants. As packs parses files directly (at least with the experimental parsers), it doesn’t care whether constants are autoloaded and so it can detect things in more files as Alex is exploiting for the monkey patch detection system: https://rubymod.slack.com/archives/C05EWU4EPEK/p1689354454141669
I created a new rails app to experiment with both packs and packwerk. I created a few different package ymls to test violations.
I’ve created a scenario in which packwerk reports 2 violations but packs only finds one of them. I wasn’t sure if i’m misusing/miss-configured or if this is not the intended behavior.
Can you try cargo install pks to update the library and rerun it?
If you have a repo containing the example app that’d be super helpful for debugging appreciate the feedback and helping me iron out the edge cases. There are some cases where globs (in packwerk.yml) evaluate differently in ruby vs rust – could be that.
I think it may actually be related to you having custom load paths. The regular packs parser assumes you have mini rails apps under each package. Eg path/to/pack/app/models/foo.rb. The experimental parser doesn’t assume anything about load paths (it just parses files for constant definitions directly).
reinstalled and same result. experimental parser actually says nothing is wrong
~/Desktop/components main ✗ ❯ packs check -- --experimental-parser
No violations detected!
I’ll upload this repo somewhere and share it. I was playing around with it more, so the current state has a few more violations than the screenshot above but the the number of violations still differs between packwerk and packs
I was able to clone the repo. That’s my bad, I put the flag in the wrong place in the command I suggested you use :man-facepalming: , sorry about that. Try this:
~/workspace/components - (main) $ ../pks/target/release/pks --experimental-parser check
next/apps/edu/web/models/school.rb:2:2
Dependency violation: `::One::Foo` belongs to `app/models/one`, but `next/apps/edu/package.yml` does not specify a dependency on `app/models/one`.
next/apps/admin/domain/lib/next/admin/dataconcat/commands/base_command.rb:11:2
Dependency violation: `::One::Foo` belongs to `app/models/one`, but `next/apps/admin/package.yml` does not specify a dependency on `app/models/one`.
2 violation(s) detected:
Error: "Packwerk check failed"
~/workspace/components - (main) $ ../pks/target/release/pks check -- --experimental-parser
No violations detected!
yup, that command works. There is still a mismatch in the number of violations between packwerk and packs. And this message at the end of pack’s output Error: "Packwerk check failed"
I noticed that packs does see the admin package yml, but doesn’t seem to have the Admin constant in it’s definitions
~/Desktop/components main ❯ packs list-packs
/Users/tim/Desktop/components/next/apps/admin/package.yml
/Users/tim/Desktop/components/app/models/one/package.yml
/Users/tim/Desktop/components/app/models/two/package.yml
/Users/tim/Desktop/components/next/apps/edu/package.yml
/Users/tim/Desktop/components/package.yml
~/Desktop/components main ❯ packs list-definitions
"::ApplicationHelper" is defined at "app/helpers/application_helper.rb"
"::ApplicationMailer" is defined at "app/mailers/application_mailer.rb"
"::ApplicationJob" is defined at "app/jobs/application_job.rb"
"::Hotel" is defined at "app/models/hotel.rb"
"::One::Foo" is defined at "app/models/one/foo.rb"
"::ApplicationController" is defined at "app/controllers/application_controller.rb"
"::Two::Bar" is defined at "app/models/two/bar.rb"
"::ApplicationCable::Connection" is defined at "app/channels/application_cable/connection.rb"
"::ApplicationCable::Channel" is defined at "app/channels/application_cable/channel.rb"
"::Hotel::Pricing" is defined at "app/models/hotel/pricing.rb"
"::ApplicationRecord" is defined at "app/models/application_record.rb"