17

I'm trying to run a npm command inside of gradle task but I'm getting a strange error:

Caused by: net.rubygrapefruit.platform.NativeException: Could not start 'npm'
    at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:27)
    at net.rubygrapefruit.platform.internal.WrapperProcessLauncher.start(WrapperProcessLauncher.java:36)
    at org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.java:65)
    ... 2 more
Caused by: java.io.IOException: Cannot run program "npm" (in directory "/Users/psilva/Documents/projects/registrolivre"): error=2, No such file or directory
    at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:25)
    ... 4 more
Caused by: java.io.IOException: error=2, No such file or directory

And this is my task:

task npmInstall(type: Exec) {
    commandLine "npm", "install"
}

Could someone help?

Pedro Henrique
  • 609
  • 2
  • 9
  • 26

5 Answers5

12

If you are on Windows try this:

task npmInstall(type: Exec) {
    commandLine "npm.cmd", "install"
}

instead of this:

task npmInstall(type: Exec) {
    commandLine "npm", "install"
}
Prashant Gupta
  • 788
  • 8
  • 26
Vikash Madhow
  • 1,287
  • 11
  • 15
  • This worked for me. I had to create `.npmrc` file on the project root though to ignore the `strict-ssl`. – Ashok M A Oct 01 '18 at 12:57
7

If you are using Windows OS, you have to use 'npm.cmd' instead of 'npm'. Better to detect whether OS is windows or not and build your npm command. Please see the code snippet below,

import org.apache.tools.ant.taskdefs.condition.Os

task npmInstall(type: Exec) {
    String npm = 'npm';
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        npm = 'npm.cmd'
    }
    workingDir 'src/main/webapp'
    commandLine npm, 'install'
}
Aldrin
  • 2,036
  • 15
  • 12
6

This answer worked for me with a different npm-related task. The recommendation there is to use an executable and args rather than commandLine.

executable 'npm' args ['install']

Depending on your directory structure, you may also need to add the workingDir property and set it to the directory where your package.json lives.

As an alternative, the Gradle Node Plugin is also really handy for managing the most common Node tasks in a Gradle build. I use this plugin as the basis for my Node tasks and then create other custom tasks as needed.

Community
  • 1
  • 1
Taylor714
  • 2,876
  • 1
  • 15
  • 16
  • I had the same problem with IntelliJ and Gradle. The [Gradle Node Plugin](https://github.com/srs/gradle-node-plugin) referred in this answer solved my integration problem and cleaned a bit npm related tasks too. – iaarnio Apr 21 '17 at 07:59
  • Using the plugin fixed the problem for me too. Perhaps just running it as an exec task doesnt see npm. Since npm is installed for you by the plugin, it works. Just a guess. Thanks! – Clark Battle Aug 03 '21 at 00:52
  • How to pass install --force in args??? – Sritam Jagadev May 15 '23 at 10:44
2

If you are using IntelliJ and npm is installed using nvm, check this Q&A

Pablo
  • 1,604
  • 16
  • 31
0

I used @ALDRIN P VINCENT answer to solve this issue. But if you need to pass command line arguments to npm script, you can do this:

Let's say following system properties are passed to gradle script

gradle test-Dsome1=dev -Dsome2=https://www.google.com

In your test script in build.gradle, you will do this:

task apifunctionaltest(type: Exec) {
String npm = 'npm';
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
    npm = 'npm.cmd'
}
commandLine npm, 'run', 'test', '--', '--some1='+System.getProperty("some1"), '--some2='+System.getProperty("some2")

}

The main command starts with commandLine npm… This line equates to:

npm run test -- --some1=dev --some2=https://www.google.com

The test script in package.json also should have ‘npm install’ (it depends) command so node modules are installed before tests run. And if modules are already installed, node will not waste time and reinstall them. test script should be something like this:

"scripts": {
    "test": "npm install && webpack"
  }

And then you can pick those command line args thru process.argv[2] and process.argv[3].

If you have a simple script like mine, then some1 and some2 will be in the 2nd and 3rd position of an array, respectively.

Faraz
  • 6,025
  • 5
  • 31
  • 88