Skip to content
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

Installing both grunt-cli and grunt globally #10

Closed
wesleytodd opened this issue Feb 9, 2013 · 42 comments
Closed

Installing both grunt-cli and grunt globally #10

wesleytodd opened this issue Feb 9, 2013 · 42 comments

Comments

@wesleytodd
Copy link

I ran into an issue while trying to get grunt v0.4.0rc7 working globally. I understand that best practice is to include grunt locally to a project, and normally do. But in this particular situation it makes more sense to install it globally.

The steps I have taken so far are as follows:

sudo npm install -g grunt-cli
sudo npm install -g grunt@0.4.0rc7

I have a Gruntfile.js in my project root with a basic test task that just prints "Works!". When I run grunt test it fails saying Fatal error: Unable to find local grunt.. I took a look at node/bin/grunt and logged the variable gruntpath inside the exit callback and it is an empty string. Also the exit code is 11, not 0. But if I replace all the logic for loading the cli module like:

require(require.resolve("grunt")).cli();

Everything works fine.

So am I missing something? Is this just a fancy way of enforcing best practices and making people include grunt locally to a project?

@cowboy
Copy link
Member

cowboy commented Feb 9, 2013

There's no valid use-case, afaik, for installing grunt 0.4.x globally. Can you elaborate?

@wesleytodd
Copy link
Author

We have a team of +10 developers (3 front-end, 7 PHP) who are working on 8-12 projects at once in different stages of development. We would like to roll grunt into our process without causing to many time costing changes in process. Mainly, we dont want everyone to have to run npm install multiple times a day as they work on project after project. Especially since every project is basically built from a boilerplate, so they will not need different javascript dependencies on the server. Really it is just going to be grunt and a few grunt plugins. And lastly, none of the grunt tasks will be run on production servers because we deploy to too many different configurations to depend on using node post development.

I would say this is a valid use case, but please, if you have a better way I am all ears!!

@cowboy
Copy link
Member

cowboy commented Feb 9, 2013

You could install grunt locally somewhere and then just symlink the Gruntfile, package.json and created node_modules directory into each project's root directory.

Maybe (this is untested) you could put package.json in a shared parent directory of all the projects, and run npm install there. Then, project-specific Gruntfiles might just work. I haven't tried this, so I'm not sure it would work. But it's a cool idea!

The problem with global installs is that if, for some reason, you EVER wanted to work on another project that just happened to require a different version of grunt or a grunt plugin, you wouldn't be able to.

@cowboy cowboy closed this as completed Feb 9, 2013
@cowboy
Copy link
Member

cowboy commented Feb 9, 2013

Also, FWIW, running "npm install" before working on a project that uses npm modules is a) very easy to do and b) a standard way of developing projects that have npm dependencies.

@wesleytodd
Copy link
Author

You could install grunt locally somewhere and then just symlink the Gruntfile, package.json and created node_modules directory into each project's root directory.

I feel like I would rather ask them to run npm install than npm link since it is easier to understand what it is doing, but I see where you are going with this. I will explore this option and see if I can get something working like this.

The problem with global installs is that if, for some reason, you EVER wanted to work on another project that just happened to require a different version of grunt or a grunt plugin, you wouldn't be able to.

I completely understand and agree with the logic here, but really this is a PHP shop and I, as a front-end dev am the only person working with grunt, so I feel this is an acceptable risk for the simplicity.

Also, FWIW, running "npm install" before working on a project that uses npm modules is a) very easy to do and b) a standard way of developing projects that have npm dependencies.

Yeah, and I probably wouldn't mind if we didn't also have to run composer install and jam install...lol, too many installs.....Good thing I can write a grunt task for those ones....

Really my end goal was to demo the new process to the team and say:

"Look!! All you have to do is grab the repo and type grunt setup!!! How awesome is that??"

Which is what I can do if I have grunt installed globally....

@cowboy
Copy link
Member

cowboy commented Feb 9, 2013

Don't run npm link, that's something different. Create regular system symlinks.

@wesleytodd
Copy link
Author

Ok, yeah I see what you mean, that still makes a global install of the package....

@wesleytodd
Copy link
Author

If you dont mind, could you explain the logic behind requiring the module in the kind of round about way? Just so I can learn....

@wesleytodd
Copy link
Author

Hey Ben, I am sorry if it seems like I am pushing this issue, but I was not convinced that an answer came out of this.

So I setup a quick test server to mess with and followed exactly what I did above, then created two directories. One setup to use v0.4.0rc7 globally with a Gruntfile.js. In the other I ran npm install grunt and checked the version to be sure it was 0.3.17. I applied the change above to the global 0.4.0 install and tried things out.

While obviously since the local bin is not in my path, there is an error if I just try grunt test since it is using the global version but the simple solution is just that in a project that I know is running a different version of grunt, all I have to do is node_modules/grunt/bin/grunt test.

So it is not that you CANT run two versions of grunt, it is just slightly more difficult. This would solve the vast majority of my needs and seeing as anyone who would be doing this would know the ramifications of making such a decision, I dont see a reason to stop people from installing the package globally if they deem it necessary.

Thoughts?

@cowboy
Copy link
Member

cowboy commented Feb 9, 2013

There are a number of issues where we debated all this. While you can undoubtedly get this to work, installing grunt globally is not recommended and is not supported. CCing @tkellen because he might remember the issues where this was discussed.

@tkellen
Copy link
Member

tkellen commented Feb 9, 2013

I can respond to this more fully tomorrow, but I just wanted to respond to this right away:

"Look!! All you have to do is grab the repo and type grunt setup!!! How awesome is that??"

What you're looking for here is a post-checkout githook. You can configure these on your repo to run npm install, composer install, etc immediately after the repos are checked out. Once someone has done this once (at least in the case of npm) subsequent checkouts should be lighting fast since all the deps will be in your npm cache.

@cowboy
Copy link
Member

cowboy commented Feb 9, 2013

@tkellen it woud be awesome to have a page in the wiki where all you did was refute arguments people made about "needing" to install grunt globally.

@wesleytodd
Copy link
Author

Oh the world would be a wonderful place if all our projects were on Git. Unfortunately, we have over a hundred projects in SVN that will not be migrated any time soon. And I dont believe that SVN has a post checkout hook.

It's alright, I will let this rest and just tell my team they have to run two commands instead of one.

Thanks for your help and great work! Grunt is awesome!

@rawtaz
Copy link

rawtaz commented Mar 17, 2013

Hi. Just thought I'd chime in that I too would like to be able to install this globally (without having to symlink and what not). Grunt should run locally if there is a local install, and otherwise fall back to a global install. Different versions of Grunt is not an issue; The API will stabilize at some point and until then projects should be kept up to date anyway.

@suedama1756
Copy link

TBH, I'm slightly confused by this issue. There are statements regarding no good use case for global installation at the top of the discussion yet grunts own installation guide specifies the -g option (http://gruntjs.com/getting-started) and has since at least version 0.3.

I've always installed it locally (which has meant that simply typing grunt doesn't work, as its not added to the path), however, after trying to install the new 0.4 release locally nothing works (can't find grunt file or grunt)!! I'll be honest, I haven't looked into why much, but I would expect to be able to create a "build/tools/grunt" folder in my project, to install grunt and grunt-cli locally from that location, and for everything to work...

If global isn't the correct way, what is the correct local method (for a non-node based project).

@wesleytodd
Copy link
Author

Hey @suedama1756! I think you should take a look at the newer documentation. Now there is a package, grunt-cli, that is adds the command to your path. This should be installed globally. Then you install the grunt package locally.

Hope that helps.

@suedama1756
Copy link

Thanks, got there in the end (after finding the docs), but still find it just a little bit cumbersome. It's very fussy about where you run things from. Conceptually grunt is good, and its definetely heading in the right direction,most of my big gripes from 0.3 are resolved, and my custom tasks needed only one line changed! Just think it could be simpler, confuses the hell out of some people on my team....(maybe its just them :) )

@adamsmeat
Copy link

I'm fairly new to nodejs and I have a similar use case. Everything was fine as I installed globally grunt and grunt-contrib. Then using npm install --link for a project, the symlinks were created within the current project. But grunt chokes and does not recognize the symlinks and really wants everything within project namespace.

@shellscape
Copy link

I'll toss my hat in the ring for a valid use-case:

We're using nodeenv to assert an exact environment regardless of any of our developers individual machine environments. nodeenv very slickly manages any deps you want to specify and install (globally) within the environment. If I npm install -g grunt-cli, it'll be installed globally only running under that environment. Outside of that env it's like it was never installed. However, we have to install Grunt locally to the directory of whatever gruntfile we want to use the environment to run against. We can freeze our environment deps so that any updates or changes to the env require explicit intent, but don't have the same safeguard with local grunt. Additionally, we want to assert that grunt-cli in the environment is using the version of grunt installed in the environment, not a locally installed version of grunt,.If you've never used nodeenv before, this may seem like nonsense, but there's real world value to being able to run grunt-cli on a gruntfile, using a global grunt install.

In this particular use-case, a response of "symlink to the env grunt directory" would be akin to saying "hey that's a neat way to use it, but we're still not going to add the capability just because." We'd like to avoid that because it's unnecessary, and every other node module being used is quite happy residing in the environment's global node_modules directory.

@jamestomasino
Copy link

I'll second @shellscape on this one. There's also the fairly standard argument against hamstringing tools to a specific, expected workflow: if you let people do things in different ways it may create a new value to the tool that wasn't intended and benefit the greater community.

@LongLiveCHIEF
Copy link

👍 to @shellscape and @jamestomasino . And I'll add yet another usecase. I'm a developer in a company that employs at least 10,000 software developers. An organization of that size has security and legal standards in place to ensure software we've acquired meets our standards. This means we're blocked from using npm against a public registry (firewall), and with the interconnected dependencies of node modules, it's a virtual nightmare just to get approval for one package from npm.

Now, if I have say 10-20 packages I use on every project as part of my dev/build process, it's much easier to install those globally after I receive approval to download them. Sure... I could copy/paste the modules into each local project... but really what's the point, if they're the same version?

@jamestomasino
Copy link

@shellscape and @LongLiveCHIEF - I found a workaround for the time being. I parse out the package.json for dependencies, install them all globally, then link the global node_modules package back to your current directory via a simlink. Works fine for me in osx and ubuntu so far. Haven't tried it in Windows yet.

Here's the script. I'd love your feedback:
https://github.com/jamestomasino/grunt-boilerplate/blob/develop/setup_global

@LongLiveCHIEF
Copy link

@jamestomasino I only have this problem on my Windows machine at work, so I'll look at it and check it out from that context. Also, left a comment on that latest commit for that file, check that out. Thanks! 💯

@shama
Copy link
Member

shama commented Feb 3, 2014

-1 to all the comments in here. It is totally not Grunt's job to support bad company policies and bad development practices. Let's fix the mistakes node.js (and so many other tools) made and are stuck with. Let's not repeat them.

We can freeze our environment deps so that any updates or changes to the env require explicit intent, but don't have the same safeguard with local grunt.

This is precisely what installing locally does. nodeenv might have made sense a long time ago but it isn't necessary now days. Just install all dependencies locally.


If you really, absolutely must have global dependencies and would like to scoff at the recommendations of almost all experienced node.js developers... at least use npm link. It creates symlinks to a global folder: https://npmjs.org/doc/cli/npm-link.html

@LongLiveCHIEF
Copy link

@shama And that's why Node is more enterprise ready than grunt. You let 10,000 devs off the chain and let them specify deps at project-by-project basis, and you'll have trouble keeping your developers trained to support your production applications. And with a developer crew that large, you're talking a billion hits a year, with users in the 100 million range.

I love grunt. But when you abstract at that level, it's no longer a "bad company policy", it's a challenge worth millions of dollars. Allowing a simple configuration choice alleviates all of that, so why not just do it? Otherwise, it's only a matter of time until another js task runner comes along with a more comprehensive model, (probably created by someone like my primary employer), and then Grunt will no longer be the cool kid.

Decisions like this should be measured in opportunity cost, not opinions about how other development teams should go about developing. (no matter how strongly I actually agree and share your opinion) It takes so little to retain so much...

@shellscape
Copy link

hm. I find @shama 's argument, while probably of good intent and interesting, to be trite, shortsighted, and religious at best. I must disagree with it wholeheartedly. Individual philosophies for development cannot outweigh the real-world and practical need for a thing. There is clearly a need. So much so that github is littered with hacks and workarounds to this limitation. Other flavors of node-based task runners and build tools have disagreed with the local-only assertion as well. I find that curious.

@wesleytodd
Copy link
Author

@LongLiveCHIEF Stole the words out of my mouth, but said way more elegantly than I could have :). I am sad to see this conversation still active with no resolution from core grunt devs.

As a HEAVY user of grunt I can say that grunt is just a tool. If it gets the job done then great, but it doesn't need to be pure conceptually to get that job done.

....Or maybe we should all start looking at gulp.js ;) Yes competition has finally arrived for Grunt.

@shama
Copy link
Member

shama commented Feb 3, 2014

gulp is awesome. Please do use it. I do as well.

This entire issue is moot as there are many ways to install Grunt globally, one of which I just provided.

This is an open source project. I am merely a contributor voicing my opinion against a feature you're asking the Grunt team to provide support for.

@jamestomasino
Copy link

@shama There are indeed many workarounds. I think the idea here is to explain that there are valid use cases where people want this feature. Rather than blocking it completely, a recommendation for standard use would be the appropriate response. @cowboy 's earlier comment (from a year ago):

@tkellen it woud be awesome to have a page in the wiki where all you did was refute arguments people made about "needing" to install grunt globally.

Is a great indicator of a desire for a feature. Are many of those reasons ridiculous? Sure! And some are valid, too. Not everyone shares your environment or workflow or even freedom to decide these things. People work in closed systems, or with rigorous legal controls, or with things you haven't even considered. The only thing you know is, this is a desire from the community.

So, rather than continually dismissing it, or setting up a wiki page to refute every argument one at a time, how about you add a line to the wiki saying that this is not the intended use, and enable the feature so folks don't end up with 10,000 different hacks.

@vladikoff
Copy link
Member

From my personal experience installing modules globally in a multi-project environment never worked out well. With Grunt, Browserify or anything else. If there was a good way to run Grunt globally I would be all for it.

@sindresorhus
Copy link
Member

I fully support what @shama and @vladikoff said.

This is also not the place to discuss it. Grunt is just following Node.js best practices. If you don't like it take it up on the Node.js mailinglist. You'll hit the exact same issue with gulp too.

@cowboy
Copy link
Member

cowboy commented Feb 4, 2014

This is absolutely not a Grunt issue. We tried the whole global install thing for 0.3 and it was a disaster, we will ABSOLUTELY NOT try it again; I'm sure someone can dredge up links to all the issues around that if you don't believe me.

We've learned our lesson and are now trying to work within established Node.js best practices, while continuing to push boundaries where we can. Eg. having a separately-installable CLI instead of relying on npm or weird PATH contortions to run Grunt.

@shellscape
Copy link

A thanks to the maintainers for weighing on the issue again, and for making grunt's official position as a project very clear.

As has been proven time and time again, "best practices" don't always make the most business sense - what works in one bubble doesn't necessarily work in another. This now falls back onto the community using grunt to provide this option. If anyone could dredge up all of the old issues surrounding the global option, I'm sure that would aid in putting a global grunt/cli option together for public consumption.

We're already running an extension to grunt-cli internally which provides global grunt support. If anyone would like details on the implementation, please feel free to reach out to me directly. We'll make it public as we're able to.

@cowboy
Copy link
Member

cowboy commented Feb 4, 2014

@shellscape I recommend creating the abstraction you need at the npm-level, or better yet, use one of the npm module mirrors that @vladikoff suggested. Then your solution will work for every project that uses npm modules and not just Grunt projects.

@wjapp-dev
Copy link

Totally agree with @LongLiveCHIEF, @shellscape and @wesleytodd on this.

We are in the same position, a bunch of projects, a team of developers and we NEVER would want any project to be configured differently from any other and when we change anything the changes are made for every project at the same time.

In our case their is no use case for not having a global grunt, I think this is common for corporate dev teams, we have lots of projects but only one client, ourselves. Packages, versions everything you can mention would always be the same across every project.

@cowboy
Copy link
Member

cowboy commented Feb 11, 2014

FWIW, I'm unsubscribing from this thread, so I won't see further post notifications.

@tbull
Copy link

tbull commented Mar 5, 2014

Fixed. See #55.

@juliusakula
Copy link

I came here from google for grunt cli not finding gruntfile windows, and eventually I ran into a short checklist.

  1. npm install grunt to get it into node_modules, at the project level, (if only installed globally, something something No)
  2. within grunt file loadNpm('grunt-contrib-') task for each grunt task
  3. npm install grunt-contrib-* (each package involved with 2)
  4. within grunt file registerTask('default', []) set to a chronological list of tasks to be done
  5. Now the command 'grunt' works.

@shawnholt
Copy link

Wow - gulp npm install global vs. local is making this newbie bull his hair out!

@pravi
Copy link

pravi commented Nov 13, 2016

In debian we want the globally installed grunt to be used to build all packaged node modules (mainly to browserify them and run their tests). But I guess, the core developers are not going to implement this feature. Can anyone subscribed to this issue help me? Did anyone get it working?

I tried @tbull 's PR #55 but I get this error when running grunt,

$ grunt
Loading "Gruntfile.js" tasks...ERROR
>> Error: Unable to read "package.json" file (Error code: MODULE_NOT_FOUND).
Warning: Task "default" not found. Use --force to continue.

@pravi
Copy link

pravi commented Nov 13, 2016

This patch fixes the above problem. But not sure why that code snippet is failing.

@matamouros
Copy link

Yes, seems there's a lot of confirmation bias on this years old thread. We have a single app which is deployed to our servers, and crickey we need to run npm install on every deploy, on every server, just for the grunt toolchain, because grunt has as a requirement that it can't be used globally because reasons. Especially loved the guy saying that grunt is awesome and the whole thread is moot, because he definitely understands how everyone in the world is using this - and also understands a lot about CICD apparently.

I'm just seriously frustrated at having lost quite a few hours on streamlining our deployment process here, only to come to the realisation that I will have to always have an npm install on the root of our app because of this short-sighted design decision.

If anything think about it in terms of dependencies "for app to run" and dependencies "for app to build". The former should indeed be on a packages.json file to be executed on every deploy, as app dependencies required for the app to run can be loosely considered as an integral part of it. However, the latter (where grunt is) is part of the toolchain that builds the app. I most certainly don't expect gcc and all the toolchain around it to ship as part of the freaking C++ app - they exist globally to build it, and then they're out of the way once that's done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests