0

I am trying to figure out what criteria should be for a decision to 'inline' some work as a set of calls directly in a lets say Does clause (using aliases), or have a set of separate tasks with proper dependencies. It seems like it can be done in either way

For example

var target = Argument ("target", "build");

Task ("build")
  .Does (() =>
{
  NuGetRestore ("./source/solution.sln");
  DotNetBuild ("./source/solution.sln", c => c.Configuration = "Release");
  CopyFiles ("./**/*.dll", "./output/");
});

Task ("pack")
  .IsDependentOn ("build")
  .Does (() => 
{
  NuGetPack ("./solution.nuspec");
});

RunTarget (target);

I could 'inline' all of this right into 'pack' task, and I could have a separate task for each of nuget restore, dotnetbuild and copy files actions

2 Answers2

1

Unfortunately, the main answer to this is, it depends. It depends on your own preferences, and how you want to work.

Personally, I break Tasks into a concrete piece of functionality, or unit of work. So, in the above example, I would have a Task for:

  • NuGetRestore
  • DotNetBuild
  • CopyFiles
  • NuGetPack

The thought process here being that depending on what I wanted to do, I might want to only run one of those tasks, and I wouldn't want to do everything that was required. Breaking the Tasks into individual ones, gives me the option to piece these Tasks together as required.

If you put all the aliases into a single Task, you no longer have the option of doing that.

Gary Ewan Park
  • 17,610
  • 5
  • 42
  • 60
  • 1
    If you did separate tasks for NuGetRestore, CopyFiles etc, would you have a dependency written right into the task definition? Like, DotNetBuild depends on Restore? – Hennadii Omelchenko Jan 03 '18 at 13:13
  • Again, the answer is it depends :-) For simple scripts, yes, I would do this. However, I have also created scripts were the dependencies are set at runtime. The other way of doing it would be to have "meta" tasks, that group all the tasks that are required to perform the one complete piece of work. – Gary Ewan Park Jan 03 '18 at 13:16
1

Best practice is to have one task per step in your build process, an example flow could be:

  1. Clean
  2. Restore
  3. Build
  4. Test
  5. Pack
  6. Publish

Then it'll be much more clear what takes time and what's the cause of any failure.

Cake will abort on any failure so the flow will be the same, but it'll give you more granular control and insight.

There's a simple example solution at github.com/cake-build/example

Convertng your script according to that example would look something like this:

var target        = Argument("target", "Pack");
var configuration = Argument("configuration", "Release");
FilePath solution = File("./source/solution.sln");

Task("Clean")
    .Does(() =>
{
    CleanDirectories(new [] {
            "./source/**/bin/" + configuration,
            "./source/**/obj/" + configuration
    });
});

Task("Restore")
    .IsDependentOn("Clean")
    .Does(() =>
{
    NuGetRestore(solution);
});


Task("Build")
    .IsDependentOn("Restore")
    .Does(() =>
{
    if(IsRunningOnWindows())
    {
    // Use MSBuild
        MSBuild(solution, settings =>
            settings.SetConfiguration(configuration));
        }
    else
    {
        // Use XBuild
        XBuild(solution, settings =>
            settings.SetConfiguration(configuration));
        }
});

Task("Pack")
    .IsDependentOn("Build")
    .Does(() => 
{
    NuGetPack("./solution.nuspec", new NuGetPackSettings {});
});


RunTarget(target);

Which will give you a nice step by step summary report like this

Task                          Duration
--------------------------------------------------
Clean                         00:00:00.3885631
Restore                       00:00:00.3742046
Build                         00:00:00.3837149
Pack                          00:00:00.3851542
--------------------------------------------------
Total:                        00:00:01.5316368

If any step fails, it'll be much more clear which.

devlead
  • 4,935
  • 15
  • 36
  • What if I use cake for deploy pipeline stages, where things get much more complicated than simple build steps? I could have pretty high-level 'tasks' that then break down into lower-level calls for several levels. That's actually my context: I have to downloads files, then create place for them, configure it, do some other actions and so on. – Hennadii Omelchenko Jan 03 '18 at 13:19