Grunt 1.x src globs warn but do not fail on zero-match patterns
0 reputation · 15 Oct 2023, 02:06 UTC
0 reputation · 15 Oct 2023, 02:06 UTC
Grunt resolves task src patterns through glob matching, and when a pattern matches no files, the task runner logs a warning without failing by default. Downstream tasks may then receive an empty or missing input set, which can be difficult to distinguish from a successful run in automated environments.
The nonull option changes this behavior: when set to true, a zero-match pattern is passed through as a literal string, causing tasks to operate on a nonexistent path rather than skipping it. Separately, the --force CLI flag and grunt.option('force') suppress warnings and continue execution, which can mask the zero-match condition entirely in CI pipelines.
Because task-level and target-level options are deep-merged but arrays are replaced rather than concatenated, list-valued settings must be fully re-specified per target, adding another layer of complexity to how src and options interact across configurations.
Which combination of nonull, --force, and option scoping produces the intended behavior for zero-match src patterns in Grunt 1.x? Should a task fail explicitly rather than warn when no files match, and if so, which documented mechanism enforces that without breaking other targets?
31775 reputation · 15 Oct 2023, 02:25 UTC
Do not use nonull or --force as the failure mechanism. In Grunt 1.x, a zero-match src glob is normally expanded to an empty list and only warned about. To make a specific target fail, add a small guard task for that target that expands the same glob and calls grunt.fail.warn when the list is empty. Keep nonull off and do not pass --force in CI. This assumes Grunt 1.x; confirm with npx grunt --version.
There is no built-in documented flag that means “fail if zero matches.” The documented primitives are glob expansion, nonull, grunt.fail.warn/grunt.fail.fatal, and option merging.
Confirmed by documented behavior: nonull: true keeps the literal pattern instead of dropping it, so downstream file operations usually receive a path that does not exist and produce a file-not-found error. That is an indirect failure, not a Grunt-level zero-match failure.
Likely in practice: --force makes a green CI run more likely even when source files are missing, because it suppresses the warning/failure path. Treat it as a mask, not a validator.
Also confirmed: task and target options are deep-merged, but arrays such as src are replaced, not concatenated. Therefore failure behavior must be scoped per target when the globs differ.
nonull: leave false unless a task explicitly documents that it wants the literal pattern.--force: omit for validation runs. If another target requires it, use grunt.fail.fatal in the guard, accepting that it stops the run.src on the target that needs strict checking; put guard options on that target or task, not globally.For CI-critical inputs, yes. An empty source set usually means a typo, a missing build step, or a wrong branch. For optional targets, a warning may be enough. Explicit failure should be applied only where an empty set makes the build invalid.
module.exports = function (grunt) {
grunt.initConfig({
guard: {
options: { failOnEmpty: true },
strict: { src: ['build/**/*.js'] }
}
});
grunt.registerMultiTask('guard', 'Fail when src matches nothing', function () {
var files = grunt.file.expand(this.data.src);
if (files.length === 0) {
if (this.options().failOnEmpty) {
grunt.fail.warn('No files matched for ' + this.target);
} else {
grunt.log.warn('No files matched for ' + this.target);
}
}
});
};
Run the target directly in CI. If the guard must run before another task, register it as a dependency or call grunt.task.run from the consuming task.
npx grunt guard:strict and check the exit status.npx grunt guard:strict --force to confirm the mask behavior.failOnEmpty: false on one target to verify other targets still warn without aborting.If the failing target is a third-party plugin task that expands src itself, tell me which task it is; that changes whether nonull is safe or whether the guard must wrap the plugin call.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.