gruntjsminimatch

using execution directory as Gruntfile's file base


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:


Solution

  • Here's the solution I came up with (H/T to @firstdoit, https://stackoverflow.com/a/28763634/356016):

    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;
    };