Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When running multiple targets, common dependent tasks are executed twice #4324

Open
2 tasks done
CharliePoole opened this issue Aug 11, 2024 · 1 comment
Open
2 tasks done

Comments

@CharliePoole
Copy link

CharliePoole commented Aug 11, 2024

UPDATED to provide a simple repro

Prerequisites

  • I have written a descriptive issue title
  • I have searched issues to ensure it has not already been reported

Cake runner

Cake .NET Tool

Cake version

4.0.0

Operating system

Windows

Operating system architecture

64-Bit

What are you seeing?

When running tests for the NUnit console runner with arguments --target=Test --target=Package the Build target is run twice, once before Test and once before Package. Build is, of course, a dependency of both targets.

I would expect the dependent target to run only once

NOTE: This appears to be related to #4066.

Steps to Reproduce

Use the following script:

var targets = Arguments<string>("target", "A");

Task("A")
	.Does(() => Information("Running A"));

Task("B")
	.IsDependentOn("A")
	.Does(() => Information("Running B"));

Task("C")
	.IsDependentOn("A")
	.Does(() => Information("Running C"));

RunTargets(targets);

Run using arguments --target=B --target=C

This produces the following output:

========================================
A
========================================
Running A

========================================
B
========================================
Running B

========================================
A
========================================
Running A

========================================
C
========================================
Running C

Task                          Duration
--------------------------------------------------
A                             00:00:00.0060125
B                             00:00:00.0003280
A                             00:00:00.0001377
C                             00:00:00.0001879
--------------------------------------------------
Total:                        00:00:00.0066661
@CharliePoole
Copy link
Author

CharliePoole commented Aug 11, 2024

@devlead I modified a version of the above to use similar code to what you proposed in 2022 as a workaround. That code, as expected, runs A B and C in sequence.

Here's the updated script:

var targets = Arguments<string>("target", "A");

Task("A")
	.Does(() => Information("Running A"));

Task("B")
	.IsDependentOn("A")
	.Does(() => Information("Running B"));

Task("C")
	.IsDependentOn("A")
	.Does(() => Information("Running C"));

RunTargets(targets); // This fails, running A twice
//MyRunTargets(targets); // This succeeds, running A only once

CakeReport MyRunTargets(ICollection<string> targets)
    => RunTarget(GetOrAddTargetsTask(targets).Name);

Task<CakeReport> RunTargetsAsync(ICollection<string> targets)
    => RunTargetAsync(GetOrAddTargetsTask(targets).Name);

private ICakeTaskInfo GetOrAddTargetsTask(ICollection<string> targets)
{
    var targetsTaskName = string.Join(',', targets);
    var targetsTask = Tasks.FirstOrDefault(
        task => task.Name == targetsTaskName
    );
    if (targetsTask == null)
    {
        var task = Task(targetsTaskName);
        foreach(var target in targets)
        {
            task.IsDependentOn(target);
        }
        targetsTask = task.Task;
    }
    return targetsTask;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant