There are often times where I am developing a task at the end of a list of targets. During this temporary development I want to run the target frequently without running the targets it depends on.
Naturally I comment out the .IsDependentOn for the task under development. However I'd strongly prefer to be able to specify -Target X -SkipTarget Y -SkipTarget Z or something similar. I don't want to make any changes to the file on account of temporary development. This way I can commit as I make progress without forgetting to uncomment and recomment.
I'd also prefer not to build a hierarchy where Release depends on Test and ReleaseWithoutTest or introduce environment variables or any other kind of script boilerplate just for the sake of being able to temporarily skip a given target.
How about something like -Target x -SkipTargetDependencies or -SingleTarget x that would only run the specified target?
@frozenskys That would work for me as well. It's less conservative but simpler.
I have no objection to this. Would however prefer --skiptask.
At the moment this, would have to be a semicolon (or similar) separated string since we don't (at the moment) support multiple keys with the same name in the arguments.
So it would be something like:
> cake.exe --skip=foo;bar;qux;baz
Another approach to your problem would be an incremental build mechanism like the one implemented in Gradle (see: https://docs.gradle.org/current/userguide/more_about_tasks.html#sec:up_to_date_checks): a task can specify input files and output files and if they have not changed since the last run, the task is not executed. So, while developing a task at the end of a list of targets, dependent task would automatically be skipped. As a side effect - or main feature - this results is much faster builds during development.
Reading through the documentation (as a newbie), this would best be implementend as an extension of the existing "criteria" functionality. Pseudo code:
Task("B")
.WithCriteria(() => IncrementalBuildCriteria.Input("**/*.cs").Output("./obj").Build()))
.IsDependentOn("A")
.Does(() =>
{
});
Or even as a new mechanism
Task("B")
.WithInput("**/*.cs")
.WithOutput("./obj", "./bin")
.IsDependentOn("A")
.Does(() =>
{
});
@abeggchr It's a little awkward to talk about output of unit tests and integration tests though, isn't it? Skipping those is what's really motivating this for me.
The output of a unit or integration test would be the report file of the
corresponding test framework.
2016-11-14 13:54 GMT+01:00 Joseph Musser [email protected]:
@abeggchr https://github.com/abeggchr It's a little awkward to talk
about output of unit tests and integration tests though, isn't it? That's
what's really motivating this for me.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/cake-build/cake/issues/1341#issuecomment-260327661,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABioi-v61XNUhPFJeU879dvR-3XXOGLmks5q-FoigaJpZM4KojMb
.
Choose Facebook, Twitter, Instagram and hope that someone, somewhere cares.
I definitely think something like this needs to be supported. If you are running in a CI that naturally has pre-build, build, test and deploy phases, then you will typically want to single-target each of the corresponding tasks, while at the same time making it easy for local builds to run the whole thing with a single cmd.
I could use the same for example when using Jenkins Pipeline which has separate steps and there it would make sense to have different cake tasks for the different steps so that you see a time for each step and the current progress more easily in Jenkins.
Here's an example:
Let's say we have three tasks: build, test and package, where package has a dependency on test and test a dependency on build.
The Jenkins pipeline would look something like:
node() {
stage('build') {
bat 'cake build'
}
stage('test') {
bat 'cake test'
}
stage('package') {
bat 'cake package'
}
}
With this, Jenkins could correctly show the time for each stage and an estimated progress.
So either we would add the "-skip" to the test and package stage here or as an alternative, we can use conditions to define if a dependency should run or not. So we could for example define, that the build dependency of test should not run if the condition "IsCIBuild" is met. Unfortunately that seems to also not work yet according to #514.
Are there any other workarounds to solve this? I only could think of having separate tasks like "citest" and "cipackage" and such which just do not have the dependencies.
Another workaround for the moment would be to not use IsDependentOn but rather use RunTarget from inside other targets.
Task("Build")
.Does(() =>
{
// Build
});
Task("Test")
.Does(() =>
{
if (!isCiBuild) {
RunTarget("Build");
}
// Test
});
That also feels a bit hacky and it would be great to have something included in cake to solve this problem better.
@Roemer I "think" what you want is perfectly do-able today. You would need something like this:
var BuildTask = Task("Build")
.Does(() =>
{
// Build
});
var TestTask = Task("Test")
.Does(() =>
{
// Test
});
var PackageTask = Task("Package")
.Does(() =>
{
// Package
});
Then, you could do something similar to what is done in Cake.Recipe (the link that I sent you yesterday) where you create the IsDependentOn links at runtime. That way, when you are using Jenkins Pipeline, you call individually the required targets that don't have any dependencies. And then, when you are running locally, using say the Default Target, you stitch together the dependencies so that it works the way you want it to.
Thoughts?
You mean something like that:
var target = Argument("target", "Build");
var buildTask = Task("Build")
.Does(() =>
{
Information("Build");
});
var testTask = Task("Test")
.Does(() =>
{
Information("Test");
});
var packageTask = Task("Package")
.Does(() =>
{
Information("Package");
});
var isCi = Jenkins.IsRunningOnJenkins;
if (!isCi) {
testTask.IsDependentOn(buildTask);
packageTask.IsDependentOn(testTask);
}
RunTarget(target);
@Roemer sure, that should work.
I also have the same need, both because I want to run a single task in isolation while developing, just like @jnm2, and because I aim to invoke a single target from the CI/CD tool, like @petertiedemann .
@ale7canna and I are investigating with the following approach, which is far from being perfect, but may be a hint to someone more expert than us:
public static CakeTaskBuilder<T> CanRunAlone<T>(this CakeTaskBuilder<T> builder)
where T : CakeTask
{
return builder
.WithCriteria( (context) =>
{
return !context.HasArgument("only-this") ||
context.Argument("target", "Default") == builder.Task.Name;
});
}
Task("foo")
.CanRunAlone()
.IsDependentOn("bar")
.Does(() => { });
Task("bar")
.CanRunAlone()
.Does(() => { });
cake.exe --target foo
Task Duration
--------------------------------------------------
bar 00:00:00.0138528
foo 00:00:00.0008833
--------------------------------------------------
Total: 00:00:00.0147361
cake.exe --target foo --only-this
Task Duration
--------------------------------------------------
bar Skipped
foo 00:00:00.0120237
--------------------------------------------------
Total: 00:00:00.0120237
This works, but needs CanRunAlone to be added to each single dependency.
@arialdomartini I submitted a PR for this a while back (https://github.com/cake-build/cake/pull/2098) so hopefully you will be able to do this out of the box at some point 😄
@patriksvensson That's exactly what I was looking for. I think it would be useful to display this on the Dependencies page in the documentation.
Most helpful comment
I definitely think something like this needs to be supported. If you are running in a CI that naturally has pre-build, build, test and deploy phases, then you will typically want to single-target each of the corresponding tasks, while at the same time making it easy for local builds to run the whole thing with a single cmd.