-
Notifications
You must be signed in to change notification settings - Fork 383
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
Enhancement: recursively npm install on all pushed node_modules #11
Conversation
Hey dondeli! Thanks for submitting this pull request! I'm here to inform the recipients of the pull request that you've already signed the CLA. |
We have created an issue in Pivotal Tracker to manage this. You can view the current status of your issue at: https://www.pivotaltracker.com/story/show/82643910. |
Hi guys, this is a nice-looking patch. Are you able to add a fixture app and test case? An ongoing concern for us is that we could change behaviour for other applications that don't follow this pattern. And, if we take this PR, that we don't have any regressions in behaviour. |
@adrai can you add a fixture app and test case? |
Hi all. I'm also a member of the buildpacks team and I just discussed this with Jacques. We cannot fairly expect you to create a running and passing test for this work. The test environment and suite are difficult to set up and operate. We are working on making it easier to use, but for now we would be really happy with:
We'll take that and formalize it as a test suite and ensure the tests are passing before committing the work to master. Thanks again! |
I used https://github.com/adrai/cf-node-deploy-example to test it... |
the app provided by @adrai shows you in an easy way and with minimum outside dependencies the problem which is solved by this PR. |
We try to evaluate based on a successfully running app, that way we do
|
yes, it should crash... |
yes it crashes, just tested it out. |
Thanks for that. That's all we need for now. |
any planned date for merging this? |
There's a rough breakdown of our thoughts on the matching tracker story: https://www.pivotaltracker.com/n/projects/1042066/stories/82643910 The large comment by Jacques in that story are the notes from Him and I working this through. The binary compilation step might be our biggest hiccup, it may affect existing users in fact. Our main task on this team is to ensure that "online buildpacks" (Heroku buildpacks assume network connectivity) can also work in offline environments. Take the Ruby buildpack for example. Making it work in a network-starved environment is not a problem. Before pushing an app, dependencies are 'vendored' (stored along with the app itself) as source dependencies, then during staging (when the internet is out, but the system is on the target host) the vendored dependencies are installed, including any compilation steps. NPM does not offer such a mechanism (as far as we know), and this makes it hard for us to make binary dependencies work for Node. It might not be obvious why this is an issue, but with your pull request, you are 'vendoring' dependencies inside the compile script. Compile is run during staging, which may be in an internet disconnected environment. We need to ensure that this code would run and not try to access the internet. The recursive traversal your code introduces, makes it necessary for an 'offline' application developer to install their dependencies recursively. So to use your code for people without binary dependency requirements, we need a tool or offering that installs dependencies recursively. Unfortunately, this almost-always leads to some binary dependencies being compiled, which are then not compiled on the target host, but locally. It is a quandary, and we are pulling in some clever minds from the node community within Pivotal to get some suggestions of least-worst scenarios. I'm of the opinion we will need a way to embed dependencies recursively on the local machine, and then recompile them recursively on the target machine. This way all the required source is installed before the app reaches staging. There's a lot of work to prove this will work. Additionally, this pull request means that we'll have modified code in our buildpack that may conflict with Heroku's. We merge from Heroku's buildpack to pick up their latest work, and we try to avoid merge conflicts and test coverage problems. Once we have a solution that works for offline users, we may want to get Heroku to accept it as a PR. We're still actively investigating this and will respond back shortly. |
Hi guys; Sorry for being quiet again for so long. We've asked another pivot to jump in to help us review this PR, we hope to get some word on it soon. Cheers, JC. |
Hi, I'm the other Pivot. I have had a quick look over this and realised it's not simple. I should get to reviewing this tomorrow afternoon (UK time) I hope. |
Apologies for taking longer to look at this than I had hoped. I've read through all the conversations now and I think I understand the problem this pull request is meant to solve, also why it conflicts with the concept of an offline buildpack. I work a lot with the Java buildpack but I'm not familiar with the changes made to support off-line mode in the Node buildpack and I haven't figured it out in the last hour. So I'll have to defer on what effect this change would have on things still working offline. I'm concerned that this essentially extends NPM functionality and if NPM decides to add better/different support for private or binary modules in the future then we will have diverged and could end up having to break backwards compatibility for Node apps on CF. I think this is also likely as 'node_modules' as an abstraction isn't intended to be modified outside if an NPM command. Given your problem, which I think is fairly reasonable for a real Node project, one solution is a private NPM repository. This has already been discussed, aside from the hassle of setting one up I think we could do more to support authentication against private repos in the buildpack. Private repos are better for an entire organisation with multiple Node projects going on, it's really too much for a single project. That's an issue for another day though. I've forked your sample app and made some changes to allow private modules to be used and automatically installed by NPM by using local file paths in the package.json file. I've also set it back to the default buildpack. Have your Grunt task copy your own modules to a new 'private_modules' directory in each app instead of the 'node_modules' directory. This approach should work in the offline case as well, once 'vendored' appropriately. It's easier to understand by looking at it, especially all the package.json files. See https://github.com/cgfrost/cf-node-deploy-example I'm following this issue now and I'll try to respond a little quicker now I'm up to speed. Let me know if you have any issues with the approach I've suggested. I've looked at the problem of structuring larger Node projects before and there is definitely a lack of best practice out there but it must be doable considering how many big Node projects there are. Thanks, Chris. As a side note, please don't use 'command' in your manifest to start an application, this functionality could be removed from all CF buildpacks at some time in the future. For a Node application it's recommended to use the NPM start script, I made this change in the sample app as well. |
The problem with this approach for us is that we use these private modules in multiple apps (for the same project) in this way we have to copy these private modules to each app... and this is not really nice when working locally... but I thank you for having investigated on this. |
...and... does these references in the package.json really work? What happens on npm install? |
Hi, NPM works just fine, it follows the file reference and installs what it finds to the local "_id": "own_a@1.0.0",
"_shasum": "b461cd55551eabe167d8beaf9befa7e31d42fa33",
"_from": "private_modules/own_a",
"_resolved": "file:private_modules/own_a" Sorry if I misunderstand, I believed your Grunt script is already copying these own/private modules round to all the separate apps in the project. Is this where you are using sym-links etc.., for local development. You could still use that approach for local dev, just sym-link in to the new Chris. |
I will try... so I assume an npm install will recursively npm install on own_a and in own_b Just one more question: is the dependency in own_a of own_b correct? ./private_modules/own_b |
Yes and yes. Local dependences are always resolved against the root of the project doing the resolving, regardless of where dependence is actually located. Chris. |
oh no... then this is a problem... I don't know who is using own_b (i.e. a logging module) It can be referenced and installed from everywhere... |
Hi guys, Based on our own research and @cgfrost 's additional review, I don't think we can accept this PR. I'm sorry it took so long to settle this matter, but we were determined to ensure that this change got a full and fair review. Cheers, JC. |
Is this really a practically solution? |
NPM & Package.json can be very flexible but it has it's limits. Once those limits have been reached the next step up is hosting a private repository. I realise that's a pain but that's the progression you have to make. FYI, here is the full doc for NPM local paths from
I'm sorry you haven't got the outcome you were looking for, I hope it doesn't hold you back too much. Chris. |
fyi: an other alternative could be to do this recursive stuff in a postInstall script |
ok i tested my last approach with a preinstall script... and it works... so if everything (all 20 apps) works this way we can use the standard nodejs-buildpack |
Based on #10 our new propose for a recursive npm install function.