Open explunit opened 11 years ago
I second this request. Also, when a task iterates over files, it would be nice to have an option to execute it on the next file when one fails.
Sounds great. I might have an alias for other tasks, some of which are allowed to fail without failing the mother task.
Something like this would be good for me. There probably is a better syntax though.
grunt.registerTask('test', ['jshint --force', 'karma:test']);
The karma task would have force off unless I run the mother task with --force
grunt test --force
+1
btw, @explunit a bit of an improvement to the hack while we wait for this to land:
var previous_force_state = grunt.option("force");
grunt.registerTask("force",function(set){
if (set === "on") {
grunt.option("force",true);
}
else if (set === "off") {
grunt.option("force",false);
}
else if (set === "restore") {
grunt.option("force",previous_force_state);
}
});
// .....
grunt.registerTask("foobar",[
"task1",
"task2",
"force:on", // temporarily turn on --force
"task3", // will run with --force in effect
"force:restore",// restore previous --force state
"task4"
]);
+1
Proposed solutions don't work in grunt-contrib--watch
. Although this may be handled in that task.
EDIT:
It is not inherited by watch task, but it is possible to add it to the watch target's tasks list.
There is also https://npmjs.org/package/grunt-continue.
May be force
also should be a task-level option like files
, then we can configure it with some task, not only a global setting:
grunt.initConfig({
concat: {
foo: {
files: {
'dest/a.js': ['src/aa.js', 'src/aaa.js'],
'dest/a1.js': ['src/aa1.js', 'src/aaa1.js'],
},
force: true,
},
bar: {
files: {
'dest/b.js': ['src/bb.js', 'src/bbb.js'],
'dest/b1.js': ['src/bb1.js', 'src/bbb1.js'],
},
force: false,
},
},
});
Issue was opened 7 months ago, and the pull request (https://github.com/yaymukund/grunt-simple-mocha/pull/36) addresses it. Has this been considered by the core contributors?
Currently set milestone target is 0.4.3. Which is the next release, so we shall look at this.
Outstanding. Thanks for getting eyes on this @vladikoff
We have looked at this and discussed some syntax options.
Something like ['jshint --force',...
is not applicable. There are a lot of task running cases to look into, we shall revisit this again in 0.4.4.
If anyone has more suggestions on how this force option may be defined. For example, should it part of the alias task definition? or anywhere else? Let us know.
@vladikoff
Something like ['jshint --force',... is not applicable
Can you elaborate on why that's not an option?
Something like ['jshint:force', ...]
could create unfortunate overlap with task parameters, I understand. But --force
seems unique enough (non-param syntax) to easily be able to be parsed out ahead of time. Can you help us understand why it's not applicable or feasible?
What about the inverse, like ['force:jshint', 'bar', 'force:bar']
, where force
was treated like a pre-defined virtual task that does something similar to what I showed in my snippet above, perhaps like:
grunt.registerTask("force",function(task){
var previous_force_state = grunt.option("force");
grunt.option("force",true);
grunt.runTask(task); // ??? is that how you run tasks?
grunt.option("force",previous_force_state)
});
That way, wherever you have the ability to specify a task, if you want to force it, you just say "force: ..." to force it, or "..." to not force it. Would that work?
@getify unfortunately, task names can be any arbitrary string. By giving the substring --force
a special meaning it could cause compatibility issues. Technically. Unlikely, though.
Either way, it feels more like a band-aid than a real solution, because I can think of scenarios where the --force
solution would be inadequate or where a more expressive solution might be desired.
For example, what if you have tasks a, b and c and you want b to not run if a fails, but you want c to run, regardless of the success of a or b.
I dunno.
For example, what if you have tasks a, b and c and you want b to not run if a fails, but you want c to run, regardless of the success of a or b.
To expand on that, we were talking about syntax solutions for this:
grunt.registerTask("build",['a','b','c']);
- if 'a' fails then 'b', 'c' will not run
grunt.registerTask("build",['a->b,c']);
- if 'a' fails then 'b' doesn't run, 'c' will still run (see how the arg is a single string)
oh please don't add a custom set of syntax where none is needed. there's already a convention in Javascript which could be used for that kind of notation:
grunt.registerTask("build",['a','b','c']);
- if 'a' fails then 'b', 'c' will not run
grunt.registerTask("build",[['a','b'],'c']);
- if 'a' fails then 'b' doesn't run, 'c' will still run
['a', 'b']
is clearly a grouping, doesn't require any understanding of special characters or syntax, and follows the same ordering convention that's been in grunt, and unless it's used internally (that notation isn't in any documentation I could find) it should be open for use.
That would only require the introduction of a config option to force, or not to force. Or what to force, specifically. If you wanted to get nuts:
- force all (default)
- force none
- force only grouped tasks
- force only ungrouped tasks
+1 I agree with @shellscape on the nesting thing. And I still think ["force:a","b"],"c",["d","force:e","f"]
serves the important use-cases. That example would say:
what use cases would that be missing?
@getify that misses 1 use case: if 'a' fails, do we even want to try running 'b', same with e/f
I think I prefer @shellscape's idea (disclaimer: @shellscape is a coworker). Anything in a sub-group is essentially, a sub-grunt that succeeds or fails atomically, and doesn't affect the parent group.
I like the prepending format, but what about using something like !
instead? ["a","!b", "c"], although that may cause some confusions with the different meaning in globbing patterns.
@shellscape could you explain all four "force" options? By "default" do you mean the current behavior?
Yeah "(default)" got put in the wrong place. Thanks for catching that. By no means set in stone, but off the cuff was thinking:
- force all
- all tasks are forced, all continue regardless of result.
- force none (default)
- current behavior.
- force only grouped tasks
- only grouped tasks would be forced. ungrouped tasks would run with the current behavior
- force only ungrouped tasks
- only tasks which were not grouped would be forced. would allow for an inverse setup eg. grunt.registerTask("build",[''c', ['a','b']]);
where task c would only be forced.
This was just off the cuff, to add to the discussion. The primary concern was logical grouping over syntax annotations.
@kmdavis
that misses 1 use case: if 'a' fails, do we even want to try running 'b', same with e/f
If you want b to only run if a succeeds, then:
[["a","b"],"c"...
or even just ["a","b","c"...
If you want the group ["a","b"]
to be itself optional (aka forced), then no, my suggestion doesn't handle that. But what's actually a real (not just theoretical) example of such a use case? If the group failed, it would seem logical that the whole chain fails. I can only see in theory the need for "optional (aka forced) groups". Seems like it'd be over-architecting to solve that "optional-group" use-case unless there was a concrete example of such.
@getify ok... real use case (please sign NDA here, here, and here, and submit in triplicate...)
In our legacy system (that we're converting over to grunt) we have some tasks that have Soft dependencies. A specific example would be linting. Linting is very nice, and we scream loudly if you fail linting... but we don't actually Stop anything that has a soft dependency on linting. We have a couple other things that are soft dependencies, like code coverage, complexity analysis, generating docs, etc. All things that are non-Essential.
Other things ARE essential. Like syntax checking, compilation, specs, etc. Sometimes, the soft deps are interspersed with the hard deps.
Example: When we run our spec task, it also runs npm install, compilation, docs, linting, syntax checking. Using @shellscape's proposed syntax, that'd look something like this:
grunt.registerTask('spec', [
'check-syntax',
[
'jshint',
'gilt-special-linting',
'complexity',
'groc'
],
'compile',
'npm-install',
'karma'
]);
@kmdavis
wouldn't this be the same thing (unless I'm missing something)?
grunt.registerTask('spec', [
'check-syntax',
'force:jshint',
'force:gilt-special-linting',
'force:complexity',
'force:groc'
'compile',
'npm-install',
'karma'
]);
To put it more succinctly, I am having trouble imagining a scenario (in the real world) like:
@getify yes, essentially they're two ways to say the same thing. I was going with the array-grouping notation because of the proposal for additional custom syntax and concerns earlier in the thread about using 'force' as a keyword in any sense. (eg. imagine someone silly writing a starwars grunt task named 'force' -> 'force:use')
We're all in agreement about the gist of the need and seemingly how it should be roughly notated. What we need now is weigh in from the people who make the decisions (@cowboy, @vladikoff) on what sits best with them. I'm good with either array grouping or making 'force:' a reserved word. I believe we are monkey-patching my proposal soonish here, and will likely submit a pull request to add to the conversation.
@shellscape agreed, for the most part.
We're inventing new "syntax" to patch a gap in functionality, not inventing a new syntax to cover every possible niche use-case. IMO the former dictates a minimal syntax for covering demonstrable/common use-cases, not a sugared syntax that is broadly capable.
That's the only reason why I was urging a simpler option than the one your proposed, to see if the simpler option (usually better) covered enough of the real-world stuff and restrained itself on the theoretically "nice" stuff which won't really get much bang for the buck.
I'm definitely not going to build-in a force:
prefix, but you should be able to create a custom task that does just that. I encourage you to create it and give it a try.
I am, however, very interested in a more general solution, like what @shellscape suggests, as long as we can't poke any big holes in it.
:+1: to a grunt --force
option, in addition to something like the inverse grouping example grunt.registerTask("build",[''c', ['a','b']])
@shellscape mentioned; where grouped tasks would be considered dependent on each other, and so should not be 'forced'. Unless you really, really wanted to force those tasks anyway, in which case I suppose a grunt --force=all
would do the trick.
Whatever the solution here, I'd like you to consider a related, pretty important aspect: The exit code. Currently, setting the force option on tasks that support it will cause grunt to exit with a zero status code, even when one or more forced tasks had errors.
My usecase is pretty simple: Run all tasks, but exit with non-zero status code if anything failed. That way I'd get the most out of Travis builds, where a trailing comma can be printed as an error in the jshint task and causes the build to fail, but it would still run the unit tests.
fwiw we've been using the solution that @kmdavis outlined for four months now and it's been easy as all hell to use and grok, and haven't run into any negative side effects given heavy use of the construct.
I agree with @jzaefferer, forcing the task should still make the whole process exit with code different than 0.
@shellscape what solution are you referring to there?
@gausie this one https://github.com/gruntjs/grunt/issues/810#issuecomment-33385633
however, we've since moved onto gulp as it made more sense for our needs.
but isn't that comment just a recommendation for a syntax?
I have published a grunt task which enable the force mode for a specific task: grunt-force-task. It's easy to use and doesn't need any configuration. For example force:jshint
.
At the moment I have one untested use case: Some tasks are executed parallel. But first it's works for me.
@jzaefferer @mzgol Agreed, there needs to be an option continue build (with grouping or --force
or whatever) but still carry through the non-zero exit code from intermediary steps so that the final exit code is also non-zero. This should be optional. Having it could solve the use case in #1114. Are there any other approaches to try
/catch
/finally
error handling per-task in Grunt?
Thanks @floriangosse. Your force-task works like a champ.
@floriangosse +1 grunt-force-task
@floriangosse +1 grunt-force-task works great!!
@getify @floriangosse Another +1 for grunt-force-task ... worked as expected. Found it easier to understand than the grouped arrays. Seems more explicit in its use than having force implicitly called based on array structure.
@getify thanks for the workaround. plus one with the others.
+1
+1
I see that several plug-ins have added a force option, for example: https://github.com/gruntjs/grunt-contrib-jshint#force https://github.com/gruntjs/grunt-contrib-clean#force
But it would be useful to have a general-purpose way of doing this at the grunt level. Here's what I'm currently doing for a workaround:
Is there a better workaround? If not, would you consider adding a feature for this?