-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Focused Workspaces RFC Implementation #5663
Conversation
const exoticResolver = getExoticResolver(this.pattern); | ||
if (exoticResolver) { | ||
return this.findExoticVersionInfo(exoticResolver, this.pattern); | ||
} else if (WorkspaceResolver.isWorkspace(this.pattern, this.resolver.workspaceLayout)) { | ||
invariant(this.resolver.workspaceLayout, 'expected workspaceLayout'); | ||
const resolver = new WorkspaceResolver(this, this.pattern, this.resolver.workspaceLayout); | ||
return resolver.resolve(); | ||
let manifest; |
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.
workspaces were never downloaded from the registry before before, so i had to add that here.
|
src/package-hoister.js
Outdated
@@ -649,6 +658,81 @@ export default class PackageHoister { | |||
} | |||
} | |||
|
|||
markShallowWorkspaceEntries(){ |
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 is where the main logic is happening.
src/package-hoister.js
Outdated
if(splitPath[0] !== w){ //entry is not related to the workspace | ||
return false; | ||
} | ||
if(!splitPath[1]){ //entry is the workspace |
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.
all sibling workspaces are shallow dependencies
src/package-hoister.js
Outdated
if(!splitPath[1]){ //entry is the workspace | ||
return true; | ||
} | ||
//don't bother marking dev dependencies for shallow installation |
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 for any dependencies the sibling workspaces already install shallowly (due to version conflicts with the hoisted version) and marks those for shallow installation.
src/package-hoister.js
Outdated
info.shallowPaths = ['']; | ||
return; | ||
} | ||
|
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.
Finally, it looks for packages that are normally hoisted but need to be shallowly installed underneath a sibling workspace because the target has its own version, and marks those for shallow installation (but not just directly under node_modules like the other ones)
src/package-hoister.js
Outdated
if (this.config.modulesFolder) { | ||
// remove the first part which will be the folder name and replace it with a | ||
// hardcoded modules folder | ||
parts.splice(0, 1, this.config.modulesFolder); | ||
} else { | ||
// first part will be the registry-specific module folder | ||
parts.splice(0, 0, this.config.lockfileFolder); | ||
if(info.shallowPaths){ |
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.
add any packages marked for shallow installation to the main output tree
I updated my original comment because I addressed a bunch of the incomplete things I originally mentioned. |
@@ -399,14 +399,10 @@ export default class Config { | |||
* Generate an absolute module path. | |||
*/ | |||
|
|||
generateHardModulePath(pkg: ?PackageReference, ignoreLocation?: ?boolean): string { | |||
generateModuleCachePath(pkg: ?PackageReference): string { |
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 was kind of being used for 2 different purposes. I removed the part about getting the path to node_modules because that was kind of broken anyway (A package can be installed to more than one location). Instead the code that relied on location being set uses the packagereference directly.
src/package-reference.js
Outdated
resolver: PackageResolver; | ||
|
||
setFresh(fresh: boolean) { | ||
this.fresh = fresh; | ||
} | ||
|
||
setLocation(loc: string): string { | ||
return (this.location = loc); | ||
addLocation(loc: string): string { |
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.
a package can have more than one location. For example, 3 workspaces depend on foo@2.0.0, and 2 workspaces depend on foo@1.0.0. foo@1.0.0 will be installed under both workspaces to avoid the conflict with the hoisted v2.
This was causing a bug where .bin links pointing to foo@1.0.0 would all point to a single copy of it, rather than each one pointing to the one installed for that package (the one it will actually use).
I also think if foo@1.0.0 has a postinstall script, it would only have run on one instance, but I never verified that. It shouldn't do that either way now though.
registryRemote = downloadedManifest._remote; | ||
hash = registryRemote.hash; | ||
//override any local changes to manifest | ||
Object.keys(manifest).forEach(k => k.startsWith('_') || delete manifest[k]); |
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 was to avoid weird bugs where the local package.json differed from the remote one (for the same version).
d98bc27
to
9bb3101
Compare
@bestander any thoughts on this implementation? (Or do you have anyone else you think should weigh in?). I'm getting close to having something that is complete and would like to know sooner rather than later if there are any major implementation issues. Thanks! |
@bdwain, great job taking it to a working solution! Half of it is a no-brainer, half of it need thinking like changing package-reference interface. I’ve scrolled through the code, are all these changes necessary for the feature or is it some refactoring that could be on its own? |
Thanks @bestander. I think all of the changes are necessary. They were all done to fix one edge case or another. Can you comment on the specific ones you’re concerned about? I'd be happy to explain any of them. For the package reference interface, I changed it to multiple locations because without that, the top level symlink of a workspace and the shallow installation would have the same location, and so any .bin links pointing to that package would both point to the location (which ended up being the one whose path ended up last alphabetically). This also caused similar issues with not running post install scripts on all of the installations. this also fixed what I feel was incorrect behavior from before in the scenario where a package was installed in multiple locations (if it couldn’t be hoisted due to another version being hoisted). In that case, all of the unhoisted versions would point to the same location, so for example, workspace b’s bin link for foo might point to workspace a’s installation of foo becuse they had the same location. And similar issues for running all post install scripts. I looked around and feel pretty confident that the change caused no unintended side effects. But if I misssd one id be happy to address it. But I do think the change is needed now since focused workspaces make it more likely to have multiple installations of a package and for those installations to be different. |
@@ -117,6 +117,7 @@ | |||
"release-branch": "./scripts/release-branch.sh", | |||
"test": "yarn lint && yarn test-only", | |||
"test-only": "node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose", | |||
"test-only-debug": "node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose", |
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 can remove this if needed but i found it very useful
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 all right to me
registryRemote = downloadedManifest._remote; | ||
invariant(registryRemote, 'missing remote info'); | ||
hash = registryRemote.hash; | ||
//override any local changes to manifest |
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 is related to the comment here.
also FYI i have all old unit tests passing, so besides addressing any PR comments, the only thing left is to add in new unit tests for the focus functionality |
I think I'm going to need to create a test repo with some workspaces in it for some new unit tests. I'll create it under my account for now, but would it make sense to move to the yarnpkg account so other people can edit it easily in the future if needed? |
@@ -33,6 +33,16 @@ test.concurrent('--verify-tree should report wrong version', async (): Promise<v | |||
expect(thrown).toEqual(true); | |||
}); | |||
|
|||
test.concurrent('--verify-tree should work from a workspace cwd', async (): Promise<void> => { |
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 made the change in check.js so that this test would pass. I needed it to work correctly for the new focus tests to work (or I could have avoided the check at the end of the install and be different from other install tests, but that felt wrong)
Looks reasonable so far. |
c6df2ae
to
c5a07cf
Compare
@bestander i think this is just about ready to go. The unit tests are all there. I did also make some changes to the main logic to fix some edge cases I missed in this commit if you want to see the differences.
EDIT: Ignore that last thing. idk if it was actually used anywhere. Are babel-polyfill methods just not available to use for yarn?
Thanks! |
74f7c4f
to
69c7639
Compare
@bestander the issues i mentioned above are fixed. So I've got nothing left to do except address PR comments. |
also if it's helpful, i can transfer my example repo and the associated npm packages (which I needed to make for the tests I added) to yarn so people can edit them if needed in the future. |
9665041
to
c3e674f
Compare
Thanks Bryan.
Sorry I’ve been phased out for a week, will review shortly
…On Sun, Apr 29, 2018 at 7:07 PM Bryan Wain ***@***.***> wrote:
also if it's helpful, i can transfer my example repo
<https://github.com/bdwain/example-yarn-workspaces> and the associated
npm packages (which I needed to make for the tests I added) to yarn so
people can edit them if needed in the future.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#5663 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ACBdWIe3GMQ6JbQcHvIx_DSFYLtqLhDCks5ttnHdgaJpZM4TS7__>
.
|
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.
Awesome work, @bdwain!
Thank you for your dedication and the effort you've made to add tests and consider the edge cases.
I don't have any concerns about this.
Here is what we do next:
- Wait for @arcanis approval to make sure this feature doesn't interfere with any features already in the works
- Merge this PR
- We'll need a blogpost https://yarnpkg.com/blog/ about this new feature! :)
Sounds great! Thanks! I can work on a blog post. Should I just make a pr to https://github.com/yarnpkg/website/tree/master/_posts ? One other question is what will the process be to release this once all 3 of those steps are done? It's not a breaking change so can it just go out in v 1.7 or whatever the next minor release is? |
Hey @bdwain! Thanks for submitting the PR! I'll look at it tomorrow and come back to you 👍 |
Yep, that would be perfect!
If there's no breaking change it should be fine in a minor :) |
d61f100
to
4c10f09
Compare
Hi @arcanis Please let me know if there's anything else you need before you look at this. I was holding off on finalizing the blog post until it was merged because if anything changes I didn't want to have to change it. Thanks! |
@bdwain, great job on this, sorry for a delay, we are all heads down working on specific projects. |
Is blog post ready? I'll be happy to spread the word |
thanks! It's not ready yet. I'll try to have it ready in the next day or so. |
Noticed what I think is a bug, I opened #5967 to discuss it 🙂 |
@bdwain Will a blog post for this still be written or has this stalled? I'm having a hard time discerning whether this has actually been released/published or not. Thanks! |
yup it was released already! https://yarnpkg.com/blog/2018/05/18/focused-workspaces/ |
Thanks for the link! That's helpful. Now I see that this feature didn't take the path I was looking for. I was hoping for something more along the lines of #4207. In my case, I'm not looking to install packages from the registry. I just want a trimmed down My reasoning is that I have an app that is in a monorepo. But on the CI server, we build it and need to zip it up along with it's 👍 |
I see. I think focused workspaces was attempting to solve a different problem. But yarn plug'n'play seems like it may help you solve your issues. |
I'm in the same boat, I thought this could solve our problems with package isolation while creating docker images for example. |
UPDATE: This is complete and ready for final review.
I've been working on an implementation of the focused workspaces RFC. It's not complete yet, but it mostly works so I was hoping to get some feedback as i try to get the last few things working to make sure my implementation makes sense.
All of the details of what it does and the edge cases are in the RFC link above, so I won't explain any of that here. I was just hoping to get general high level feedback on my approach. Most importantly, I was hoping for feedback on was how I used the hoisted tree result (from package-hoister) to calculate which packages need to be shallowly installed inside the target workspace and where. I'll comment inline to point out where that is.
FYI I haven't written any unit tests yet. I'm beginning work on those now. But I wanted to post this early to get feedback in case there are any major issues with my implementation.
Sorry in advance if there's a better place to do this (like a development chat or something). This is my first big yarn change so I wasn't sure what the normal process was.
Thanks!
cc @bestander