-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
feat!: make all settings mergeable #4982
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
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
|
cc @paul-soporan in case this overlaps with the work you are doing related to config I think |
baa3ff8 to
0a4f244
Compare
|
I think I haven't been clear enough on the original issue, sorry 😅 When I said having a It'd work the same for arrays: I'd assume that array contents aren't merged, since I don't see any way to do it in a clean way: This way, we wouldn't have to change the public API at all, and users would be able to define whether they want to override settings straight from their setting file. Does that make sense? |
I've thought about it, but I'm worried I'm going in the wrong direction 🙈. I think all of yarn settings can be [1] type Value = unknown; // Depends on `SettingsType`;
interface ConfigurationValue = Value | {
value: Value;
strategy: 'extend' | 'reset'; // default is `extend`
}this is similar to the current plugin definition (String | Shape) and does not conflict with the new parser.
I think so too, this PR currently works like this 🚀
I can remove the
yes! I think so. if [1] + [2] is OK, that way I think the changes requested in this comment should be easy. |
1bab4dc to
1081a77
Compare
|
@arcanis can you take a look at this new test? It shows the way my last comment said 🥸 but this will make I may also reverse the order in which rcfiles are read, currently it reads from child directory to parent directory, however, this will result in the parent directory's rcfile having more weight when multiple rcfiles have a "reset" strategy on the same field. |
1081a77 to
b5fe0ad
Compare
| value: { | ||
| number: 22, | ||
| string: `bar2`, | ||
| }, | ||
| strategy: `reset`, |
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.
nit: not a fan of strategy: reset, the "strategy" here doesn't look super clear to me ... onConflict: reset, maybe? 🤔
And do we need the value field? Perhaps we could just use the remaining keys as the proper object; it would allow to remove an indentation level if someone wanted to use onConflict: reset at the top-level to disable the yarnrc inheritance altogether:
onConflict: reset
npmRegistryServer:
# ...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.
And do we need the value field? Perhaps we could just use the remaining keys as the proper object
I think your method will make the configuration easier, but I'm not sure how this works in ARRAY and SINGLEVALUE, would you be willing to tell me more 🙏?
onConflict: "xxx"
// MAP & SHAPE
packageExtensions:
onConflict: "xxx"
gatsby-cli@*:
onConflict: "xxx"
peerDependencies:
onConflict: "xxx"
eslint: "*"
gatsby: "*"
// ARRAY
🤔
// SINGLE VALUE (string, number, boolean)
🤔
/*
(Currently, if a single value has the `reset' option, it will still overwrite the original value,
even if `useWithSource.opts.overwrite === false`, but this may be an overdesign 🧐.)
*/
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.
Yes, in the case of array we'd probably need to have a value field, I don't see a clear way to avoid it there... 🤔
It's a first iteration anyway, we can improve that later on if we find a prettier syntax
(Currently, if a single value has the
resetoption, it will still overwrite the original value, even ifuseWithSource.opts.overwrite === false, but this may be an overdesign 🧐.)
Looking at its usage, we probably should remove useWithSource.opts.overwrite entirely, and replace it by adding onConflict: reset to all the places that used it.
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.
These days I have done some things
-
reverse the read order of rcfile 7dae8d7
-
I removed
useWithSource.opts.overwriteandBaseSettingsDefinition.concatenateValues(It doesn't seem to matter much, and it doesn't seem to work withoutoverwrite🧐) -
I implemented
onConflictand it now has three behaviorsextend(default)
attempt to merge or overwrite(reset)
reset
overwrite a field whether it has a value or not
skip
if the value already exists in the field, it will not be parsed
- I modified the test to cover the
onConflictbehavior
948c5be
updated:
currently the plugins field is not supported using onConflict, because its process is different from other field.
b5fe0ad to
cc836f6
Compare
cc836f6 to
948c5be
Compare
This comment was marked as resolved.
This comment was marked as resolved.
|
I fixed it and now ready for review 🤡 adc7ff0 |
…or "configuration".
…concatenateValues`
adc7ff0 to
e04eb19
Compare
|
I made a couple of changes:
Generally I'm a little worried of the implementation complexity, and especially that it's interlaced with the rest of the configuration parser. If the tests pass we can land it as-is, but I think it could make sense to potentially revisit this part later and extract the merging logic as a separate pass, before the settings are interpreted. In pseudo-code, something like: const rcFiles = getAllRcFiles();
const rcFilesWithoutOnConflict = resolveOnConflictFields(rcFiles);
configuration.use(rcFilesWithoutOnConflict);This way the In any case, let's see how the tests go! |
|
I fixed a test, but a failing one remains - my understanding is that the code here is problematic: berry/packages/yarnpkg-core/sources/Configuration.ts Lines 685 to 694 in 32772b5
That's because it makes the configuration think that If you can take a look (either to hotfix this, or to look at changing the implementation to be closer from a preprocessor, as I suggested in the previous post) it'd be great! |
|
No problem ~ there is still enough time before the official release of Yarn 4, so I don't mind spending more time if I can make it better 😀. |
cbc26ec to
ebd9e72
Compare
ebd9e72 to
dfc6865
Compare
dfc6865 to
6e8c1ac
Compare
|
arcanis
left a comment
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.
Looks generally good to me, although I'll wait for @RDIL to make a review pass as well since he asked to do it - two nice potential follow ups (for subsequent PRs, I think it's fine to land this one as-is and improve incrementally):
- Rework the
RESOLVED_RC_FILEmarker so that it isn't needed - Make
Configuration#useaccept onConflict markers
| export function getValue(value: unknown) { | ||
| return isResolvedRcFile(value) ? value[1] : value; | ||
| } | ||
|
|
||
| export function getSource(value: unknown) { | ||
| return isResolvedRcFile(value) ? value[0] : null; | ||
| } |
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'm not a fan of this pattern - I'd prefer if the manipulated were always of a consistent type, even if it requires normalizing them beforehand.
|
Thank you @jj811208, this is great! |
What's the problem this PR addresses?
related: #3591
closes #4341
closes #2106
...
How did you fix it?
define a new parameter
resetforuseWithSourceI put the
configuration.useoptsinto theparseXxxfamily of functions so that themergeandoverwriteandresetactions work throughout the configuration treeby the above three points, make
shape,map,arraymergeable in depth 0f9a52eI added some tests to verify that I didn't break anything f816430
current behavior
opts.overwrite
if true, overwrite currentValue with the new calculated value
opts.reset
if true, currentValue will always be
undefined| empty map | empty array...
Checklist