Skip to content

javascript: Do not read none mapped package.json files in javascript rules#18523

Merged
stuhood merged 9 commits intopantsbuild:mainfrom
tobni:fix/do-not-read-none-mapped-package-json
Apr 3, 2023
Merged

javascript: Do not read none mapped package.json files in javascript rules#18523
stuhood merged 9 commits intopantsbuild:mainfrom
tobni:fix/do-not-read-none-mapped-package-json

Conversation

@tobni
Copy link
Contributor

@tobni tobni commented Mar 18, 2023

Consider the to-be-parsed TargetGeneratorRequests and read the associated package.json from globs before GenerateNodePackageTargets is consumed to produce GeneratedTargets. It needs to be done like this to avoid a circular rule dependency that stems from WrappedTarget being used to validate addresses, and _TargetParametrizations being an integral part of this validation (I think?).

This is an attempt at fixing point 1. of the weirdness observed in #18326 (comment).

I also took some liberties in refactoring resolve_target_parametrizations, because I struggled to navigate it. It does mean more @rules in the graph module though, I dont know if that is a metric to be weary of?

@tobni tobni changed the title javscript: Do not read none mapped package.json files in javascript rules javascript: Do not read none mapped package.json files in javascript rules Mar 18, 2023
@tobni
Copy link
Contributor Author

tobni commented Mar 18, 2023

@stuhood Not sure if the issue warrants this change, but I think something like this is what is required to fix the "only read mapped package.json's", while avoiding the rule dependency cycle.

@benjyw benjyw requested review from stuhood and sureshjoshi April 1, 2023 03:23
@benjyw
Copy link
Contributor

benjyw commented Apr 1, 2023

@stuhood can you take a look at the refactoring here?

@tobni I think it would be best to separate the refactoring from the JS backend changes, in case we have to roll one back, and to make it easier to review.

Copy link
Member

@stuhood stuhood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot: this looks solid. As to @rule count: it does matter slightly, in that if something has exactly one consumer, it generally makes sense to either:

  1. inline it into the consumer
  2. use an async function (formerly known as @rule_helper) instead, which is treated as a plain function call rather than a memoization boundary / trampoline.

But I think that if you make the suggested edit, this change will be good to go.

Sorry for the long delay on review: my only excuse is that your comment suggested that you weren't sure that it should land, but having reviewed it, it looks very reasonable.

Comment on lines 380 to 383
@rule
async def _target_generator_overrides(
req: _TargetGeneratorOverridesRequest, unmatched_build_file_globs: UnmatchedBuildFileGlobs
) -> _Overrides:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this doesn't need to be independently memoized AFAICT, rather than a @rule it should probably be a just an async function (née @rule_helper), which would avoid needing to define the argument and return type wrappers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I seem to (to me at least) arbitrarily hit

native_engine.IntrinsicError: Get(Paths, PathGlobs, PathGlobs(globs=('demo/f1.ext',), glob_match_error_behavior=<GlobMatchErrorBehavior.warn: 'warn'>, conjunction=<GlobExpansionConjunction.any_match: 'any_match'>, description_of_origin='the `overrides` field for demo:demo')) was not detected in your @rule body at rule compile time. Was the `Get` constructor called in a separate function, or perhaps dynamically? If so, it must be inlined into the @rule body.

when switching to a rule helper (just regular async function) here?

Copy link
Contributor Author

@tobni tobni Apr 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is MultiGet different from Get in this instance?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm... it shouldn't be? cc @kaos

Copy link
Contributor Author

@tobni tobni Apr 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can push the patch so you can see the edit.

Edit:
0b36a0e

yep, CI agrees

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that does work!

Copy link
Contributor Author

@tobni tobni Apr 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this worth adding to the "probable issue" bit of the error?

This bit:

Was the `Get` constructor called in a separate function, or perhaps dynamically? If so, it must be inlined into the @rule body.

?

Copy link
Contributor Author

@tobni tobni Apr 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, considering your suggestions, that error seems not correct in any sense? The Get in the helper in question is dynamic (if-clause) afaict?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, for sure: that message hasn't been updated since rule helpers became supported.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened #18663, not sure about the wording but imo still better than current state 🤷‍♂️

@@ -490,7 +495,28 @@ async def read_package_jsons(globs: PathGlobs) -> PackageJsonForGlobs:

@rule
async def all_package_json() -> AllPackageJson:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to add a note here that explains why this avoids using the more obvious APIs.

@stuhood stuhood added the category:bugfix Bug fixes for released features label Apr 3, 2023
tobni added 7 commits April 3, 2023 21:10
A bit hacky, considering the validation layers are skipped,
but also quite safe, as the rule requires the files to exist,
by virtue of it trying to read them.

This also discovered a little faulty test setups with
missing BUILD files 🎉
@tobni tobni force-pushed the fix/do-not-read-none-mapped-package-json branch from 4209064 to 0b36a0e Compare April 3, 2023 19:48
@stuhood stuhood enabled auto-merge (squash) April 3, 2023 22:47
@stuhood stuhood merged commit 9046bb7 into pantsbuild:main Apr 3, 2023
@tobni tobni deleted the fix/do-not-read-none-mapped-package-json branch May 16, 2023 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category:bugfix Bug fixes for released features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants