-
Notifications
You must be signed in to change notification settings - Fork 113
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
Fix CLI init by defining default load path value #77
Conversation
Note, CLA has been signed. Tried reopening the PR to trigger a re-check of CLA status, but no luck.. |
This change looks good to me 👍 Thank you for fixing the issue. |
The Configuration class recently stopped inferring a set of load paths unless packwerk.yml file specified one: For non-Rails applications, your change reinstates the previous behaviour of setting As for Rails applications, I think only the ApplicationValidator class will notice that Configuration#load_paths is inconsistent with Rails' own load paths: packwerk/lib/packwerk/application_validator.rb Lines 50 to 63 in 88526cc
I think your change is a step in the right direction, @mikelkew . Do you have anything to add, @wildmaples ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the proposed solution in this PR is correct. By adding this change, we are not generating any load_paths for packwerk init
. Instead it will just return an empty list. The correct behaviour is to get a list of load paths through Rails, and populate the configuration file.
We'll have to change the load path argument on this line:
Line 92 in 1489086
load_paths: @configuration.load_paths, |
ApplicationLoadPaths#extract_relevant_paths
method.
132cfa7
to
b9844f7
Compare
Thanks @wildmaples, I had a suspicion that might be the desired behaviour. I've just pushed b9844f7 to address it (keeping the PR as a single commit as preferred). I've intentionally kept the empty array as a fallback for |
Calling packwerk/lib/packwerk/application_load_paths.rb Lines 12 to 23 in 88526cc
Somewhere in the generate configs logic, we're missing this pseudocode generated_load_paths = rails_app? ? ApplicationLoadPaths.extract_relevant_paths : [] Solution 1The Solution 2The CLI should not be in the business of implementing the decision modeled in the pseudocode. But there is precedent for calling a generator with a Lines 80 to 87 in 88526cc
Say we passed the same hint into # lib/packwerk/cli.rb
Packwerk::Generators::ConfigurationFile.generate(
for_rails_app: rails_app?,
root: @configuration.root_path,
out: @out
)
# lib/packwerk/generators/configuration_file.rb
class << self
def generate(for_rails_app:, root:, out:)
new(for_rails_app: for_rails_app, root: root, out: out).generate
end
end
def initialize(for_rails_app:, root:, out: $stdout)
@for_rails_app = for_rails_app
@root = root
@out = out
set_template_variables
end
def load_paths
@load_paths ||= @for_rails_app ? Packwerk::ApplicationLoadPaths.extract_relevant_paths : []
end
def set_template_variables
@load_paths_formatted = if load_paths.empty?
"# load_paths:\n# - 'app/models'\n"
else
load_paths.map { |path| "- #{path}\n" }.join
end
@load_paths_comment = unless load_paths.empty?
"# These load paths were auto generated by Packwerk.\nload_paths:\n"
end
end I have a preference for the first solution. |
b9844f7
to
a8e626d
Compare
Thanks for catching that @rochlefebvre. I've gone with your first suggestion, both for simplicity, and because it matches the behaviour for non-rails apps that was in place before #68 was merged. |
@@ -10,18 +10,14 @@ class << self | |||
|
|||
sig { returns(T::Array[String]) } | |||
def extract_relevant_paths | |||
assert_application_booted | |||
return [] unless defined?(::Rails) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to return []
outside this class instead of in this early return?
defined?(::Rails)
is really misleading because it (almost) always this will be true, as Packwerk itself has Rails and will fall back to that. This is a known "bug". I am not sure why we even still have this check. @exterm @tomstuart
In the case where defined?(::Rails)
works the way we intend it too though:
In the context of ApplicationLoadPaths
, we would still want to raise if Rails is not defined because the point of the class is to get the Rails load paths. Returning an empty array would be misleading users to the actual functionality / API of this class.
TL;DR: We should not return empty array here but instead outside of this class, as it would be misleading to the functionality of this class. We should also keep the raise instead of failing silently because this class won't get its intended functionality if we don't have Rails defined.
edit: ignore my comments about Rails not being defined, that check works 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per my latest comment, we can just leave this class as is and come back to add the Rails loading logic in another PR. When that is added, we won't have to raise when Rails is not defined, and just return an empty array as you proposed here.
We could make the change now and return an empty array, but it would be hiding the fact that Rails should be defined/loaded but is not.
Unless someone has strong opinions, I say we keep the raise until we can make that change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, thanks @wildmaples, implemented in fe1697e
If we want to avoid raising for non-rails apps in the meantime, then I could implement the second suggestion from @rochlefebvre instead. But if the PR for the Rails logic is going to be worked on sooner rather than later, perhaps the raise isn't too much of a concern for now.
I had a chat with @rafaelfranca There are two bugs here: the first is solved by this line of change. The second issue is that We previously had I will add an issue for this sometime tomorrow. In the meantime, I think the appropriate change is the line I linked above. |
`ConfigurationFile#initialize` is expecting an Array value for `load_paths`, yet when called via the `packwerk init` CLI command, it was being passed as `nil` and thus throwing a Sorbet type violation. This restores the prior behaviour of loading the application load paths to pass to the configuration file generator. I'm also providing an empty array as a fallback for `load_paths` when loading a configuration file. This is expected to be an array elsewhere, so this covers us if the config file doesn't have it defined.
a8e626d
to
fe1697e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR addresses the Sorbet violation when initializing a ConfigurationFile, at least within a Rails app. It breaks packwerk init
and packwerk generate_configs
for non-Rails applications, now that Packwerk::Generators::ConfigurationFile.generate_configs
relies on ApplicationLoadPaths
. We intend to track and fix that in a separate issue/PR.
Having Configuration return []
unless provided some load_paths prevents a NoMethodError in ApplicationValidator#check_autoload_path_cache
, even if the check itself will fail, as designed.
Just stumbled upon this as I've just tried to install on a brand new Rails app and got the same error, is this going to be merged soon / tagged to fix the issue? As currently it's impossible (I think) to install Packwerk on any Rails app 😬 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Thanks, @mikelkew
What are you trying to accomplish?
Resolves #76.
ConfigurationFile#initialize
is expecting an Array value forload_paths
, yet when called via thepackwerk init
CLI command, it was being passed asnil
and thus throwing a Sorbet type violation.What approach did you choose and why?
I've just provided an empty array as a fallback if no
load_paths
value is defined, which is the case when running the config generator. Seemed like the most logical solution and matches the approach used forcustom_associations
.What should reviewers focus on?
I assume an empty array is the desired fallback here, although I guess
ApplicationLoadPaths.extract_relevant_paths
could also be an option.Type of Change
Additional Release Notes
Checklist