How to run a command in child process in grunt tasks? - gruntjs

I want to write a grunt task, which will start a server, and run some tests based on that server:
grunt.initConfig({
shell: {
sbtRun: {
options: {
stdout: true
},
command: './sbt run'
}
}
});
grunt.loadNpmTasks('grunt-shell');
grunt.registerTask('run-test-only', ...);
grunt.registerTask('start-server-and-test', ['shell:sbtRun', 'run-test-only']);
But the problem is, the task ./sbt run is not running in daemon. When I run:
grunt start-server-and-test
It will blocking in the shell:sbtRun task forever.
Is there any way to start it in a child process? So the second task run-test-only will be called, and the server will be destroyed automatically after testing?

I was facing a similar issue. I wanted to connect to a database and store the result of a query in a .csv. I created a separate file to do all that work and I was successful in running that file through the command line using:
node filename.js
I used grunt-shell and grunt-exec to run this command but everytime I saw the same error:
const child = require('child_process').exec;
Then, I found another grunt plugin i.e grunt-execute which was able to create a child process and the task was completed successfully. You could find more about grunt-execute here, https://www.npmjs.com/package/grunt-execute.
Hope this helps.

Related

Grunt error task "default" not found

When trying to run grunt, I get an error message:
Warning: Task "default" not found. Use --force to continue.
Aborted due to warnings.
I have already found several posts on this topic, and in each of them the problem was a missing comma. But in my case I have no idea what's wrong, I think I didn't miss any comma (btw, this content was copy/pasted from the internet).
module.exports = (grunt) => {
grunt.initConfig({
execute: {
target: {
src: ['server.js']
}
},
watch: {
scripts: {
files: ['server.js'],
tasks: ['execute'],
},
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-execute');
};
What could be the problem?
You didn't registered the default task. Add this after the last loadNpmTask
grunt.registerTask('default', ['execute']);
The second parameter is what you want to be executed from the config, you can put there more tasks.
Or you can run run existing task by providing the name as parameter in cli.
grunt execute
With you config you can use execute and watch. See https://gruntjs.com/api/grunt.task for more information.
If you run grunt in your terminal it is going to search for a "default" task, so you have to register a task to be executed with Grunt defining it with the grunt.registerTask method, with a first parameter which is the name of your task, and a second parameter which is an array of subtasks that it will run.
In your case, the code could be something like that:
...
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-execute');
grunt.registerTask("default", ["execute", "watch"]);
...
In this way the "default" task will run rispectively the "execute" and the "watch" commands.
However here you can find the documentation to create tasks with Grunt.
Hope it was helpful.

Can you use the --verbose flag for individual Grunt tasks?

Here's an example GruntFile for a "clean" task (using the grunt-contrib-clean plugin):
clean: {
dry: {
src: ["build/css"],
options: {
'no-write': true
}
}
}
Running grunt clean:dry would output:
Running "clean:dry" (clean) task
>> 2 paths cleaned.
Done, without errors.
Using grunt clean:dry -v, gives me what I want:
Running "clean:dry" (clean) task
Not actually cleaning live/css...
Not actually cleaning live/js...
...but it also displays a bunch of configuration logs that have nothing to do with the current task. Can I use the --verbose flag (or something else) to show the full output of a task without having to scroll through all of the non-related config logs?
PS: My other plugins suffer from the same problem, displaying only a single line of output when their documentation indicates that I should expect more.
(Related questions: Logging from grunt-contrib-jasmine and How can I force JSHint running in grunt to always use the --verbose flag do not answer this question).
There are some insights into this.
grunt.initConfig({
verbosity: {
default: {
options: { mode: 'dot' }, // normal, oneline, dot, hidden
tasks: ['groundskeeper', 'requirejs']
}
}
grunt.registerTask( '_start', ['verbosity:default', 'projectInfo'] );

WebDriver + Protractor with grunt

I'm trying to run end-to-end tests with WebDriver and Protractor. No problem when I run it manually with:
webdriver-manager start
and then
protractor test-UI/e2e/conf.js
Now I would like to launch them from a grunt command, so I tried with grunt-shell, joining them with '&&'. But as WebDriver waits, tests are never started. Did someone try this before?
Thanks.
There is a fork of Grunt-shell called Grunt-shell-spawn (Github Repo) which allows you to run background processes asynchronously. This happens to work very well with starting the selenium webdriver server helping to automate the protractor testing process. There are a few grunt plugins specifically for starting the webdriver server but from my experience they all have small bugs that cause errors once the tests are finished or require you to mark a flag keepAlive: true which means it will not kill the webdriver server process forcing you to ctrl+c or close and re-open the command prompt which can cause a lot of issues when devs are using the functional tests and with continuous integration (CI) servers. Grunt-shell-spawn has the ability to kill the process as you can see at the end of my 'test' task which is really invaluable for maintaining consistency and ease of use.
'use strict';
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-shell-spawn');
grunt.loadNpmTasks('grunt-protractor-runner');
var path = require('path');
grunt.initConfig({
...
...
...
shell: {
updateserver: {
options: {
stdout: true
},
command: "node " + path.resolve('node_modules/protractor/bin/webdriver-manager') + ' update --standalone --chrome'
},
startserver: {
options: {
stdout:false,
stdin: false,
stderr: false,
async:true
},
command: 'node ' + path.resolve('node_modules/protractor/bin/webdriver-manager') + ' start --standalone'
},
});
grunt.registerTask('test',[
'shell:updateserver',
'shell:startserver',
'protractor:e2e',
'shell:startserver:kill'
]);
You can to install grunt-protractor-runner
npm install grunt-protractor-runner --save-dev
Check this blog with details
http://www.codeorbits.com/blog/2014/01/26/angularjs-end-to-end-testing-with-protractor-easy-set-up-with-yeoman/
Try running grunt --verbose to see more details on whats happening.

Grunt-open: Spawn ENOENT

I keep getting "Warning: Spawn ENOENT" problem when I am running grunt-open.
My setup
I have all my project files on Google Drive.
I am doing my development on the files directly on them (using Google Drive desktop).
I just want to open the index.html file when I run grunt. Just that simple.
Part of my Gruntfile.js
open: {
all: {
path : 'index.html'
}
},
But I couldn't get it working? What am I missing?
I have figured out.
You have to change your system environment variable to include the following if on PC.
%SystemRoot%\system32;
I had similar problem for grunt-run task:
run: {
jasmine: {
cmd: 'jasmine-node.cmd',
args: ['--autotest', '--test-dir', 'test']
}
},
You have to specify jasmine-node.cmd as cmd - not just jasmine-node which is enough when running from command line.

Grunt uglifym - call stack size exceeded

I am trying to use uglify with grunt to concat and minify some files. I have already used the npm to install grunt-contrib-uglify.
I have the following in my grunt.js file: (I have removed some other tasks for anonymity)
module.exports = function(grunt) {
'use strict';
grunt.loadNpmTasks('grunt-contrib-uglify');
uglify: {
options: {
sourceMap: 'app/map/source-map.js'
},
files: {
'app/dist/sourcefiles.min.js': [
'app/test_js/test.js'
]
}
}
};
I then run:
grunt uglify
but I keep getting the following error:
Warning: Maximum call stack size exceeded Use --force to continue.
If I use force, the grunt task never stops running.
Can someone tell me where I am going wrong? I am tearing my hair out on this one.
I had the same problem, using an other Grunt plugin called recess.
The error message was not explicit.
Warning: Cannot read property 'message' of undefined Use --force to continue.
But the verbose mode showed that my task was called hundred of times.
The problem was that I created a "cyclic dependency" (causing an infinite loop) when I registered my task.
grunt.registerTask('recess', ['recess']); //does not work => cyclic dependency!
The first parameter of registerTask method is an "alias task" and has to be different from the task names defined in the second parameter.
I corrected like this:
grunt.registerTask('my-recess-task', ['recess']);
And I runned the task calling this (in the Command prompt window)
grunt my-recess-task
And then it was OK!
More about registerTask() method, from grunt API:
http://gruntjs.com/api/grunt.task#grunt.task.registertask
I also met this problem, i solved this by removing
grunt.registerTask('uglify', ['uglify']);
before i solved this, i ran grunt uglify -v to check what happend.
I found it because that where you using this grunt.loadNpmTasks('grunt-contrib-uglify'); ,it implicitly executes the grunt.registerTask('uglify', ['uglify']); ^_^

Resources