I'm trying to use Grunt to clean up a large project. For this specific example, I am trying to run unit tests and want to do so only for paths under the current grunt
execution directory (i.e., the result of pwd
).
I want one Gruntfile at the project root. I know grunt
will find and execute this with no problem from any subdirectory. If I define my test runner options to look in "test/"
, it only runs tests under {project root/}test/
. Is there a way to tell a project-level Gruntfile to make its paths (in all or in part) relative to the executing location?
Notes:
"**/test/"
isn't the answer, because I want only the tests under the current grunt
execution directory.--base
also won't work, because Grunt will look for the Node packages at the base location.grunt.config.merge(grunt.file.readJSON("../grunt-shared.json"));
. However, that requires Gruntfiles in subfolders, as well as a hard-coded path to the shared file (e.g., ../
), which seems tenuous.Here's the solution I came up with (H/T to @firstdoit, https://stackoverflow.com/a/28763634/356016):
Gruntfile.js
.node_modules
source.Gruntfile.js
/**
* This Gruntfile is largely just to establish a file path base for this
* directory. In all but the rarest cases, it can simply allow Grunt to
* "pass-through" to the project-level Gruntfile.
*/
module.exports = function (grunt)
{
var PATH_TO_ROOT = "../";
// If customization is needed...
// grunt.config.init({});
// grunt.config.merge(require(PATH_TO_ROOT + "grunt-shared.js")(grunt));
// Otherwise, just use the root...
grunt.config.init(require(PATH_TO_ROOT + "grunt-shared.js")(grunt));
};
Using a var
for PATH_TO_ROOT
is largely unnecessary, but it provides a single focus point for using this boilerplate file across sub-projects.
{ROOT}/grunt-shared.js
module.exports = function (grunt)
{
// load needed Node modules
var path = require("path");
var processBase = process.cwd();
var rootBase = path.dirname(module.filename);
/*
* Normally, load-grunt-config also provides the functionality
* of load-grunt-tasks. However, because of our "root modules"
* setup, we need the task configurations to happen at a different
* file base than task (module) loading. We could pass the base
* for tasks to each task, but it is better to centralize it here.
*
* Set the base to the project root, load the modules/tasks, then
* reset the base and process the configurations.
*
* WARNING: This is only compatible with the default base. An explicit base will be lost.
*/
grunt.file.setBase(rootBase);
require("load-grunt-tasks")(grunt);
// Restore file path base.
grunt.file.setBase(processBase);
// Read every config file in {rootBase}/grunt/ into Grunt's config.
var configObj = require("load-grunt-config")(grunt, {
configPath: path.join(rootBase, "grunt"),
loadGruntTasks: false
});
return configObj;
};